并行库充分利用多核的优势,通过并行运算提高程序效率,本文主要介绍c++中两个知名的并行库,一个是intel开发的TBB,一个是微软开发的PPL。本文只介绍其基本的常用用法:并行算法和任务。

TBB(Intel® Threading Building Blocks )

TBB是intel用标准c++写的一个开源的并行计算库。它的目的是提升数据并行计算的能力,可以在他的官网上下载最新的库和文档。TBB主要功能:

    1. 并行算法
    2. 任务调度
    3. 并行容器
    4. 同步原语
    5. 内存分配器

TBB并行算法

parallel_for:并行方式遍历一个区间。

parallel_for(, , [](int i){cout << i << endl; });
parallel_for(blocked_range<size_t>(, ), [](blocked_range<size_t>& r)
{
for (size_t i = r.begin(); i != r.end(); ++i)
cout << i << endl;
});

parallel_do和parallel_for_each:将算法应用于一个区间

vector<size_t> v;
parallel_do(v.begin(), v.end(), [](size_t i){cout << i << endl; });
parallel_for_each(v.begin(), v.end(), [](size_t i){cout << i << endl; });

 parallel_reduce

  类似于map_reduce,但是有区别。它先将区间自动分组,对每个分组进行聚合(accumulate)计算,每组得到一个结果,最后将各组的结果进行汇聚(reduce)。这个算法稍微复杂一点,parallel_reduce(range,identity,func,reduction),第一个参数是区间范围,第二个参数是计算的初始值,第三个参数是聚合函数,第四个参数是汇聚参数。

float ParallelSum(float array [], size_t n) {
return parallel_reduce(
blocked_range<float*>(array, array + n),
.f,
[](const blocked_range<float*>& r, float value)->float {
return std::accumulate(r.begin(), r.end(), value);
},
std::plus<float>()
);
}

这个对数组求和的例子就是先自动分组然后对各组中的元素进行聚合累加,最后将各组结果汇聚相加。

parallel_pipeline:并行的管道过滤器

  数据流经过一个管道,在数据流动的过程中依次要经过一些过滤器的处理,其中有些过滤器可能会并行处理数据,这时就可以用到并行的管道过滤器。举一个例子,比如我要读入一个文件,先将文件中的数字提取出来,再将提取出来的数字做一个转换,最后将转换后的数字输出到另外一个文件中。其中读文件和输出文件不能并兴去做,但是中间数字转换的环节可以并行去做的。parallel_pipeline的原型:

parallel_pipeline( max_number_of_live_tokens,
make_filter<void,I1>(mode0,g0) &
make_filter<I1,I2>(mode1,g1) &
make_filter<I2,I3>(mode2,g2) &
...
make_filter<In,void>(moden,gn) );

  第一个参数是最大的并行数,我们可以通过&连接多个filter,这些filter是顺序执行的,前一个filter的输出是下一个filter的输入。

float RootMeanSquare( float* first, float* last ) {
float sum=;
parallel_pipeline( /*max_number_of_live_token=*/,
make_filter<void,float*>(
filter::serial,
[&](flow_control& fc)-> float*{
if( first<last ) {
return first++;
} else {
fc.stop();
return NULL;
}
}
) &
make_filter<float*,float>(
filter::parallel,
[](float* p){return (*p)*(*p);}
) &
make_filter<float,void>(
filter::serial,
[&](float x) {sum+=x;}
)
);
return sqrt(sum);
}

  第一个filter生成数据(如从文件中读取数据等),第二个filter对产生的数据进行转换,第三个filter是对转换后的数据做累加。其中第二个filter是可以并行处理的,通过filter::parallel来指定其处理模式。

parallel_sort:并行排序

const int N = ;
float a[N];
float b[N];
parallel_sort(a, a + N);
parallel_sort(b, b + N, std::greater<float>());

parallel_invoke:并行调用,并行调用多个函数

