【问题标题】:Populating a vector in parallel, order not important并行填充向量,顺序不重要
【发布时间】:2016-12-16 20:24:19
【问题描述】:

我必须创建一个包含 k 个元素的向量。每个线程都会创建它的部分,比如说 k * 25%,并且必须将它放入向量中的任何索引处。在example 的驱使下,我正准备做这样的事情:

std::atomic<std::vector<aClass<templatedType>>> H;

但这不起作用:

/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/atomic:823:13: error: 
      _Atomic cannot be applied to type
      'std::__1::vector<StableHashFunction<int>,
      std::__1::allocator<StableHashFunction<int> > >' which is not trivially
      copyable
    mutable _Atomic(_Tp) __a_;

因为它不是简单可复制的——而且解决方法也不是很好。此外,我需要它是原子的吗?

这就是问题,当我不关心顺序时,我还应该使用原子吗?换句话说,数据竞争是否只影响元素的顺序,或者它们会导致其他副作用,比如躲避一个元素(所以最后只有 k - 1 个元素而不是 k 个元素)?

【问题讨论】:

  • push_back()emplace_back() 不是原子操作,因此您必须使用诸如 std::mutex 之类的同步机制来保护它们。
  • 创建一个大小为 K 的向量,然后每个线程更新该向量的一部分,这样就不会在线程之间共享数据。
  • @Jarod42 这也是我的第一个想法,但要做到这一点,您需要默认构造向量中的所有元素。
  • @gsamaras 好吧,如果你按照我的建议去做,那么只有在 CPU 密集型工作来计算应该用于初始化向量的值时才有意义。别担心,我只是很少投赞成票;)。
  • 顺便说一句,@πάνταῥεῖ 不是关于互斥锁的回答...如果您需要将工作负载分成不同的线程,那么您可能关心性能。如果你关心性能,你应该尽可能多地编写每个并行化,尽可能少互斥/原子少/共享内存,因为线程之间的同步非常昂贵,你可能会浪费掉通过运行节省的所有时间在平行下。所以只要你的向量计算在线程之间是独立的,确保目标内存也是,那么你就不需要任何锁定和同步,只需要等待所有线程完成+合并结果。

标签: c++ multithreading stl parallel-processing stdthread


【解决方案1】:

当您尝试并行插入项目时,只有当向量必须更改其大小时才会出现问题:并发插入必须更新内存中的相同位置,从而导致不正确的行为(崩溃、丢失项目等)

但是,同时设置现有向量的不同元素不会导致问题,因此解决此问题的常见方法是预先分配向量。

这种方法需要向量元素的默认构造函数,以及每个线程将要放入向量中的项目的确切数量的前期知识。例如,如果您知道线程 0 将放置 100 个元素,线程 1 将放置 120 个元素,线程 2 将放置 110 个元素,则您预先分配了 100+120+110 个元素的向量,并且给每个线程自己的初始索引:0、100 和 220。现在每个线程都可以将项目放入向量中,而不会遇到并发问题。

【讨论】:

  • 我对行缓存很好奇。如果索引 99 和 100 的元素在同一缓存行上会发生什么?
  • @Amadeus 这称为虚假共享,是一个有效的问题。如果线程都从头到尾,你可能看不到它。
  • @Amadeus 这应该不会造成太大问题:碰巧首先写入的核心将使另一个核心的缓存行无效,因此下次请求数据时它必须从内存中读取.你所看到的只是一个小的减速,这甚至不应该是一个问题,因为当第一个线程即将写入位置 99 时,第二个线程应该长时间完成位置 100,一直写到位置 199 左右。
【解决方案2】:

如果你想将原子与向量或其他类一起使用,你可以使用指针来代替。我认为在您的情况下,您必须使用互斥锁来使线程安全地访问向量,或者使用 TBB library 。该库具有完成任务所需的所有功能。

【讨论】:

  • 我不想使用任何库,但感谢您的提示,为可能感兴趣的未来用户 +1。
猜你喜欢
  • 1970-01-01
  • 2018-11-28
  • 1970-01-01
  • 1970-01-01
  • 2010-10-22
  • 2016-01-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多