Просто начинайте работу с OpenMP. Мне было интересно, можно ли запустить OpenMP-параллель в цикле for, который вызывает внешнюю функцию, которая сама по себе не вызывает никакой другой функции. Я поставил некоторый упрощенный код, чтобы понять:
#pragma omp parallel for
for(span=0;span<info.nospanelement;span++)
{
some_function(info,wakePtr[time][span],P,w_ind,1);
//additions to be done each repeat
w_wake[0] += w_ind[0];
w_wake[1] += w_ind[1];
w_wake[2] += w_ind[2];
}
Я знаю, что мне нужно добавить еще немного для вызова, но может ли этот цикл OpenMp технически работать?
У вас никогда не должно быть разных потоков, которые пишут одни и те же переменные без правильной синхронизации, что позволяет избежать условий гонки.
В вашей программе несколько потоков читают одно и то же значение переменной, затем каждый добавляет к ней другое значение, затем все они записывают результат в том же месте, так что многие вычисления переписываются и не суммируются до окончательного результат. Из-за этого результаты, рассчитанные вашей программой, ниже, чем правильные значения (кстати, вы должны точно указать, как результат вашей программы отличается от того, что вы ожидали).
Простым, но неэффективным обходным путем является использование атомных добавок:
#pragma omp parallel for
for(span=0;span<info.nospanelement;span++) {
some_function(info,wakePtr[time][span],P,w_ind,1);
//additions to be done each repeat
#pragma omp atomic
w_wake[0] += w_ind[0];
#pragma omp atomic
w_wake[1] += w_ind[1];
#pragma omp atomic
w_wake[2] += w_ind[2];
}
Более эффективный способ суммирования в параллель состоит в том, чтобы каждый поток накапливал значения в частной переменной (только видимой этим потоком), получая при этом частичные суммы.
#pragma omp parallel
{
int wake0 = wake1 = wake2 = 0; // private variables
#pragma omp for
for(span=0;span<info.nospanelement;span++)
{
some_function(info,wakePtr[time][span],P,w_ind,1);
//additions to be done each repeat
wake0 += w_ind[0]; // accumulate in private variable
wake1 += w_ind[1];
wake2 += w_ind[2];
}
// now we're out of the loop but still inside the parallel region
// so, let add up the partial sums
#pragma omp atomic
w_wake[0] += wake0;
#pragma omp atomic
w_wake[1] += wake1;
#pragma omp atomic
w_wake[2] += wake2;
}
Обычно лучше, чтобы OpenMP управлял операциями сокращения, но если вам нужно сохранить результаты в массиве, то, вероятно, проще просто сделать это самостоятельно.
С другой стороны, если вам не нужен массив, вы можете просто сделать это:
int wake0 = wake1 = wake2 = 0; // SHARED variables this time
#pragma omp parallel for reduction(+ : wake0, wake1, wake2)
{
for(span=0;span<info.nospanelement;span++)
{
some_function(info,wakePtr[time][span],P,w_ind,1);
//additions to be done each repeat
wake0 += w_ind[0]; // accumulate in private variable
wake1 += w_ind[1];
wake2 += w_ind[2];
}
}
#pragma omp parallel for reduction(+ : w_wake[0], w_wake[1], w_wake[2])
?