Openmp 没有加速并行循环

Jac*_*arf 3 c parallel-processing performance multithreading openmp

我有以下令人尴尬的并行循环

//#pragma omp parallel for
for(i=0; i<tot; i++)
    pointer[i] = val;
Run Code Online (Sandbox Code Playgroud)

为什么取消注释 #pragma 行会导致性能下降?当我使用 openmp 并行化这个 for 循环时,我的程序运行时间略有增加。既然每次访问都是独立的,那岂不是大大提高了程序的速度?

是否有可能如果这个 for 循环没有针对较大的 tot 值运行,开销是否会减慢速度?

dre*_*ash 5

在共享内存环境中使用多线程实现性能通常取决于:

  1. 任务粒度
  2. 并行任务之间的负载平衡
  3. 使用的并行任务数/内核数
  4. 并行任务之间的同步量;
  5. 算法的边界类型;
  6. 机器架构

我将简要概述上述每一点。

  1. 您需要检查并行任务粒度是否足以克服并行化的开销例如,线程创建和同步)。也许你的循环的迭代次数和计算量pointer[i] = val;不足以证明线程创建的开销是合理的;但值得注意的是,过大的任务粒度也会导致问题,例如负载不平衡。

  2. 您必须测试负载平衡(每个线程的工作量)。理想情况下,每个线程应该计算相同的工作量。在您的代码示例中,这没有问题;

  3. 你在使用超线程吗?!您是否使用了比内核更多的线程?!因为,如果你是,线程将开始“竞争”资源,这会导致性能下降;

  4. 通常,人们希望减少线程之间的同步量。因此,有时会使用更细粒度的同步机制甚至数据冗余(以及其他方法)来实现这一目标。您的代码没有这个问题。

  5. 在尝试并行化您的代码之前,您应该分析它是否受内存限制、受 CPU 限制,等等。如果它受内存限制,您可以在处理并行化之前先提高缓存使用率。对于此任务,强烈建议使用分析器。

  6. 为了充分利用下划线架构,多线程方法需要解决该架构的约束。例如,在SMP架构中实现高效的多线程方法与在架构中执行是不同的NUMA。由于在后者中,必须考虑内存亲和力

编辑:@Hristo lliev 的建议

  1. 线程亲和性:“将线程绑定到核心可以提高整体性能,甚至在 NUMA 系统上更能提高性能,因为它提高了数据局部性。”

顺便说一句,我建议您阅读这篇英特尔多线程应用程序开发指南。