OpenMP:While 循环内嵌套了 2 个 For 循环。如何修复多线程功能? (雅各比求解器)
OpenMP: 2 Nested For loops inside of a While loop. How to fix for multi-threaded functionality? (Jacobi Solver)
我正在尝试使用 OpenMP 并行化 Jacobi 网格求解器。
当使用 1 个线程时:
就目前而言,当仅分配一个线程时,代码会正确执行,并产生与参考单线程函数(未显示)相同的结果。
当差异变量小于“0.01000”(应该如此)时,while 循环中断
当使用两个或多个线程时:
代码仅在外部 while 循环中运行一次。
来自第一个线程的差值远远高于 0.0100(应该是),但其他线程给出的差值瞬间低于它,因此循环中断,没有进行任何计算。
我已经测试了很多编译迭代,这些迭代有策略地将各个变量放在 shared/private/reduction 子句中,希望能够在所有使用的线程上正确累积差异值。我知道 "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;
}
您无法并行化 while
循环,因为每次迭代中 grid->element
的值取决于前一次迭代的值。
您必须将 #pragma omp parallel
移动到 while 内(移动到第一个 for
循环之前)。
num_elements
应在 reduction
子句中命名,new
和 old
应在 内 声明内部 for
循环。
我正在尝试使用 OpenMP 并行化 Jacobi 网格求解器。
当使用 1 个线程时:
就目前而言,当仅分配一个线程时,代码会正确执行,并产生与参考单线程函数(未显示)相同的结果。
当差异变量小于“0.01000”(应该如此)时,while 循环中断
当使用两个或多个线程时:
代码仅在外部 while 循环中运行一次。 来自第一个线程的差值远远高于 0.0100(应该是),但其他线程给出的差值瞬间低于它,因此循环中断,没有进行任何计算。
我已经测试了很多编译迭代,这些迭代有策略地将各个变量放在 shared/private/reduction 子句中,希望能够在所有使用的线程上正确累积差异值。我知道 "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;
}
您无法并行化 while
循环,因为每次迭代中 grid->element
的值取决于前一次迭代的值。
您必须将 #pragma omp parallel
移动到 while 内(移动到第一个 for
循环之前)。
num_elements
应在 reduction
子句中命名,new
和 old
应在 内 声明内部 for
循环。