(Ответ ниже относится к исходному коду в вопросе, который с тех пор был улучшен с применением этих предложений)
Вам необходимо прочитать больше о том, как использовать OpenMP.Спецификация доступна на http://www.openmp.org; и есть ссылки на учебные пособия и другие ресурсы.
Я укажу на некоторые проблемы в вашем коде и дам рекомендации, как их исправить.
float *d = malloc(3*sizeof(float));
float diff;
d
используется как временная переменная, поэтому следует пометить ее как private
в #pragma omp parallel for
(см. Ниже), чтобы избежать скачек данных.Между тем вместо динамического размещения я бы просто использовал 3 отдельных числа с плавающей точкой.diff
также содержит временное значение, поэтому также должно быть private
.
#pragma omp parallel
for(i=0;i<ncft;i+=jump){
#pragma omp parallel
for(j=0;j<ntri2;j++){
Вы создали параллельную область, в которой каждый поток выполняет весь цикл (так как область не содержит никаких конструкций совместного использования работы)и внутри него вы создали вложенную область с новым (!) набором потоков, каждый из которых выполняет весь внутренний цикл.Это добавляет много накладных и ненужных вычислений в вашу программу.Вам нужно #pragma omp parallel for
, и оно применяется только к внешнему циклу.
d[0] = vG1[i][0] - vG2[j][0];
d[1] = vG1[i][1] - vG2[j][1];
d[2] = vG1[i][2] - vG2[j][2];
diff = sqrt(pow(d[0],2) + pow(d[1],2) + pow(d[2],2));
Не связано с параллелизмом, но зачем вызывать pow
просто для вычисления квадратов?Старое доброе умножение, вероятно, будет и проще для чтения, и быстрее.
if(j==0)
dist[k] = diff;
else
if(diff<dist[k])
dist[k] = diff;
Поскольку действие одинаковое (dist[k]=diff;
), код можно упростить, комбинируя два условия с ||
(логическийили).
}
avg += dist[k];
if(dist[k]>max)
max = dist[k];
Здесь вы вычисляете агрегированные значения во внешнем цикле.В OpenMP это делается с помощью reduction
предложения #pragma omp for
.
k++;
}
В настоящее время вы увеличиваете k
на каждой итерации, создавая тем самым ненужную зависимость между итерациями, которая приводит к гонке данных впараллельный код.Согласно вашему коду, k
- это просто удобный «псевдоним» для i/jump
, поэтому просто присвойте его такому в начале итерации и сделайте private
.