多线程的循环大小是多少?

What loop size to multithread?

想象一个简单的循环:

constexpr int N; // some big number

#pragma omp parallel for
for(int i=0; i<N; ++i)
{
    // some not very demanding computation like
    // c[i] = a[i] + b[i]
}

我如何确定(大约)这样的循环是否适合在大小 N 方面进行并行化?

例如,如果我有一个 20 核 CPU,这个 #pragma 与普通版本相比在 N = 400 的速度方面没有任何变化。 但是它显然适用于 N = 1e+7.

之类的东西

关于 hardware/operation cost/etc 我应该了解什么来估计多线程的加速(或减速)?

选择并行化是否适合给定的代码段显然没有经验法则,只是因为它确实依赖于太多的东西:

  • 您真的需要额外的性能吗?也许您的代码在 147 毫秒而不是 23 毫秒内完全没问题 运行?也许您还关心代码的可读性?能量消耗?如果您的程序 运行 与许多其他程序一样,占用计算机资源也许不是一个好主意?
  • Amdahl's law 告诉您,即使您的大部分代码可能 运行 并行,一小部分单线程代码也足以极大地限制您的性能扩展
  • 任务本身:即使是简单的任务,数据访问是怎样的?它缓存友好吗?你怎么写你的数据?你需要在线程之间同步吗?也许您的算法很复杂并且可以做得更快?等等
  • 编译器优化:例如,您的编译器可能会自动矢量化您的循环以利用您的处理器 AVX 支持。在这种情况下,实际的“工作量”可能远低于您的 N
  • 关于 OpenMP,大多数实现会在程序启动时分配一个线程池。因此,您只需在 运行 时间支付“少量”费用即可分派任务。当然,如果实际做任务的时间比派发时间还少,并行化显然不值得

长话短说:了解并行化是否值得的唯一方法是尝试并衡量性能。幸运的是,#pragma omp parallel for编写和测试速度非常快。

有关并行效率和可扩展性的更多信息,我向您推荐此演示文稿:https://www.nersc.gov/assets/Uploads/Profiling-and-Scaling.pdf