OpenMP 开销计算

ent*_*edX 4 c++ parallel-processing openmp

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

例如,给定下面的代码

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

我可以以某种方式计算创建这些线程需要多少开销吗?

Ste*_*ell 5

我认为测量开销的方法是对串行和并行版本进行计时,然后查看并行版本与线程数量的“理想”运行时间相差多远。

例如,如果您的串行版本需要 10 秒,并且您在 4 个内核上有 4 个线程,那么您的理想运行时间是 2.5 秒。如果您的 OpenMP 版本需要 4 秒,那么您的“开销”就是 1.5 秒。我将开销放在引号中,因为其中一些将是线程创建和内存共享(实际线程开销),而其中一些将只是无与伦比的代码部分。我试图从阿姆达尔定律的角度来思考。

为了演示,这里有两个例子。它们不测量线程创建开销,但它们可能会显示预期改进和实现改进之间的差异。虽然 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;
}
Run Code Online (Sandbox Code Playgroud)

并行 (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;
}
Run Code Online (Sandbox Code Playgroud)

所以我编译了这些

g++ -O3 -o speedtest.exe speedtest.cpp
g++ -fopenmp -O3 -o omp_speedtest.exe omp_speedtest.cpp
Run Code Online (Sandbox Code Playgroud)

当我运行它们时

$ 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
Run Code Online (Sandbox Code Playgroud)


min*_*ang 4

是的你可以。请查看EPCC 基准测试。尽管此代码有点旧,但它测量了 OpenMP 构造的各种开销,包括omp parallel foromp critical

基本方法有些非常简单明了。您无需任何 OpenMP 即可测量基线串行时间,只需包含要测量的 OpenMP 编译指示即可。然后,减去经过的时间。这正是 EPCC 基准测试衡量开销的方式。请参阅“syncbench.c”等源代码。

请注意,开销表示为时间,而不是周期数。我还尝试测量周期数,但 OpenMP 并行构造的开销可能包括由于同步而导致的阻塞时间。因此,周期数可能无法反映 OpenMP 的实际开销。