0

我正在使用 Intel TBB parallel_for 来加速 for 循环进行一些计算:

tbb::parallel_for(tbb::blocked_range<int>(0,ListSize,1000),Calc);

Calc 是 doCalc 类的对象

class DoCalc
{
vector<string>FileList;
public:
    void operator()(const tbb::blocked_range<int>& range) const{
    for(int i=range.begin(); i!=range.end();++i){
    //Do some calculations
    }
    }
    DoCalc(vector<string> ilist):FileList(ilist){}
};

大约需要。当我使用 for 循环的标准串行形式时,大约需要 60 秒。当我使用 TBB 的 parallel_for 完成工作时,需要 20 秒。使用标准时,我的 i5 CPU 的每个内核的负载约为。15%(根据 Windows 任务管理器)并且非常不均匀,大约为 15%。50% 并且在使用 parallel_for 时非常均匀。

我想知道在使用 parallel_for 时是否可以获得更高的核心负载。除了grain_size还有其他参数吗?如何在不更改 for 循环中的操作的情况下提高 parallel_for 的速度(此处为//在上面的代码示例中进行一些计算)。

4

3 回答 3

1

粒度参数是可选的。如果未指定 grainsizee,则应为算法模板提供分区器。分区器是指导范围分块的对象。auto_partitioner 提供了一种替代方法,可以启发式地选择粒度大小,这样您就不必指定一个。启发式尝试限制开销,同时仍为负载平衡提供充足的机会。

获取更多信息,请访问 tbb 网站。www.threadingbuildingblocks.org

于 2012-12-12T16:57:41.287 回答
0

您的问题的答案还取决于算法中内存访问和计算之间的比率。如果您对大量数据执行很少的操作,那么您的问题是内存受限,这将限制核心负载。另一方面,如果您用很少的数据进行大量计算,那么您改进的机会就更大。

于 2013-02-14T14:13:40.743 回答
0

正如@Eugene Roader 已经建议的那样,您可能希望使用 auto_partitioner (这是 TBB 版本 2.2 的默认设置)来自动分块范围:

tbb::parallel_for(tbb::blocked_range<int>(0,ListSize),Calc,tbb:auto_partitioner());

我假设您的 i5-CPU 有 4 个内核,因此您获得了 3 倍的加速(60 秒 => 20 秒),这已经“相当不错”了,因为并行化中可能存在某些开销。一个问题可能是 CPU 的内存带宽的最大限制,它被 3 个线程饱和 - 或者您可能有很多分配/解除分配,这些分配/取消分配是/必须在线程之间与标准内存管理器同步。在内部循环中没有太多代码更改的情况下解决这个问题的一个技巧可能是使用线程本地分配器,例如对于 FileList:

vector<string,tbb:scalable_allocator<string>> FileList;

请注意,您也应该为循环中使用的所有其他容器尝试 tbb::scalable_allocator,以使您的并行化加速更接近内核数 4。

于 2013-02-22T23:48:07.403 回答