Исследования проводились на 8-ядерной машине (2CPU x 4core) Intel(R) Xeon(R) CPU E5530 @ 2.40GHz под управлением операционной системы Microsoft Windows XP Professional x64 Edition Service Pack 2. Все примеры компилировались на Microsoft Visual Studio 2008 Version 9.0.30729.1 SP в конфигурацией Release, OpenMP, с полной оптимизацией, без inline-ов.
для особо любопытствующих представлю «шапку» кода с вспомогательной функцией:
#include <stdio.h>
#include <tchar.h>
#include <memory.h>
#include <math.h>
#include <omp.h>
static const int iLoopLen = 10000000;
static const int iNumThreads = 8;
static const int iFactor = 100;
static const int iArrLen = 100000;
void print_time_delta(DWORD tcStart, DWORD tcEnd)
{
const double dTime = (tcEnd-tcStart) * .001;
printf("%g s\n", dTime);
}
и перейду к делу. Предположим есть у вас большой цикл, совершающий полезное деяние (10 миллионов повторений, прошу заметить)
{
for(int i=0; i<iLoopLen; ++i) {
const int index = i%iArrLen;
pdArr[index] += fabs(i*.001-20.) * 5. + 3.;
}
}
и хочется вам его распараллелить.
{
#pragma omp parallel for num_threads(iNumThreads)
for(int i=0; i<iLoopLen; ++i) {
const int index = i%iArrLen;
const double dVal = fabs(i*.001-20.) * 5. + 3.;
#pragma omp critical
{
pdArr[index] += dVal;
}
}
}
Дело благое, и пользователь должен только сказать Вам спасибо, когда программа съест всю мощь его мультиядерной машины и отработает быстрее. Вот только быстрее-ли? Давайте проверять… Для этого используется следующая функция:
{
double dArr[iArrLen];
printf("*** Test1: 1 thread ");
{
const DWORD tcStart = GetTickCount();
for(int i=0; i<iFactor; ++i) {
f1( dArr );
}
const DWORD tcEnd = GetTickCount();
print_time_delta(tcStart, tcEnd);
}
printf("*** Test2: 8 threads (critical) ");
{
const DWORD tcStart = GetTickCount();
for(int i=0; i<iFactor; ++i) {
f2( dArr );
}
const DWORD tcEnd = GetTickCount();
print_time_delta(tcStart, tcEnd);
}
}
И получаем результат: последовательная (однопоточная) версия отрабатывает за 4.344 секунды, а параллельная (8-поточная) за … 223 секунды! Т.е. в 50 раз медленнее.
Опытный программист конечно же уже знает в чём дело, а я расскажу почему, и продолжу изыскания, в следующем выпуске.
Метки: C++, OpenMP