




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、TBB的几个特性与线程不同,您可以对任务使用更高程度的抽象。Intel 声称,在 Linux 系统上,启动和结束任务的速度是对线程执行相同操作的 18 倍。Intel TBB 附带了一个任务调度程序,该程序可以跨多个逻辑和物理内核高效地处理负载平衡。Intel TBB 中的默认任务调度策略不同于大多数线程调度程序所拥有的轮询策略。Intel TBB 提供了一些可直接使用的线程安全容器,比如 concurrent_vector 和 concurrent_queue。可以使用通用的并行算法,如 parallel_for 和 parallel_reduce。模板类 atomic 中提供了无锁(Loc
2、k-free,也称为 mutex-free)并发编程支持。这种支持使得 Intel TBB 适合用于高性能的应用程序,因为 Intel TBB 可以锁定和解除锁定互斥体 (mutex)。这都是用 C+ 实现的!没有进行任何扩展或使用宏,Intel TBB 只使用这种语言,同时还使用了大量的模板。上图的内容可以分为以下几类:l 通用并行算法TBB提供了parallel_for,parallel_while,parallel_reduce等算法,应用于不同的并行算法场景l 并发容器这是对常见容器的线程安全版本的实现,同时考虑到性能要求,提供了细粒度的锁机制,TBB2.0里提供的容器包括hash m
3、ap,vector,queue。l 任务调度器:提供了task机制的封装l 同步原语:提供了原子操作、mutex、lock等同步原语的封装l 内存分配:提供了对cache机制更友好的支持parallel_forl 摘要parallel_for是在一个值域执行并行迭代操作的模板函数。l 语法templateFunc parallel_for( Index first, Index_type last, const Func& f , task_group_context&group ); templateFunc parallel_for( Index first, Index_
4、type last, Index step, const Func&f , task_group_context&group ); template Void parallel_for( const Range& range, const Body& body, , partitioner,task_group_context& group );l 头文件#include “tbb/parallel_for.h”l 描述parallel_for(first, last,step, f)表示一个循环的并行执行: for(auto i= first; ila
5、st; i+=step) f(i);example:#include #include using namespace tbb;using namespace std;int main() parallel_for(0,10,(int v)coutv ;); return0;parallel_for原型语义Body:Body(const Body&) 拷贝构造Body:Body()析构void Body:operator()(Range& range) const对range对象应用body对象l描述parallel_for(range, body, partitioner)提
6、供了并行迭代的泛型形式。它表示在区域的每个值,并行执行body。partitioner选项指定了分割策略。Range类型必须符合Range概念模型。body必须符合下表的要求:采用最后一个模板以及stl中的vector容器改写example:#include #include #include #include #include using namespace std;using namespace tbb;typedef vector:iterator IntVecIt;struct body void operator()(const blocked_range&r)const f
7、or(auto i = r.begin(); i!=r.end(); i+) cout*i ; ;int main() vector vec; for(int i=0; i10; i+) vec.push_back(i); parallel_for(blocked_range(vec.begin(), vec.end() , body(); return 0;原型摘要R:R(const R& )构造函数R:R()析构函数bool R:empty() const区域为空返回turebool R:is_divisible() const 如果区域可再分,返回tureR:R(R& r
8、, split)将r分为两个子区域Parallel_reducel 摘要parallel_reduce模板在一个区域迭代,将由各个任务计算得到的部分结果合并,得到最终结果。parallel_reduce对区域(range)类型的要求与parallel_for一样。l 语法templateValue parallel_reduce(const Range& range, const Value& identity, const Func& func, const Reduction& reduction, , partitioner,task_group_cont
9、ext& group ); template void parallel_reduce(const Range& range, const Body& body , partitioner,task_group_context& group );l 头文件#include “tbb/parallel_reduce.h”原型摘要Value IdentityFunc:operator()的左标识元素Value Func:operator()(const Range& range, const Value& x)累计从初始值x开始的子区域的结果Valu
10、e Reduction:operator()(const Value& x, const Value& y);合并x跟y的结果l 描述parallel_reduce模板有两种形式。函数形式是为方便与lambda表达式一起使用而设计。第二种形式是为了最小化数据拷贝。 下面的表格总结了第一种形式中的identity,func,reduction的类型要求:Parallel_reduce#include #include #include #include using namespace std;using namespace tbb;int main() vector vec; f
11、or(int i=0; i100; i+) vec.push_back(i);int result = parallel_reduce(blocked_rangevector:iterator(vec.begin(), vec.end(), 0, (const blocked_rangevector:iterator& r, int init)-int for(auto a = r.begin(); a!=r.end(); a+) init+=*a; return init; , (int x, int y)-int return x+y; ); coutresult:resulten
12、dl; return 0;了解TBB任务Intel TBB 基于 任务 的概念。您需要定义自己的任务,这些任务是从 tbb:task 中派生的,并使用 tbb/task.h 进行声明。用户需要在自己的代码中重写纯虚拟方法 task* task:execute ( )。下面展示了每个 Intel TBB 任务的一些属性:当 Intel TBB 任务调度程序选择运行一些任务时,会调用该任务的 execute 方法。这是入口点。execute 方法会返回一个 task*,告诉调度程序将要运行的下一个任务。如果它返回 NULL,那么调度程序可以自由选择下一个任务。task:task( ) 是虚拟的,不
13、管用户任务占用了什么资源,都必须在这个析构函数 (destructor) 中释放。任务是通过调用 task:allocate_root( ) 来分配的。主任务通过调用 task:spawn_root_and_wait(task) 来完成任务的运行。创建第一个 Intel TBB 任务#include tbb/tbb.h#include using namespace tbb;using namespace std;class first_task : public task public: task* execute( ) cout Hello World!n; return NULL; ;i
14、nt main( ) task_scheduler_init init(task_scheduler_init:automatic); first_task& f1 = *new(tbb:task:allocate_root() first_task( ); tbb:task:spawn_root_and_wait(f1);Simple Example: Fibonacci NumbersThis is the serial code:long SerialFib( long n ) if( n2 ) return n; else return SerialFib(n-1)+Seria
15、lFib(n-2);The top-level code for the parallel task-based version is:long ParallelFib( long n ) long sum; FibTask& a = *new(task:allocate_root() FibTask(n,&sum); task:spawn_root_and_wait(a); return sum;The real work is inside struct FibTask. Its definition is shown below.class FibTask: public
16、 task public: const long n; long* const sum; FibTask( long n_, long* sum_ ) : n(n_), sum(sum_) task* execute() / Overrides virtual function task:execute if( nCutOff ) *sum = SerialFib(n); else long x, y; FibTask& a = *new( allocate_child() ) FibTask(n-1,&x); FibTask& b = *new( allocate_c
17、hild() ) FibTask(n-2,&y); / Set ref_count to two children plus one for the wait. set_ref_count(3); / Start b running. spawn( b ); / Start a running and wait for all children (a and b). spawn_and_wait_for_all(a); / Do the sum *sum = x+y; return NULL; ;END谢谢观看!Simple Example: Fibonacci NumbersThis
18、 is the serial code:long SerialFib( long n ) if( n2 ) return n; else return SerialFib(n-1)+SerialFib(n-2);The top-level code for the parallel task-based version is:long ParallelFib( long n ) long sum; FibTask& a = *new(task:allocate_root() FibTask(n,&sum); task:spawn_root_and_wait(a); return
19、 sum;ThiscodeusesataskoftypeFibTasktodotherealwork.Itinvolvesthefollowingdistinctsteps:1.Allocatespaceforthetask.Thisisdonebyaspecialoverloadednewandmethodtask:allocate_root.The_rootsuffixinthenamedenotesthefactthatthetaskcreatedhasnoparent.Itistherootofatasktree.Tasksmustbeallocatedbyspecialmethods
20、sothatthespacecanbeefficientlyrecycledwhenthetaskcompletes.2.ConstructthetaskwiththeconstructorFibTask(n,&sum)invokedbynew.Whenthetaskisruninstep3,itcomputesthenthFibonaccinumberandstoresitinto*sum.3.Runthetasktocompletionwithtask:spawn_root_and_wait.The real work is inside struct FibTask. Its d
21、efinition is shown below.class FibTask: public task public: const long n; long* const sum; FibTask( long n_, long* sum_ ) : n(n_), sum(sum_) task* execute() / Overrides virtual function task:execute if( nCutOff ) *sum = SerialFib(n); else long x, y; FibTask& a = *new( allocate_child() ) FibTask(
22、n-1,&x); FibTask& b = *new( allocate_child() ) FibTask(n-2,&y); / Set ref_count to two children plus one for the wait. set_ref_count(3); / Start b running. spawn( b ); / Start a running and wait for all children (a and b). spawn_and_wait_for_all(a); / Do the sum *sum = x+y; return NULL;
23、;MethodFibTask:execute()doesthefollowing:Checksifnissosmallthatserialexecutionwouldbefaster.FindingtherightvalueofCutOffrequiressomeexperimentation.Avalueofatleast16workswellinpracticeforgettingmostofthepossiblespeedupoutofthisexample.Resortingtoasequentialalgorithmwhentheproblemsizebecomessmallisch
24、aracteristicofmostdivide-and-conquerpatternsforparallelism.Findingthepointatwhichtoswitchrequiresexperimentation,sobesuretowriteyourcodeinawaythatallowsyoutoexperiment.Iftheelseistaken,thecodecreatesandrunstwochildtasksthatcomputethe(n-1)thand(n-2)thFibonaccinumbers.Here,inheritedmethodallocate_chil
25、d()isusedtoallocatespaceforthetask.Rememberthatthetop-levelroutineParallelFibusedallocate_root()toallocatespaceforatask.Thedifferenceisthatherethetaskiscreatingchildtasks.Thisrelationshipisindicatedbythechoiceofallocationmethod.Callsset_ref_count(3).Thenumber3representsthetwochildrenandanadditionali
26、mplicitreferencethatisrequiredbymethodspawn_and_wait_for_all.Makesuretocallset_reference_count(3)beforespawninganychildren.Failuretodosoresultsinundefinedbehavior.Thedebugversionofthelibraryusuallydetectsandreportsthistypeoferror.Spawnstwochildtasks.Spawningataskindicatestotheschedulerthatitcanrunth
27、etaskwheneveritchooses,possiblyinparallelwithothertasks.Thefirstspawning,bymethodspawn,returnsimmediatelywithoutwaitingforthechildtasktostartexecuting.Thesecondspawning,bymethodspawn_and_wait_for_all,causestheparenttowaituntilallcurrentlyallocatedchildtasksarefinished.Afterthetwochildtaskscomplete,t
28、heparentcomputesx+yandstoresitin*sum.https:/ TBB 和 OpenMP API 通过工作窃取来管理任务调度。在工作窃取过程中,线程池中的每个线程维护一个双端列队本地任务池。一个线程像使用堆栈一样使用自身的任务池,并将所产生的新任务推堆栈顶部。当一个线程执行了一个任务, 它会首先从本地堆栈的顶部弹出一个任务。堆栈顶部的任务是最新的,因此最有可能访问到数据缓存中的热点数据。如果本地任务池中没有任务,它会试图从另一线程()那里窃取工作。当工作被窃取时,一个线程会将偷窃对象的双端队列作为普通队列来使用,因,所窃取的仅是偷窃对象双端队列中最旧的任务。对于递归算
29、法,这些最旧的任务均为位于任务树高处的节点,因此属于大型工作块,并且通常不是偷窃对象数据缓存中的热点。因此,工作窃取是一个实现负载平衡并且维持本地化缓存的高效机制。To set up the terminology for the following discussion, a thread belonging to TBBs internal thread pool will be called a “worker”, and any other thread will go under the alias of “master” (e.g. applications main thread
30、, or any thread explicitly created by programmer).When the first master initialized TBB 2.2 task scheduler, the following things happened:1) Global “arena” object was instantiated2) Internal pool of “worker” threads (or simply workers) was created3) Workers registered themselves in the arenaWhen the master
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 工业互联网平台安全多方计算技术在2025年的挑战与机遇报告
- 动漫产业链2025年协同创新与市场拓展策略报告
- 浙江省普通高中第二共同体2025年高三压轴卷英语试卷含解析
- 河南上蔡第一高级中学2025年高考考前模拟英语试题含解析
- 2025年第一期入党积极分子培训班结业考试试题附答案
- 聚焦2025:生物制药领域生物制药产业国际化与全球市场布局报告
- 2025《商业店铺装修工程施工合同》(示范文本)
- 智慧树知到《大学生心理健康》(吉林大学)见面课、章节测试、期末考试答案
- 网络文学出海2025年:跨文化传播与海外市场拓展实践创新案例分析报告
- 数字化赋能:2025供应链金融在中小企业融资中的应用趋势报告
- 2023年高考全国乙卷作文“一花独放不是春百花齐放春满园”写作
- 建材公司质量管理手册(模板范文)
- 钳工中级知识培训课件
- GB/T 42706.2-2023电子元器件半导体器件长期贮存第2部分:退化机理
- 高考语文新题型+“文学短评”相关写作(真题+技法+练习)
- 幼儿园小班数学活动《认识里外》教学PPT课件【幼儿教案】
- 国开【形考】《管理英语(3)》形成性考核1-8答案
- 2023学年完整公开课版用户思维
- 于丹--庄子心得
- 新产品试产工作指引
- 2023年供货方案 医疗器械供货方案(四篇)
评论
0/150
提交评论