void f();
extern void bar(int); void RunFunctionsInParallel() {
tbb::parallel_invoke(f, []{bar();}, []{bar();} );
}

TBB任务

task_group表示可以等待或者取消的任务集合

task_group g;
g.run([]{TestPrint(); });
g.run([]{TestPrint(); });
g.run([]{TestPrint(); });
g.wait();

PPL(Parallel Patterns Library)

  PPL是微软开发的并行计算库,它的功能和TBB是差不多的,但是PPL只能在windows上使用。二者在并行算法的使用上基本上是一样的, 但还是有差异的。二者的差异:

  1. parallel_reduce的原型有些不同,PPL的paraller_reduce函数多一个参数,原型为parallel_reduce(begin,end,identity,func,reduction), 比tbb多了一个参数,但是表达的意思差不多,一个是区间,一个是区间迭代器。
  2. PPL中没有parallel_pipeline接口。
  3. TBB的task没有PPL的task强大,PPL的task可以链式连续执行还可以组合任务,TBB的task则不行。

PPL任务的链式连续执行then

int main()
{
auto t = create_task([]() -> int
{
return ;
}); // Create a lambda that increments its input value.
auto increment = [](int n) { return n + ; }; // Run a chain of continuations and print the result.
int result = t.then(increment).then(increment).then(increment).get();
cout << result << endl;
}
/* Output:
3
*/

PPL任务的组合

  1.when_all可以执行一组任务,所有任务完成之后将所有任务的结果返回到一个集合中。要求该组任务中的所有任务的返回值类型都相同。

array<task<int>, > tasks =
{
create_task([]() -> int { return ; }),
create_task([]() -> int { return ; }),
create_task([]() -> int { return ; })
}; auto joinTask = when_all(begin(tasks), end(tasks)).then([](vector<int> results)
{
cout << "The sum is "
<< accumulate(begin(results), end(results), )
<< '.' << endl;
}); // Print a message from the joining thread.
cout << "Hello from the joining thread." << endl; // Wait for the tasks to finish.
joinTask.wait();

2.when_any任务组中的某一个任务执行完成之后,返回一个pair,键值对是结果和任务序号。

array<task<int>, > tasks = {
create_task([]() -> int { return ; }),
create_task([]() -> int { return ; }),
create_task([]() -> int { return ; })
}; // Select the first to finish.
when_any(begin(tasks), end(tasks)).then([](pair<int, size_t> result)
{
cout << "First task to finish returns "
<< result.first
<< " and has index "
<< result.second<<endl;
}).wait();
//output: First task to finish returns 42 and has index 1.

总结:

  ppl和tbb两个并行运算库功能相似,如果需要跨平台则选择tbb,  否则选择ppl。ppl在任务调度上比tbb强大,tbb由于设计上的原因不能做到任务的连续执行以及任务的组合,但是tbb有跨平台的优势。

如果你觉得这篇文章对你有用,可以点一下推荐,谢谢。

c++11 boost技术交流群:296561497,欢迎大家来交流技术。

