并行求和一个数组

Posted

技术标签:

【中文标题】并行求和一个数组【英文标题】:Summing up an array in parallel 【发布时间】:2016-09-15 20:35:25 【问题描述】:

我有以下算法对数组元素求和:

// global
index = 0
array = [...]
total_sum = 0 // this is what we're interested in

// per thread
thread_sum = 0
mutex.lock()
while (index < array.size) 
  mutex.unlock()

  thread_sum += array[index]

  mutex.lock()
  index++

total_sum += thread_sum
mutex.unlock()

每个线程都运行相同的代码,并在完成后立即加入主线程。问题是有时不止一个线程添加相同的数字。这是怎么发生的?

原始代码是 C++ 并使用 std::vector/thread/mutex/ref。

【问题讨论】:

完全不要使用线程。你正在扼杀表演。并且每个元素的锁定只会让它变得更糟。 那么,你想用多个线程对单个数组的所有元素求和吗? 【参考方案1】:

在释放锁之前增加index,否则多个线程可能看到相同的值:

// per thread
thread_sum = 0
mutex.lock()
while (index < array.size) 
  i = index++
  mutex.unlock()

  thread_sum += array[i]

  mutex.lock()

total_sum += thread_sum
mutex.unlock()

再一次,如果您使用atomic integers,原子地更改整数的值可以更有效地完成。

最后考虑在单个工作负载很小或非常可预测时进行批处理,以减少同步的开销。

【讨论】:

我在重新锁定后增加索引。这还不够好吗?有什么区别? 在循环体内部的线程重新加锁之前,另一个线程可能会获得锁并以相同的值进入循环体。

以上是关于并行求和一个数组的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的多线程并行求和函数的向量受限于线程数?

使用分支/合并框架执行并行求和

向量的并行求和

C++ Armadillo 和 OpenMp:外积求和的并行化 - 定义 Armadillo 矩阵的约简

并行减少(例如求和)hpx::futures<double> 的向量

对数组元素求和