c++并行计算库TBB和PPL的基本用法
并行库充分利用多核的优势,通过并行运算提高程序效率,本文主要介绍c++中两个知名的并行库,一个是intel开发的TBB,一个是微软开发的PPL。本文只介绍其基本的常用用法:并行算法和任务。
TBB(Intel® Threading Building Blocks )
TBB是intel用标准c++写的一个开源的并行计算库。它的目的是提升数据并行计算的能力,可以在他的官网上下载最新的库和文档。TBB主要功能:
- 并行算法
- 任务调度
- 并行容器
- 同步原语
- 内存分配器
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上使用。二者在并行算法的使用上基本上是一样的, 但还是有差异的。二者的差异:
- parallel_reduce的原型有些不同,PPL的paraller_reduce函数多一个参数,原型为parallel_reduce(begin,end,identity,func,reduction), 比tbb多了一个参数,但是表达的意思差不多,一个是区间,一个是区间迭代器。
- PPL中没有parallel_pipeline接口。
- 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的基本用法的更多相关文章
- intel线程库tbb的使用
[size=small]首先下载: http://www.threadingbuildingblocks.org/uploads/77/111/2.1/tbb21_20080605oss_win.zi ...
- 【c++】标准模板库STL入门简介与常见用法
一.STL简介 1.什么是STL STL(Standard Template Library)标准模板库,主要由容器.迭代器.算法.函数对象.内存分配器和适配器六大部分组成.STL已是标准C++的一部 ...
- urllib 库的代替品 requests 的用法
Requuests 官方的介绍时多么的霸气,之所以那么霸气,是因为 Requestts 相比于 urllib 在使用方面上会让开发者感到更加的人性化.更加简洁.更加舒适,并且国外的一些公司也在使用re ...
- python可视化库 Matplotlib 01 figure的详细用法
1.上一章绘制一幅最简单的图像,这一章介绍figure的详细用法,figure用于生成图像窗口的方法,并可以设置一些参数 2.先看此次生成的图像: 3.代码(代码中有详细的注释) # -*- enco ...
- numpy库数组拼接np.concatenate的用法
concatenate功能:数组拼接 函数定义:numpy.concatenate((a1, a2, ...), axis=0, out=None)
- (原创)发布一个c++11开发的轻量级的并行Task库TaskCpp
TaskCpp简介 TaskCpp是c++11开发的一个跨平台的并行task库,它的设计思路来源于微软的并行计算库ppl和intel的并行计算库tbb,关于ppl和tbb我在前面有介绍.既然已经有了这 ...
- 好用的http client库CPP REST SDK
前言 C++中http client库本身就少,好用的就更少了,在了解微软开源的CPP REST SDK库之前,我知道的C++ http client库有libcurl(这个是C语言的),Qt的QNe ...
- Intel TBB in OpenCASCADE
Intel TBB in OpenCASCADE eryar@163.com OpenCASCADE使用了一个开源的第三方库Intel TBB,这个并行计算库主要用于网格化.布尔操作等复杂算法,可以明 ...
- 转: 工作中用的C++库
转:https://www.mhftz.com/archives/42.html 个人学习C/C++的开源代码: 0.STL 1.osmium 2.leveldb 3.glog 4.redis 个人使 ...
随机推荐
- 聊聊单元测试(三)——Spring Test+JUnit完美组合
本着“不写单元测试的程序员不是好程序员”原则,我在坚持写着单元测试,不敢说所有的Java web应用都基于Spring,但至少一半以上都是基于Spring的. 发现通过Spring进行bean管理后, ...
- DPDK无法分出连续大页面(contiguous hugepages)的几个解决方法
在使用DPDK或者SPDK的时候,需要在进程刚启动的时候使用rte_eal_init初始化Environment Abstract Layer,应用进程会通过这个函数告诉EAL为它映射多大的hugep ...
- 屏蔽alert弹框下面一层的操作
需求: 给alert框戴个套. 屏蔽下层页面的操作. 搞这个花里胡哨的东西. 还一baidu全都是长得一样的答案. 神魔恋. /** * Tip Message像alert一样 */ function ...
- [转]解决Eclipse中编辑xml文件的智能提示问题
转自:http://hi.baidu.com/cghroom/item/48fd2d0dc1fc23c675cd3c3e 摘要: Eclipse for Android xml 文件代码自动提示功能 ...
- libev ev_init分析
/* these may evaluate ev multiple times, and the other arguments at most once */ /* either use ev_in ...
- apache配置中ProxyPassReverse指令的含义
apache中的mod_proxy模块主要作用就是进行url的转发,即具有代理的功能.应用此功能,可以很方便的实现同tomcat等应用服务器的整合,甚者可以很方便的实现web集群的功能. 例如使用ap ...
- Android权限详解
在Android的设计中,资源的访问或者网络连接,要得到这些服务都需要声明其访问权限,否则将无法正常工作.在Android中这样的权限有很多种,这里ATAAW.COM将各类访问权限一一罗列出来,供大家 ...
- jquery 父、子页面之间页面元素的获取,方法的调用
一.jquery 父.子页面之间页面元素的获取,方法的调用: 1. 父页面获取子页面元素: 格式:$("#iframe的ID").contents().find("#if ...
- 搭建自己的 github.io 博客
1.前言 github.io 是基于 Github 的 repo 管理,这意味着咱们对其是有绝对的控制,这个跟放在第三方的平台比,可控性要好太多. 使用 github pages 服务搭建博客的好处有 ...
- golang学习笔记 ---面向并发的内存模型
Go语言是基于消息并发模型的集大成者,它将基于CSP模型的并发编程内置到了语言中,通过一个go关键字就可以轻易地启动一个Goroutine,与Erlang不同的是Go语言的Goroutine之间是共享 ...