132 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
		
		
			
		
	
	
			132 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| 
								 | 
							
								### 使用c++11开发一个轻量级的并行task库
							 | 
						|||
| 
								 | 
							
								#### 15.1 TBB的基本用法
							 | 
						|||
| 
								 | 
							
								#### 15.1.1 TBB概述
							 | 
						|||
| 
								 | 
							
								TBB 是inter用标准c++写的一个开源的并行计算库,它的目的是提升数据并行计算的能力。主要功能如下:
							 | 
						|||
| 
								 | 
							
								1. 并行计算
							 | 
						|||
| 
								 | 
							
								2. 任务调度
							 | 
						|||
| 
								 | 
							
								3. 并行容器
							 | 
						|||
| 
								 | 
							
								4. 同步原语
							 | 
						|||
| 
								 | 
							
								5. 内存分配器
							 | 
						|||
| 
								 | 
							
								#### 15.1.2 TBB并行算法
							 | 
						|||
| 
								 | 
							
								1. parallel_for:以并行的方式遍历一个区间
							 | 
						|||
| 
								 | 
							
								2. parallel_do和parallel_for_each:将算法用于一个区间
							 | 
						|||
| 
								 | 
							
								3. parallel_reduce:并行汇聚
							 | 
						|||
| 
								 | 
							
								4. parallel_pipeline:并行的管道过滤器
							 | 
						|||
| 
								 | 
							
								5. parallel_sort和parallel_invoke:并行排序和调和
							 | 
						|||
| 
								 | 
							
								#### 15.1.3 TBB的任务组
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								tbb::task_group g;
							 | 
						|||
| 
								 | 
							
								g.run([]{task();});
							 | 
						|||
| 
								 | 
							
								g.run([]{task();});
							 | 
						|||
| 
								 | 
							
								g.run([]{task();});
							 | 
						|||
| 
								 | 
							
								g.wait();
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								#### 15.2 PPL的基本用法
							 | 
						|||
| 
								 | 
							
								两者差异:
							 | 
						|||
| 
								 | 
							
								1. parallel_reduce的原型有些不同。
							 | 
						|||
| 
								 | 
							
								2. PPL中没有parallel_pipeline接口
							 | 
						|||
| 
								 | 
							
								3. TBB的task没有PPL的task强大,PPL的task可以链式连续执行,还可以组合任务,而TBB的task不行。
							 | 
						|||
| 
								 | 
							
								#### 15.5 TaskCpp的任务
							 | 
						|||
| 
								 | 
							
								#### 15.5.1 task的实现
							 | 
						|||
| 
								 | 
							
								基于task的并行编程模型最基本的执行单元是task,一个task就代表了一个要执行的任务。外部只需要简单调用接口就可以创建task并且执行,另一个细节就是异步执行。
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								template<typename T>
							 | 
						|||
| 
								 | 
							
									class Task;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									template<typename R, typename...Args>
							 | 
						|||
| 
								 | 
							
									class Task<R(Args...)>
							 | 
						|||
| 
								 | 
							
									{
							 | 
						|||
| 
								 | 
							
										std::function<R(Args...)> m_fn;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									public:
							 | 
						|||
| 
								 | 
							
										typedef R return_type;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										template<typename F>
							 | 
						|||
| 
								 | 
							
										auto Then(F&& f)//->Task<typename std::result_of<F(R)>::type(Args...)>
							 | 
						|||
| 
								 | 
							
										{
							 | 
						|||
| 
								 | 
							
											typedef typename std::result_of<F(R)>::type ReturnType;
							 | 
						|||
| 
								 | 
							
											auto func = std::move(m_fn);
							 | 
						|||
| 
								 | 
							
											return Task<ReturnType(Args...)>([func, &f](Args&&... args)
							 | 
						|||
| 
								 | 
							
											{
							 | 
						|||
| 
								 | 
							
												std::future<R> lastf = std::async(func, std::forward<Args>(args)...);
							 | 
						|||
| 
								 | 
							
												return std::async(f, lastf.get()).get();
							 | 
						|||
| 
								 | 
							
											});
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										Task(std::function<R(Args...)>&& f) :m_fn(std::move(f)){}
							 | 
						|||
| 
								 | 
							
										Task(std::function<R(Args...)>& f) :m_fn(f){}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										~Task()
							 | 
						|||
| 
								 | 
							
										{
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										void Wait()
							 | 
						|||
| 
								 | 
							
										{
							 | 
						|||
| 
								 | 
							
											std::async(m_fn).wait();
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										template<typename... Args>
							 | 
						|||
| 
								 | 
							
										R Get(Args&&... args)
							 | 
						|||
| 
								 | 
							
										{
							 | 
						|||
| 
								 | 
							
											return std::async(m_fn, std::forward<Args>(args)...).get();
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										std::shared_future<R> Run()
							 | 
						|||
| 
								 | 
							
										{
							 | 
						|||
| 
								 | 
							
											return std::async(m_fn);
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
									};
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								#### 15.5.2 task的延续
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								#include <functional>
							 | 
						|||
| 
								 | 
							
								namespace Cosmos
							 | 
						|||
| 
								 | 
							
								{
							 | 
						|||
| 
								 | 
							
									template<typename T>
							 | 
						|||
| 
								 | 
							
									class Task;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									template<typename R, typename...Args>
							 | 
						|||
| 
								 | 
							
									class Task<R(Args...)>
							 | 
						|||
| 
								 | 
							
									{
							 | 
						|||
| 
								 | 
							
										std::function<R(Args...)> m_fn;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									public:
							 | 
						|||
| 
								 | 
							
										typedef R return_type;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										template<typename F>
							 | 
						|||
| 
								 | 
							
										auto Then(F&& f)//->Task<typename std::result_of<F(R)>::type(Args...)>
							 | 
						|||
| 
								 | 
							
										{
							 | 
						|||
| 
								 | 
							
											typedef typename std::result_of<F(R)>::type ReturnType;
							 | 
						|||
| 
								 | 
							
											auto func = std::move(m_fn);
							 | 
						|||
| 
								 | 
							
											return Task<ReturnType(Args...)>([func, &f](Args&&... args)
							 | 
						|||
| 
								 | 
							
											{
							 | 
						|||
| 
								 | 
							
												std::future<R> lastf = std::async(func, std::forward<Args>(args)...);
							 | 
						|||
| 
								 | 
							
												return std::async(f, lastf.get()).get();
							 | 
						|||
| 
								 | 
							
											});
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										Task(std::function<R(Args...)>&& f) :m_fn(std::move(f)){}
							 | 
						|||
| 
								 | 
							
										Task(std::function<R(Args...)>& f) :m_fn(f){}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										~Task()
							 | 
						|||
| 
								 | 
							
										{
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										void Wait()
							 | 
						|||
| 
								 | 
							
										{
							 | 
						|||
| 
								 | 
							
											std::async(m_fn).wait();
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										template<typename... Args>
							 | 
						|||
| 
								 | 
							
										R Get(Args&&... args)
							 | 
						|||
| 
								 | 
							
										{
							 | 
						|||
| 
								 | 
							
											return std::async(m_fn, std::forward<Args>(args)...).get();
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										std::shared_future<R> Run()
							 | 
						|||
| 
								 | 
							
										{
							 | 
						|||
| 
								 | 
							
											return std::async(m_fn);
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
									};
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								```
							 |