Вероятно, у вас могут быть некоторые зависимости в данных, когда вы распараллеливаете внешний цикл, и компилятор не может понять это и добавляет дополнительные блокировки.
Скорее всего, он решает, что различные итерации внешнего цикла могут записываться втот же (C+(i*Nu+j))
и добавляет блокировки доступа для его защиты.
Компилятор, вероятно, может выяснить, что нет никаких зависимостей, если вы распараллелите 2-й цикл.Но выяснить, что параллелизации внешнего цикла нет зависимостей, не так тривиально для компилятора.
ОБНОВЛЕНИЕ
Некоторые измерения производительности.
Hiснова.Похоже, 1000 double *
и +
недостаточно для покрытия затрат на синхронизацию потоков.
Я провел несколько небольших тестов, и простое векторное скалярное умножение не работает с openmp, если только числоэлементов меньше ~ 10'000.По сути, чем больше ваш массив, тем больше вы получите производительности от использования openmp.
Таким образом, распараллеливая самый внутренний цикл, вам придется разделить задачу между различными потоками и собрать данные обратно 1000 000 раз.
PS.Попробуйте Intel ICC, это бесплатно для студентов и проектов с открытым исходным кодом.Я помню, как использовал openmp для меньших, чем 10 000 массивов элементов.
ОБНОВЛЕНИЕ 2: Пример сокращения
double sum = 0.0;
int k=0;
double *al = A+i*Nu;
double *bl = A+j*Nu;
#pragma omp parallel for shared(al, bl) reduction(+:sum)
for(k=0;k<Nu ;k++){
sum +=al[k] * bl[k]; //C(i,j)=sum(over k) A(i,k)*B(k,j)
}
C[i*Nu+j] = sum;