OpenMP开销计算

5

给定n个线程,有没有一种方法可以计算在OpenMP中实现特定指令所需的开销(例如循环次数)。

例如,给定以下代码

 #pragma omp parallel
 {
    #pragma omp for
    for( int i=0 ; i < m ; i++ )
       a[i] = b[i] + c[i];
 }

我能否计算一下创建这些线程需要多少额外开销呢?

2个回答

5
我认为衡量开销的方法是计算串行和并行版本的时间,然后比较并行版本与其理想运行时间的差距。例如,如果串行版本需要10秒钟,而你有4个线程在4个核心上运行,则你的理想运行时间为2.5秒。如果你的OpenMP版本需要4秒钟,则你的“开销”为1.5秒钟。这里的“开销”用引号括起来,因为其中一部分将是线程创建和内存共享(实际的线程开销),另一部分则只是未并行化的代码部分。我试图从Amdahl's Law的角度思考。
以下是两个示例,它们没有测量线程创建开销,但可以展示预期和实际改进之间的差异。虽然Mystical正确地指出唯一真正的衡量方法是计时,但即使像您的for循环这样的简单示例也不一定会受到内存限制。OpenMP做了我们看不到的很多工作。

串行(speedtest.cpp)

#include <iostream>

int main(int argc, char** argv) {
  const int SIZE = 100000000;
  int* a = new int[SIZE];
  int* b = new int[SIZE];
  int* c = new int[SIZE];

  for(int i = 0; i < SIZE; i++) {
    a[i] = b[i] * c[i] * 2;
  }

  std::cout << "a[" << (SIZE-1) << "]=" << a[SIZE-1] << std::endl;

  for(int i = 0; i < SIZE; i++) {
    a[i] = b[i] + c[i] + 1;
  }

  std::cout << "a[" << (SIZE-1) << "]=" << a[SIZE-1] << std::endl;

  delete[] a;
  delete[] b;
  delete[] c;

  return 0;
}

并行(omp_speedtest.cpp)

#include <omp.h>
#include <iostream>

int main(int argc, char** argv) {
  const int SIZE = 100000000;
  int* a = new int[SIZE];
  int* b = new int[SIZE];
  int* c = new int[SIZE];

  std::cout << "There are " << omp_get_num_procs() << " procs." << std::endl;

  #pragma omp parallel
  {
    #pragma omp for
    for(int i = 0; i < SIZE; i++) {
      a[i] = b[i] * c[i];
    }
  }

  std::cout << "a[" << (SIZE-1) << "]=" << a[SIZE-1] << std::endl;

  #pragma omp parallel
  {
    #pragma omp for
    for(int i = 0; i < SIZE; i++) {
      a[i] = b[i] + c[i] + 1;
    }
  }

  std::cout << "a[" << (SIZE-1) << "]=" << a[SIZE-1] << std::endl;

  delete[] a;
  delete[] b;
  delete[] c;

  return 0;
}

所以我用编译器将它们编译在一起

g++ -O3 -o speedtest.exe speedtest.cpp
g++ -fopenmp -O3 -o omp_speedtest.exe omp_speedtest.cpp

当我运行它们时

$ time ./speedtest.exe
a[99999999]=0
a[99999999]=1

real    0m1.379s
user    0m0.015s
sys     0m0.000s

$ time ./omp_speedtest.exe
There are 4 procs.
a[99999999]=0
a[99999999]=1

real    0m0.854s
user    0m0.015s
sys     0m0.015s

谢谢您的回复。看起来我可能需要进行一系列测试,以了解这种开销成本会是多少。我正在尝试执行一些自动并行化,并希望有一个资源指定线程创建等定义的周期数,以便我可以评估开销成本与操作成本之间的差异,以确定是否有并行化的优势。 - entitledX

4
是的,你可以。请看一下EPCC基准测试。虽然这段代码有些陈旧,但它可以测量OpenMP结构的各种开销,包括omp parallel foromp critical
基本方法非常简单直接。您可以测量不使用任何OpenMP的基线串行时间,并且只包含您要测量的OpenMP编译指示符。然后,减去经过的时间。这正是EPCC基准测试如'syncbench.c'所示的方式来测量开销。
请注意,开销以时间表示,而不是#周期数。我也尝试过测量周期数,但是由于同步造成的阻塞时间可能包括在OpenMP并行结构的开销中。因此,周期数可能无法反映OpenMP的真实开销。

这不是“测量”而不是“计算”吗?就我个人而言,我认为测量比尝试计算要好得多,但我们应该明确区分(特别是当涉及到我们可能无法直接访问的硬件时)。 - Toby Speight

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接