- 浏览: 2036833 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (651)
- ACE (35)
- BAT (9)
- C/C++ (116)
- fast-cgi (14)
- COM (27)
- python (59)
- CGI (4)
- C# (2)
- VC (84)
- DataBase (29)
- Linux (96)
- P2P (6)
- PHP (15)
- Web (6)
- Memcached (7)
- IME输入法 (11)
- 设计模式 (2)
- 搜索引擎 (1)
- 个人情感 (4)
- 笔试/面试 (3)
- 一亩三分地 (33)
- 历史 (2)
- 地理 (1)
- 人物 (3)
- 经济 (0)
- 不仅仅是笑哦 (43)
- 小故事大道理 (2)
- http://www.bjdsmyysjk120.com/ (0)
- http://www.bjdsmyy120.com/ (0)
- 它山之石可以攻玉 (15)
- 大学生你关注些什么 (28)
- 数据恢复 (1)
最新评论
-
luokaichuang:
这个规范里还是没有让我明白当浏览器上传文件时,STDIN的消息 ...
FastCGI规范 -
effort_fan:
好文章!学习了,谢谢分享!
com技术简介 -
vcell:
有错误os.walk(strPath)返回的已经是全部的文件和 ...
通过python获取目录的大小 -
feifeigd:
feifeigd 写道注意:文章中的CPP示例第二行 #inc ...
ATL入门:利用ATL编写简单的COM组件 -
feifeigd:
注意:文章中的CPP示例第二行 #include " ...
ATL入门:利用ATL编写简单的COM组件
示例
用TBB写并行transform代替原std::transform,分别使用parallel_for和pipeline实现
#include <iostream> #include <algorithm> #include <vector> #include <list> #include <math.h> #include <tbb/task_scheduler_init.h> #include <tbb/blocked_range.h> #include <tbb/parallel_for.h> #include <tbb/pipeline.h> #include <tbb/tick_count.h> //-----------------随机存取迭代器版本------------------------------------- //both_random_helper,作用:测试两个模板是否都是random_access_iterator_tag //是则Iter_cat返回random_access_iterator_tag //否则返回forward_iterator_tag template<class _Cat1, class _Cat2> struct both_random_helper{ typedef std::forward_iterator_tag Iter_cat; }; template<> struct both_random_helper< std::random_access_iterator_tag, std::random_access_iterator_tag>{ typedef std::random_access_iterator_tag Iter_cat; }; // 用于存放一对迭代器 template<class _InIt, class _OutIt> struct Iter_pair{ _InIt m_in; _OutIt m_out; Iter_pair(_InIt _in, _OutIt _out) :m_in(_in),m_out(_out){} //支持blocked_range拆分 Iter_pair operator+(size_t off) const { return Iter_pair(m_in+off, m_out+off); } size_t operator-(Iter_pair rhs) const { return m_in-rhs.m_in; } bool operator<(Iter_pair rhs) const { return m_in<rhs.m_in; } }; // 随机存取迭代器版本 template<class _InIt, class _OutIt, class _Fn1> struct op_parallel_transform{ op_parallel_transform(_Fn1 _Func) :m_Func(_Func){} void operator()(const tbb::blocked_range<Iter_pair<_InIt,_OutIt> > &r) const { std::transform(r.begin().m_in, r.end().m_in, r.begin().m_out, m_Func); } private: _Fn1 m_Func; }; template<class _InIt, class _OutIt, class _Fn1> _OutIt _parallel_transform(_InIt _First, _InIt _Last, _OutIt _Dest, _Fn1 _Func, std::random_access_iterator_tag) { // 使用parallel_for来处理 typedef typename Iter_pair<_InIt,_OutIt> iter_pair_type; _OutIt LastDest = _Dest + (_Last - _First); iter_pair_type begin(_First, _Dest); iter_pair_type end(_Last, LastDest); tbb::blocked_range<iter_pair_type> x(begin, end); tbb::parallel_for(x, op_parallel_transform<_InIt,_OutIt,_Fn1>(_Func), tbb::auto_partitioner()); return LastDest; } //-----------------顺序存取迭代器版本------------------------------------- template<class _InIt> struct filter_in : tbb::filter{ filter_in(_InIt _First, _InIt _Last) :tbb::filter(true),m_First(_First), m_Last(_Last){} void* operator()(void*) { if(m_First==m_Last) return NULL; void* p = &(*m_First); ++m_First; return p; } private: _InIt m_First, m_Last; }; template<class _Fn1> struct filter_process : tbb::filter{ typedef typename _Fn1::result_type r_type; typedef typename _Fn1::argument_type a_type; filter_process(_Fn1 _Func) :tbb::filter(false),m_Func(_Func){} void* operator()(void* data) { a_type &at = *(a_type*)data; m_r = m_Func( at ); return &m_r; } private: _Fn1 m_Func; r_type m_r; }; template<class _OutIt, class _DataType> struct filter_out : tbb::filter{ filter_out(_OutIt _Dest) :tbb::filter(true),m_Dest(_Dest){} void* operator()(void* data) { _DataType *p = (_DataType*) data; *m_Dest = *p; ++m_Dest; return NULL; } private: _OutIt m_Dest; }; template<class _InIt, class _OutIt, class _Fn1> _OutIt _parallel_transform(_InIt _First, _InIt _Last, _OutIt _Dest, _Fn1 _Func, std::forward_iterator_tag) { // 使用管线pipeline来处理 tbb::pipeline pipeline; filter_in<_InIt> f1(_First, _Last); filter_process<_Fn1> f2(_Func); filter_out<_OutIt, _Fn1::result_type> f3(_Dest); pipeline.add_filter(f1); pipeline.add_filter(f2); pipeline.add_filter(f3); pipeline.run(3); return _Dest; } //----------------------parallel_transform---------------------------- template<class _InIt, class _OutIt, class _Fn1> inline _OutIt parallel_transform(_InIt _First, _InIt _Last, _OutIt _Dest, _Fn1 _Func) { typedef typename std::iterator_traits<_InIt>::iterator_category cat1; typedef typename std::iterator_traits<_OutIt>::iterator_category cat2; return _parallel_transform(_First, _Last, _Dest, _Func, both_random_helper<cat1,cat2>::Iter_cat()); } // 测试代码 struct SinFunctor :std::unary_function<double, double>{ double operator()(double &d) const { // 高强度运算 double sum = 0; for(int i=0; i<10000; i++) sum += sin(i*d); return sum; } }; int main() { // 随机存取迭代 std::vector<double> a(10000,1.5); // 顺序存取迭代 std::list<double> b(10000,1.5); tbb::task_scheduler_init init; tbb::tick_count t0,t1; t0 = tbb::tick_count::now(); parallel_transform(a.begin(), a.end(), a.begin(), SinFunctor()); t1 = tbb::tick_count::now(); std::cout << "并行(随机迭代)" << (t1 - t0).seconds() << std::endl; t0 = tbb::tick_count::now(); std::transform(a.begin(), a.end(), a.begin(), SinFunctor()); t1 = tbb::tick_count::now(); std::cout << "原版(随机迭代)" << (t1 - t0).seconds() << std::endl; t0 = tbb::tick_count::now(); parallel_transform(b.begin(), b.end(), b.begin(), SinFunctor()); t1 = tbb::tick_count::now(); std::cout << "并行(顺序迭代)" << (t1 - t0).seconds() << std::endl; t0 = tbb::tick_count::now(); std::transform(b.begin(), b.end(), b.begin(), SinFunctor()); t1 = tbb::tick_count::now(); std::cout << "原版(顺序迭代)"<< (t1 - t0).seconds() << std::endl; std::cin.get(); return 0; }在我的双核Centrino电脑上测试结果如下:
在顺序存取迭代器版本的_parallel_transform中,因为迭代器不能随意跳转,所以使用了tbb::pipeline加三个filter分 别执行顺序读取,处理和写入。其中的处理是可以并行处理的。从上面的结果可以看出,pipeline的性能甚至不亚于parallel_for循环。关于 pipeline的使用说明,请参考文章:TBB流水线 这里写的parallel_transform可以直接替换大家原有代码中的std::transform,当然如果有兴趣的话完全可以把标准库中的算法 全用TBB改写成并行算法。不过要注意的一点是并不是任何地方都适合使用并行运算的,象这个例子中测试用的处理算子是“for(int i=0; i<10000; i++) sum += sin(i*d);”这样的需要耗时较长的运算,如果把它改成“return sin(d);”。那么考虑到线程调度以及TBB的任务调度,并行算法的效率可能还不如串行算法。 TBB库可以从这里下载:http://www.threadingbuildingblocks.org/download.php 另外再推荐几篇TBB入门文章:并行(随机迭代)3.17299
原版(随机迭代)5.41531
并行(顺序迭代)3.13054
原版(顺序迭代)5.33182
Intel Threading Building Blocks 之 并行循环
Intel Threading Building Blocks 之 并发容器
Intel Threading Building Blocks 基于任务编程
相信度过了自己的20岁生日之后的C++,在多核时候将再创辉煌!
发表评论
-
Berkeley DB 使用经验总结
2012-08-27 14:41 3087作者:陈磊 NoSQL是现在互联网Web2.0时代备受 ... -
嵌入式数据库系统Berkeley DB
2012-08-27 14:37 1534前言 UNIX/LINUX平台下的数据库种类非常多 ... -
C语言中标准输入流、标准输出流、标准错误输出流
2011-06-13 14:32 9294C语言中标准输入流、标准输出流、标准错误输出流 在 ... -
Rsync 实现原理
2011-05-12 20:06 8323Rsync 实现原理 前言 关于rsync的原始文档 ... -
c++简单的虚函数测试
2011-04-27 14:25 1021#include <iostream> u ... -
C++文件行查找
2011-04-26 14:10 1409#include <iostream> # ... -
c++偏特化简单示例
2011-04-13 11:17 2157c++偏特化 // temp1.c ... -
GDB调试精粹及使用实例
2011-03-16 14:06 1142GDB调试精粹及使用实例 一:列文件清单 1. ... -
简单的ini文件解析
2011-02-12 16:36 1624int GetKeyVal(const string s ... -
scanf族函数高级用法
2011-01-25 16:00 2563如何解释 fscanf(fd,&quo ... -
使用scons替代makefile(1)
2011-01-25 11:58 3735早在多年前我刚开始接触linux下的C程序时,经常被makef ... -
使用scons替代makefile(2)
2011-01-25 11:57 3585本篇文章接着上一篇进一步介绍scons的使用方法,主要介绍静态 ... -
使用scons替代makefile(3)
2011-01-25 11:55 4822在上两篇文章中已经简单介绍了用scons编译库文件,可执行程序 ... -
C 支持动态添加测试数据的测试代码
2011-01-13 17:22 1121/下面的定义为了支持可扩增。 //当需要增加一个新的测试用列 ... -
Linux下Makefile的automake生成
2010-12-28 16:55 1103******************helloworld.c* ... -
SCons笔记(详细版)
2010-12-23 16:11 105431. 基本使用 SConstruct文件就功能而言相当于Ma ... -
scons 学习
2010-12-23 11:14 2184scons 学习 作者:Sam(甄峰) sam_code@h ... -
scons随笔
2010-12-22 20:20 4708scons随笔 Scons是新一代的软件构件工具,或者说ma ... -
Scons在linux下的安装和使用
2010-12-21 11:59 3287因为正在用的一个开源软件需要的Developm ... -
排列组合的实现
2010-12-20 12:41 1066简单算法: 从前往后(或者从后往前)每次交换一个位置。当存在 ...
相关推荐
《C++多核编程》是一本专注于探讨如何利用C++进行多核并行计算的权威著作,出版于2010年,对于当时的多核技术发展来说,这本书具有开创性的意义。多核编程是现代计算机科学中的一个重要领域,因为随着处理器核心数量...
在当今计算机硬件发展迅速的时代,多核处理器已经成为主流,因此掌握多线程和并行编程技术对于提升软件性能至关重要。这本书旨在帮助开发者从传统的顺序编程模式转向能够充分利用多核优势的并行编程,从而实现程序...
《多核计算与程序设计》是一本深入探讨如何利用多核处理器进行高效并行计算的书籍,源码和OpenMP示例提供了丰富的实践资源。在现代计算机系统中,多核计算已经成为提升性能的关键技术,而OpenMP作为一种并行编程模型...
本文档通过一系列C/C++示例代码,介绍了多核编程的基本概念和技术。 #### 二、多核编程中的线程创建与管理 ##### 1. Win32线程API:创建线程实例1 **知识点:** - **线程的概念与作用**:线程是程序执行流的最小...
C++ AMP(Accelerated Massive Parallelism)是C++的一个扩展,旨在利用现代多核处理器的并行计算能力,特别是针对GPU(图形处理器)的编程。这些示例代码是为了帮助开发者理解和应用C++ AMP在实际项目中的工作原理...
2. 并行编程模型:深入探讨OpenMP、MPI、Pthread等并行编程接口,以及如何在C++、Fortran、Java等语言中实现多线程编程。 三、Intel多核优化 1. 编译器优化:阐述Intel编译器如何自动识别并优化多核代码,提高执行...
这个资源包“Intel多核大学——多核程序设计源码”就是为学习者提供了一个实践平台,通过实际的代码示例来教授多核程序设计的技巧和最佳实践。 首先,多核技术是现代计算机硬件发展的关键趋势。传统的单核处理器在...
通过理解并实践这些现代C++异步编程技术,开发者可以编写出更高效、更适应多核处理器的程序。例如,对于大规模数据处理、计算密集型任务或IO密集型任务,使用异步编程可以显著减少总体执行时间,提高用户体验。同时...
并发编程是现代多核处理器环境下提高软件性能的关键技术,C++作为一门强大且灵活的编程语言,提供了丰富的工具和机制来支持并发。 在C++中,并发主要涉及以下几个核心概念: 1. **线程**:线程是程序执行的最小...
随着信息技术的飞速发展,我们已经进入了多核处理器的时代,这标志着计算机硬件性能的巨大提升。在这个时代背景下,网络讲坛的"多核时代下的并行编程(下)j.zip"视频教程成为了一个极具价值的学习资源。本课程深入...
压缩包中的"code"文件可能包含了示例代码,这些代码可能是用C++、Python、Java或其他支持并行编程的语言编写,用于演示如何在多核环境下实现并行计算。通过分析和学习这些代码,你可以了解到并行编程的基本原理和...
rocksdb:用 C++ 编写的高性能键值存储引擎。该项目是由 Fackbook 数据库团队基于 levelDB 开发,键值均支持二进制流,能够充分利用多核 CPU 获得高性能,并兼容 levelDB 的 API 可谓是青出于蓝而胜于蓝。RocksDB ...
#### 一、多核时代与多核编程概览 **多核时代**: - **台式机的多核时代**:自2000年代中期以来,随着计算机处理器架构的发展,多核处理器成为了主流配置。这意味着单一的处理器包含了多个独立的核心,能够同时处理...
《C++ Concurrency in Action》是一本深入探讨C++并发编程的权威著作,作者是知名软件开发者、C++专家...通过阅读这本书,C++开发者能够深入理解并发编程的本质,从而在多核计算时代编写出更强大、更可靠的软件。
在《多线程与多核编程.pdf》这份文档中,可能会详细介绍以上概念,并给出实际编程示例,包括如何在不同编程环境下(如Windows、Linux或Unix系统)创建和管理线程,以及如何利用OpenMP编写并行程序。此外,文档可能还...
7. **多线程编程**:Visual C++支持多线程编程,能够充分利用多核处理器的优势,提高程序的并发性能。了解互斥量、条件变量、线程池等同步机制至关重要。 8. **调试技巧**:有效的调试策略和工具使用,如断点、监视...
13. **多线程编程**:C++11引入了线程库,支持并发编程,可以充分利用多核处理器的优势。 14. **C++的现代特性**:包括RAII(Resource Acquisition Is Initialization)、智能指针、右值引用、lambda表达式等,使...
使用`EnterCriticalSection`和`LeaveCriticalSection`进入和离开临界区,确保同一时刻只有一个线程执行。 2. **互斥量(Mutex)**:与临界区类似,但可以跨进程使用。通过`CreateMutex`创建,`WaitForSingleObject`或...
由于C++11对并发的支持是一次革命性的更新,它为开发者提供了丰富的工具来构建高效、线程安全的应用程序,这一点对于处理现代多核处理器的复杂性至关重要。 本书详细介绍了C++的线程库,包括std::thread类的使用...