Я пытаюсь распараллелить решатель Якоби, используя OpenMP.
Когда используется 1 поток:
В нынешнем виде код выполняется правильно, когда назначен только один поток,и выдает те же результаты, что и эталонная однопотоковая функция (не показана).
Цикл while прерывается, когда разностная переменная меньше 0,01000 (как и должно быть)
Когда два или более потоковиспользуются:
Код проходит через внешний цикл while только один раз.Значение разницы от первого потока намного выше 0,0100 (как и должно быть), но значение разности, заданное другим потоком (ами), мгновенно оказывается ниже его, поэтому цикл прерывается без выполнения каких-либо вычислений.
Я протестировал множество итераций компиляции для стратегического размещения соответствующих переменных в разделах shared / private / reduction, надеясь получить значение diff для правильного накопления во всех используемых потоках.Я понял, что переменная "diff" должна использоваться всеми потоками, но то, что я пробовал, не сработало для накопления значений из всех потоков.Я не уверен, что еще я могу попробовать?
Спасибо за ваше время и ввод
int
compute_using_omp_jacobi (grid_t *grid, int num_threads)
{
/////////////////////////////////////////////////////////
int i, j;
int num_iter = 0;
int done = 0;
double diff;
float old, new;
float eps = 1e-2; /* Convergence criteria. */
int num_elements;
omp_set_num_threads(num_threads);
#pragma omp parallel default(none) shared(grid, eps, done, diff) private ( i, j, old, new, num_elements) reduction (+:num_iter)
while(!done) { /* While we have not converged yet. */
diff = 0.0;
num_elements = 0;
#pragma omp for reduction (+: diff) collapse(2)
for (i = 1; i < (grid->dim - 1); i++)
for (j = 1; j < (grid->dim - 1); j++) {
old = grid->element[i * grid->dim + j]; /* Store old value of grid point. */
/* Apply the update rule. */
new = 0.25 * (grid->element[(i - 1) * grid->dim + j] +\
grid->element[(i + 1) * grid->dim + j] +\
grid->element[i * grid->dim + (j + 1)] +\
grid->element[i * grid->dim + (j - 1)]);
grid->element[i * grid->dim + j] = new; /* Update the grid-point value. */
diff = diff + fabs(new - old); /* Calculate the difference in values. */
num_elements++;
//printf ("DIFF %f.", diff);
}
/* End of an iteration. Check for convergence. */
diff = diff/num_elements;
printf ("Iteration %d. DIFF: %f.\n", num_iter, diff);
// printf ("number of elements %d.", num_elements);
num_iter++;
if (diff < eps)
done = 1;
}
return num_iter;
}