c++并行计算库TBB和PPL的基本用法的更多相关文章

  1. intel线程库tbb的使用

    [size=small]首先下载: http://www.threadingbuildingblocks.org/uploads/77/111/2.1/tbb21_20080605oss_win.zi ...

  2. 【c++】标准模板库STL入门简介与常见用法

    一.STL简介 1.什么是STL STL(Standard Template Library)标准模板库,主要由容器.迭代器.算法.函数对象.内存分配器和适配器六大部分组成.STL已是标准C++的一部 ...

  3. urllib 库的代替品 requests 的用法

    Requuests 官方的介绍时多么的霸气,之所以那么霸气,是因为 Requestts 相比于 urllib 在使用方面上会让开发者感到更加的人性化.更加简洁.更加舒适,并且国外的一些公司也在使用re ...

  4. python可视化库 Matplotlib 01 figure的详细用法

    1.上一章绘制一幅最简单的图像,这一章介绍figure的详细用法,figure用于生成图像窗口的方法,并可以设置一些参数 2.先看此次生成的图像: 3.代码(代码中有详细的注释) # -*- enco ...

  5. numpy库数组拼接np.concatenate的用法

    concatenate功能:数组拼接 函数定义:numpy.concatenate((a1, a2, ...), axis=0, out=None)

  6. (原创)发布一个c++11开发的轻量级的并行Task库TaskCpp

    TaskCpp简介 TaskCpp是c++11开发的一个跨平台的并行task库,它的设计思路来源于微软的并行计算库ppl和intel的并行计算库tbb,关于ppl和tbb我在前面有介绍.既然已经有了这 ...

  7. 好用的http client库CPP REST SDK

    前言 C++中http client库本身就少,好用的就更少了,在了解微软开源的CPP REST SDK库之前,我知道的C++ http client库有libcurl(这个是C语言的),Qt的QNe ...

  8. Intel TBB in OpenCASCADE

    Intel TBB in OpenCASCADE eryar@163.com OpenCASCADE使用了一个开源的第三方库Intel TBB,这个并行计算库主要用于网格化.布尔操作等复杂算法,可以明 ...

  9. 转: 工作中用的C++库

    转:https://www.mhftz.com/archives/42.html 个人学习C/C++的开源代码: 0.STL 1.osmium 2.leveldb 3.glog 4.redis 个人使 ...

随机推荐

  1. Unrecognized option: -jrockit

    weblogic报错: starting weblogic with Java version: Unrecognized option: -jrockit Error: Could not crea ...

  2. [解决]java.lang.IllegalArgumentException: Bad level "DEBUG"

    Tomcat启动报错,搞得烦的一比.常规思维就会迷瞪,谁让tomcat的日志级别特殊ne.... http://tomcat.apache.org/tomcat-7.0-doc/ 错误现象: Hand ...

  3. Ubuntu18.04使用adb和tcpdump对android设备进行网络调试

    准备工作 1. Android设备需要root 2. 在 https://www.androidtcpdump.com/ 下载适用于Android的tcpdump可执行文件 3. 本地安装 andro ...

  4. 转:Ogre的MaterialSystem分析

    1. Mesh .SubMesh.SubEntity和Entity 所有的Mesh对象是由SubMesh构成的,每个SubMesh代表了Mesh对象的一部分,该部分只能使用一种Meterial.如果一 ...

  5. ArcGIS 概述

    ArcGIS产品线为用户提供一个可伸缩的,全面的GIS平台.ArcObjects包含了大量的可编程组件,从细粒度的对象(例如,单个的几何对象)到粗粒度的对象(例如与现有ArcMap文档交互的地图对象) ...

  6. C++中public、protected及private使用方法

    1.类的一个特征就是封装,public和private作用就是实现这一目的.所以: 用户代码(类外)能够訪问public成员而不能訪问private成员:private成员仅仅能由类成员(类内)和友元 ...

  7. macbook上安装homestead

    参考资料: 1:https://solarhell.com/post/2016/04/homestead 2:https://phphub.org/topics/491 3:http://larave ...

  8. iOS实现基于VLC播放器的封装效果

    前言: 在一些特定场景下,我们获取到的音视频,由于格式比较特殊,用avplayer等播放器是无法播放的,此时,我们可以借助强大的VLC播放器来处理. 原理这里不再赘述,下面我们讲一下如何添加VLC播放 ...

  9. Seqlite学习

    之前没有接触过数据库编程,尼玛,面试神码的最恶心了,非得神码都懂点,好吧,最近开始研究下,先从SQLite开始吧,贴上找到SQliteDB.之后搜集资料,慢慢学习!

  10. 重写Checkbox 改写选择框的大小

    /* 作者:Starts_2000 * 日期:2009-07-30 * 网站:http://www.csharpwin.com CS 程序员之窗. * 你可以免费使用或修改以下代码,但请保留版权信息. ...