Тот факт, что вы используете OpenMP, не означает, что ваша программа будет работать быстрее. Здесь может произойти несколько вещей:
Существует стоимость, связанная с созданием каждого потока, и если вы создаете поток для выполнения небольшого объема вычислений, создание самого потока займет больше времени, чем вычисление.
По умолчанию OpenMP создаст максимальное количество потоков, поддерживаемое вашим процессором. С процессорами, которые поддерживают 2 или более потоков на ядро, потоки будут конкурировать за ресурсы каждого ядра. Используя omp_get_num_threads()
, вы можете увидеть, сколько потоков будет создано по умолчанию. Я рекомендую попробовать запустить ваш код с половиной этого значения, используя omp_set_num_threads()
.
Вы подтвердили, что результаты были одинаковыми с OpenMP и без него? Кажется, есть зависимость с переменными j и c2. Вы должны объявить их приватными для каждого потока:
#pragma omp parallel for private(j,c2)
Я хотел добавить еще одну вещь: прежде чем пытаться распараллелить, вы должны убедиться, что код уже оптимизирован.
В зависимости от вашего компилятора, флагов компилятора и сложности инструкции компилятор может оптимизировать ваш код, а может и нет:
// avoid calculation nnoib-2 every iteration
int t_nnoib = nnoib - 2;
for (i=2; i< t_nnoib; ++i){
// avoid calculation nnojb-2 every iteration
int t_nnojb = nnojb - 2;
// avoid loading absi[i] every iteration
int t_absi = absi[i];
for (j=2; j< t_nnojb; ++j) {
C[i][j]= t_absi * absj[j] *
(2.0f*B[i][j] + t_absi * absj[j] *
(VEL[i][j] * VEL[i][j] * fat *
(16.0f * (B[i][j-1] + B[i][j+1] + B[i-1][j] + B[i+1][j])
-1.0f * (B[i][j-2] + B[i][j+2] + B[i-2][j] + B[i+2][j])
-60.0f * B[i][j]
) - A[i][j]));
// c2 is a useless variable
if (abs(C[i][j]) > Amax[i][j]) {
Amax[i][j] = abs(C[i][j]);
Ttra[i][j] = t;
}
}
}
Это может показаться незначительным, но это может оказать огромное влияние на ваш код. Компилятор попытается поместить локальные переменные в регистры (которые имеют гораздо более быстрое время доступа). Имейте в виду, что вы не можете применять эту технику бесконечно, поскольку у вас ограниченное количество регистров, и злоупотребление этим приведет к тому, что ваш код будет страдать от утечки регистров.
В случае с массивом absi
вы избежите того, чтобы система хранила часть этого массива в кеше во время выполнения цикла j
. Общая идея этого метода состоит в том, чтобы перемещать во внешний цикл любой доступ к массиву, который не зависит от переменной внутреннего цикла.
person
Cristiano Sousa
schedule
10.03.2013
c2
? - person Mysticial   schedule 10.03.2013c2
. - person Mysticial   schedule 10.03.2013