我想在一个大数据集中运行tbb::parallel_for并生成一个唯一的集合。parallel_for主体中包含一些附加逻辑,用于确定是否应将原始数据集的每个子元素包括在该集合中。结果集通常比原始数据集小得多,我不愿计算带有重复项的向量,然后删除重复数据集,因为这样会增加内存使用量。
我的第一个实现使用tbb::concurrent_unordered_set,通过分析,我注意到set.insert()方法中的一个重要性能瓶颈。
我试图对此进行改进,尝试使用线程本地存储来生成每个线程的集合,然后将最后的集合组合起来以删除atomics。
尽管阅读了大量的文档,但我仍然不确定tbb::组合还是tbb::enumerable_thread_specific最适合。
这必须是一个相当常见的用例。有人能给我提供一个示例实现吗?或者向我指出一个我可以在线查看的示例?
发布于 2015-05-16 19:05:36
我认为你走的方向是对的。并发哈希表对于大量的元素(千)是有效的。尽管在运行算法之前仍然可以尝试保留足够的容量,并使用concurrent_unordered_set
的负载因子(设置为1),也可以尝试concurrent_hash_map
(在没有访问器的情况下使用insert(value)
更快,但也需要保留一些容量)。
tbb::combinable
和tbb::enumerable_thread_specific
都使用相同的后端实现。不同之处仅在于界面。文档给出了后者的示例,我对其进行了一些重新设计:
typedef tbb::enumerable_thread_specific< std::pair<int,int> > CounterType;
CounterType MyCounters (std::make_pair(0,0));
int main() {
tbb::parallel_for( tbb::blocked_range<int>(0, 100000000),
[](const tbb::blocked_range<int> &r) {
CounterType::reference my_counter = MyCounters.local();
++my_counter.first; my_counter.second += r.size();
});
std::pair<int,int> sum = MyCounters.combine(
[](std::pair<int,int> x, std::pair<int,int> y) {
return std::make_pair(x.first+y.first, x.second+y.second);
});
printf("Total calls to operator() = %d, "
"total iterations = %d\n", sum.first, sum.second);
}
最后,尝试另一种方法,在不需要其他方法(例如可组合)的情况下,使用tbb::parallel_reduce
,而且简化主要是并行完成的(只有log顺序步骤,而组合线程特定值则需要对所有P元素进行顺序访问)。
https://stackoverflow.com/questions/30275431
复制相似问题