并行库充分利用多核的优势,通过并行运算提高程序效率,本文主要介绍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. rtl-sdr在win7和ubuntu16.04的安装

    硬件准备 RTL2832+R820T2 usb dongle x 1 Long wire antenna x 1 USB电视棒的购买: 在淘宝上搜索"软件无线电"或"rt ...

  2. 【RS】Matrix Factorization Techniques for Recommender Systems - 推荐系统的矩阵分解技术

    [论文标题]Matrix Factorization Techniques for Recommender Systems(2009,Published by the IEEE Computer So ...

  3. java struts2入门学习实例--使用struts2快速实现多个文件上传

    一.错误提示信息配置 昨天说到更改默认错误配置信息,我测试很多遍,一直都不对.下面贴出来,待以后有好方法了再补充吧. 首先新建一个properties文件,这里命名为testupload.proper ...

  4. block(六)循环引用-b

    在ARC与非ARC环境下对block使用不当都会引起循环引用问题,一般表现为,某个类将block作为自己的属性变量,然后该类在block的方法体里面又使用了该类本身,简单说就是self.theBloc ...

  5. svn开发常用整理

    1.删除tortoise svn中的账号信息 其实tortoise svn也是将账号信息存放在本地的配置文件中 在不同的操作系统下,操作基本类似,首先我们来看一下windows下如何操作的. 以win ...

  6. 1142 - show view command denied to user

    原因是没有给test用户授予"show_view_priv"权限 mysql> SELECT * FROM mysql.user WHERE User = 'test' an ...

  7. Android 6.0+ RecyclerView嵌套在ScrollView中显示不全

    ScrollView嵌套RecyclerView在Android6.0以下能正常显示,但是在6.0以上就会出现RecyclerView显示不全的bug.尝试多种方法之后终于找到解决办法,特在此记录下. ...

  8. hdu 3183 A Magic Lamp(RMQ)

    A Magic Lamp                                                                               Time Limi ...

  9. go test命令參数问题

    go test命令參数问题 在使用go test对go代码进行单元測试的时候,遇到关于命令參数的问题.google了一下,没有找到非常好的说明,其实就是一些细节而已. 问题是这种,在进行单元測试的时候 ...

  10. 构建高性能J2EE应用的五种核心策略

    对于J2EE,我们知道当开发应用时,在架构设计阶段的决定将对应用的性能和可扩展性产生深远的影响.现在当开发一个应用项目时,我们越来越多地注意到了性能和可扩展性的问题.应用性能的问题比应用功能的不丰富问 ...