gpt4 book ai didi

c++ - TBB 线程本地集使用可组合的还是可枚举的_thread_specific?

转载 作者:行者123 更新时间:2023-11-30 05:43:19 27 4
gpt4 key购买 nike

我想在大型数据集上运行 tbb::parallel_for 并生成一个唯一的集。 parallel_for 主体中包含一些额外的逻辑,用于确定原始数据集的每个子元素是否应包含在该集合中。结果集通常比原始数据集小得多,我宁愿不计算具有重复项的 vector 并在之后删除重复项,因为这会增加内存使用量。

我的第一个实现使用 tbb::concurrent_unordered_set 并且通过分析我注意到 set.insert() 方法中的一个显着性能瓶颈。

我尝试改进这一点是尝试使用线程本地存储为每个线程生成一个集合,然后在最后组合这些集合以删除原子。

尽管阅读了大量文档,但我仍然不确定 tbb::combinable 或 tbb::enumerable_thread_specific 哪个最适合。

这一定是一个相当常见的用例。有人可以提供示例实现或指出我可以查看的在线示例吗?

最佳答案

我认为您的方向是正确的。并发哈希表对于大量元素(数千)是有效的。虽然您仍然可以尝试在运行算法之前保留足够的容量并使用 concurrent_unordered_set 的负载因子(设置为 1)并尝试 concurrent_hash_map(它更快在不带accessor的情况下使用insert(value)时,也需要预留一些容量。

tbb::combinabletbb::enumerable_thread_specific 使用相同的后端实现。区别仅在于界面。 documentation有后者的例子,我重新设计了一下:

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 顺序步骤,同时组合线程特定值需要顺序访问所有 P 元素)。

关于c++ - TBB 线程本地集使用可组合的还是可枚举的_thread_specific?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30275431/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com