Расчет накладных расходов OpenMP - PullRequest
4 голосов
/ 14 сентября 2011

Учитывая n потоков, есть ли способ, которым я могу вычислить количество служебной информации (например, # циклов), которая требуется для реализации определенной директивы в OpenMP.

Например, с учетом приведенного ниже кода

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

Можно ли как-то рассчитать, сколько накладных расходов требуется для создания этих потоков?

Ответы [ 2 ]

4 голосов
/ 15 сентября 2011

Да, вы можете.Пожалуйста, обратите внимание на EPCC Benchmark .Хотя этот код немного старше, он измеряет различные издержки конструкций OpenMP, включая omp parallel for и omp critical.

Базовый подход несколько очень прост и понятен.Вы измеряете базовое время serial без какого-либо OpenMP и просто включаете прагму OpenMP, которую хотите измерить.Затем вычтите прошедшее время.Именно так тест EPCC измеряет накладные расходы.См. Источник как 'syncbench.c'.

Обратите внимание, что накладные расходы выражаются как время, а не как число циклов.Я также пытался измерить количество циклов, но издержки параллельных конструкций OpenMP могут включать заблокированное время из-за синхронизации.Следовательно, число циклов может не отражать реальные издержки OpenMP.

4 голосов
/ 14 сентября 2011

Я думаю, что способ измерения накладных расходов состоит в том, чтобы рассчитать как последовательную, так и параллельную версии, а затем посмотреть, насколько далека параллельная версия от ее «идеального» времени выполнения для вашего числа потоков.

Так, например, если ваша серийная версия занимает 10 секунд, а у вас 4 потока на 4 ядрах, то идеальное время работы составляет 2,5 секунды.Если ваша версия OpenMP занимает 4 секунды, тогда ваши накладные расходы составляют 1,5 секунды.Я помещаю накладные расходы в кавычки, потому что некоторые из них будут создавать потоки и разделять память (фактические накладные расходы на потоки), а некоторые из них будут просто непараллельными частями кода.Я пытаюсь мыслить здесь с точки зрения Закона Амдала .

Для демонстрации приведем два примера.Они не измеряют накладные расходы на создание потоков, но они могут показать разницу между ожидаемым и достигнутым улучшением.И хотя Mystical был прав, что единственный реальный способ измерения - это рассчитать время, даже такие тривиальные примеры, как ваш цикл for, не обязательно связаны с памятью.OpenMP выполняет большую часть работы, которую мы не видим.

Serial (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;
}

Parallel (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
...