首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用可组合或enumerable_thread_specific的线程本地集?

使用可组合或enumerable_thread_specific的线程本地集?
EN

Stack Overflow用户
提问于 2015-05-16 12:04:06
回答 1查看 1.2K关注 0票数 2

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

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

我试图对此进行改进,尝试使用线程本地存储来生成每个线程的集合,然后将最后的集合组合起来以删除atomics。

尽管阅读了大量的文档,但我仍然不确定tbb::组合还是tbb::enumerable_thread_specific最适合。

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

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-05-16 19:05:36

我认为你走的方向是对的。并发哈希表对于大量的元素(千)是有效的。尽管在运行算法之前仍然可以尝试保留足够的容量,并使用concurrent_unordered_set的负载因子(设置为1),也可以尝试concurrent_hash_map (在没有访问器的情况下使用insert(value)更快,但也需要保留一些容量)。

tbb::combinabletbb::enumerable_thread_specific都使用相同的后端实现。不同之处仅在于界面。文档给出了后者的示例,我对其进行了一些重新设计:

代码语言:javascript
运行
复制
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元素进行顺序访问)。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30275431

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档