支持多线程方法来构建数组中所有元素的集合吗

Stand multi-threaded approach to build the set of all elements in an array?

本文关键字:元素 集合 方法 多线程 构建 数组 支持      更新时间:2023-10-16

我有一个要哈希的元素数组(它是一个模板数组;如果你喜欢,也可以是一个向量)和一个空哈希表。我有一个有几个核心(和超线程)的CPU,我想尽可能地利用它将所有数组元素插入到集合中。STL(或Boost或其他免费库)中是否有代码可以做到这一点?

我意识到一些琐碎的解决方案是:

  1. 使用并发/线程安全集(例如hash-backed),并让每个线程插入数组的一部分
  2. 让每个线程创建自己的集合,然后重复计算集合并集

但重点是我宁愿不写自己的代码,而是选择常用的代码编辑此外,我想要一个不需要我使用某些特定线程管理/池系统的解决方案,但我可以将其用于我的任意线程。

注意:

  • 不用说,集合插入不会插入重复副本
  • 数组可能有重复项(事实上,我希望集合元素的数量小于数组长度的1%,但不能总是这样)
  • 该套件不需要支持元件移除,或者可能速度较慢等

在http://www.threadingbuildingblocks.org.特别地,有concurrent_unordered_set和其他并发友好的容器,以及函数模板(例如parallel_forparallel_for_each),以便于编写并行代码。TBB是开源和跨平台的。

同样的功能也存在于微软的并行模式库(ppl)中。

将矢量元素插入concurrent_unordered_set的一些代码草图。该代码使用最新版本的TBB进行了测试,但为了简洁起见,省略了一些部分。

#include <tbb/tbb.h>
#include <tbb/concurrent_unordered_set.h> // missing in tbb.h
int main() {
std::vector<MyDataType> v;
tbb::concurrent_unordered_set<MyDataType> s;
/* (1) */
tbb::parallel_for_each( v.begin(), v.end(), [&](const MyDataType& item){
s.insert(item);
} );
/* (2) */
tbb::parallel_for( size_t(0), size_t(v.size()), [&](size_t i){
s.insert(v[i]);
} );
/* (3) */
tbb::parallel_for(
tbb::blocked_range<std::vector<MyDataType>::iterator>(v.begin(), v.end()),
[&](const tbb::blocked_range<std::vector<MyDataType>::iterator>& range){
s.insert(range.begin(), range.end()); // inserts a sequence
}
);
return 0;
} // main

变体(1)是最简单的,但也是最慢的,因为parallel_for_each当前不聚合循环迭代的处理。在这段代码中,单个迭代中的工作量太小,无法证明任务创建和执行的开销是合理的。

变体(2)使用parallel_for,它在单个任务中聚合多个迭代,因此速度更快,但仍然非常简单。

变体(3)是最快的,但也是最冗长的。它显式地使用blocked_range,从而向用户的代码公开聚合。这样做的好处是,给定范围内的所有向量元素都可以通过一次调用插入到集合中。它增加了几个百分点的性能,并且一些冗长可以用例如typedefs来隐藏。

免责声明:我是TBB开发人员。