多线程向量和

时间:2018-01-09 15:06:41

标签: c++ multithreading scalability

这是一个用于多线程向量和的C ++ 11代码。

#include <thread>

template<typename ITER>
void sum_partial(ITER a, ITER b, double & result) {
  result = std::accumulate(a, b, 0.0);
}

template<typename ITER>
double sum(ITER begin, ITER end, unsigned int nb_threads) {
  size_t len = std::distance(begin, end);
  size_t size = len/nb_threads;

  std::vector<std::thread> thr(nb_threads-1);
  std::vector<double> r(nb_threads);
  size_t be = 0;
  for(size_t i = 0; i < nb_threads-1; i++) {
    size_t en = be + size;
    thr[i] = std::thread(sum_partial<ITER>, begin + be, begin + en, std::ref(r[i]));
    be = en;
  }
  sum_partial(begin + be, begin + len, r[nb_threads-1]);
  for(size_t i = 0; i < nb_threads-1; i++)
    thr[i].join();
  return std::accumulate(r.begin(), r.end(), 0.0);
}

典型用途为sum(x.begin(), x.end(), n)x为双倍向量。

这是一个图表,显示计算时间作为线程数的函数(求和10⁷值的平均时间,在没有其他运行的8核计算机上 - 我在32核计算机上试过,行为非常相似)。

enter image description here

为什么可扩展性如此差?可以改进吗?

我(非常有限)的理解是,要获得良好的可伸缩性,线程应避免在同一缓存行中写入。这里所有的线程都在r写一次,在计算的最后,我不会指望它是限制因素。这是内存带宽问题吗?

1 个答案:

答案 0 :(得分:3)

accumulate对cpu算术单元的使用率很低,但缓存和内存吞吐量很可能是瓶颈,特别是对于10 ^ 7 double或1000万double = 80MB数据,这比你的CPU更多缓存大小。

要克服缓存和内存吞吐量瓶颈,您可能需要enable prefetch -fprefetch-loop-arrays,甚至手动执行某些程序集。