您的位置:首页 > 其它

tbb基础之parallel_reduce用法详解

2015-04-09 10:42 936 查看
对一组数据执行诸如sum, max, min等操作被称为reduction operation。对一组数据并行执行reduction操作可能由于四舍五入导致不同的结果,如 A+B+C+D,串行执行的顺序为(((A+B)+C)+D),而并行执行的顺序可能为((A+B)+(C+D))。

首先,我们还是来看一个例子:

// parallel_reduction
class SumFoo
{
	float *my_a;

public:
	float sum;
	void operator()( const blocked_range<size_t>& range)
	{
		float *a = my_a;

		for ( size_t i = range.begin(); i!=range.end(); ++i)
		{
			sum += a[i];
		}
	}

	SumFoo(SumFoo& x, tbb::split):my_a(x.my_a),sum(0)
	{	}

	void join(const SumFoo& y)
	{
		sum += y.sum;
	}

	SumFoo( float * a):my_a(a),sum(0)
	{	}
};

float ParallelSumFoo(  float * fArray, size_t nSize)
{
	SumFoo sf(fArray);
	parallel_reduce( blocked_range<size_t>(0, nSize, 100), sf);
	return sf.sum;
}


通过上面的例子知道: parallel_reduce的定义与parallel_for类似,但parallel_reduce却与其也有很大的不同点:

1)operator()是非const

parallel_reduce必须对SumFoo::sum进行更新,以便后面执行join()时使用。

2)SumFoo有一个带有split类的构造函数

带有split类的SumFoo构造函数,split参数用于原对象的引用,用于区分copy构造函数。

3)join()操作

当任何一个subtask执行完成时就会调用join()方法,该方法将subtask执行完的结果merge到main body中。

parallel_reduce执行流程如下图所示:



具体来说就是:当任务调度器发现有可供调度的工作线程时,parallel_reduce就调用代用split的构造函数为处理器创建一个子任务(Invoking the splitting constructor to create a subtask for the processor);当子任务执行完成,parallel_reduce则调用join()方法累加子任务的结果。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: