Я думаю, что способ измерения накладных расходов состоит в том, чтобы рассчитать как последовательную, так и параллельную версии, а затем посмотреть, насколько далека параллельная версия от ее «идеального» времени выполнения для вашего числа потоков.
Так, например, если ваша серийная версия занимает 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