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 子句中命名,newold 应在 声明内部 for 循环。