【问题标题】:Why does OMP nested parallelism execution outputs differently than linear execution?为什么 OMP 嵌套并行执行的输出与线性执行不同?
【发布时间】:2021-06-30 03:36:37
【问题描述】:

我试图在以线性方式和并行方式检测图像边缘时比较执行时间值。一切都以线性方式正常工作,但以并行方式写入的图像在图像的一部分中有太多的白色像素。为了更好地表达我的意思,请参见下图:

左图是线性执行代码的输出,右图是使用并行。您可以在两个图像中看到建筑物的边缘,而右侧图像的底部靠近其边界的部分没有相同的问题,其余部分没有。

我裁剪了执行此任务的代码的“关键”部分,希望有人知道可能导致此问题的原因。

omp_set_nested(1);
#pragma omp parallel
while(col<cols-1) {
    line = 1;
    #pragma omp parallel
    while(line<lines-1) {
        gradient_x = 0;
        gradient_y = 0;
        for(int m = 0; m < mask_size; m++) {
            for(int n = 0; n < mask_size; n++) {
                int np_x = line + (m - 1);
                int np_y = col + (n - 1);

                float v = img(np_y,np_x);

                int mask_index = (m*3) + n;

                gradient_x = gradient_x + (x_mask[mask_index] * v);
                gradient_y = gradient_y + (y_mask[mask_index] * v);
            }
        }
        float gradient_sum = sqrt((gradient_x * gradient_x) + (gradient_y * gradient_y));
        if(gradient_sum >= 255) {
            gradient_sum = 255;
        } else if(gradient_sum <= 0) {
            gradient_sum = 0;
        }
        output(line, col) = gradient_sum;
        #pragma omp critical
        line++;
    }
    #pragma omp critical
    col++;
}

我将 line 和 col 变量定义为关键变量,因为它们用于读取和写入数据,而且我相信其他一切都正常工作。

【问题讨论】:

    标签: c++ c multithreading parallel-processing openmp


    【解决方案1】:

    没有更多上下文,很难说。尽管如此,这两个嵌套的并行区域没有意义,因为您没有在线程之间分配任务;相反,您只是由多个线程执行相同的代码,可能在变量gradient_x 和gradient_y 等的更新上出现race-conditions。从以下更简单的并行代码开始:

    omp_set_nested(0);
    while(col<cols-1) {
        line = 1;
        while(line<lines-1) {
            gradient_x = 0;
            gradient_y = 0;
            #pragma omp parallel for reduction(+:gradient_x,gradient_y)
            for(int m = 0; m < mask_size; m++) {
                for(int n = 0; n < mask_size; n++) {
                    int np_x = line + (m - 1);
                    int np_y = col + (n - 1);
                    float v = img(np_y,np_x);
                    int mask_index = (m*3) + n;
    
                    gradient_x = gradient_x + (x_mask[mask_index] * v);
                    gradient_y = gradient_y + (y_mask[mask_index] * v);
                }
            }
            float gradient_sum = sqrt((gradient_x * gradient_x) + (gradient_y * gradient_y));
            if(gradient_sum >= 255) {
                gradient_sum = 255;
            } else if(gradient_sum <= 0) {
                gradient_sum = 0;
            }
            output(line, col) = gradient_sum;
            line++;
        }
        col++;
    }
    

    您可以尝试以下方法:

    #pragma omp parallel for collapse(2)
    for(int col = 0; col<cols-1; col++) {
        for(int line = 1; line<lines-1; line++) {
            float gradient_x = 0;
            float gradient_y = 0;
            for(int m = 0; m < mask_size; m++) {
                for(int n = 0; n < mask_size; n++) {
                    int np_x = line + (m - 1);
                    int np_y = col + (n - 1);
                    float v = img(np_y,np_x);
                    int mask_index = (m*3) + n;
                    gradient_x = gradient_x + (x_mask[mask_index] * v);
                    gradient_y = gradient_y + (y_mask[mask_index] * v);
                }
            }
            float gradient_sum = sqrt((gradient_x * gradient_x) + 
                                      (gradient_y * gradient_y));
            if(gradient_sum >= 255) {
                gradient_sum = 255;
            } else if(gradient_sum <= 0) {
                gradient_sum = 0;
            }
            output(line, col) = gradient_sum;
        }
    }
    

    当然,你需要检查你裁剪的代码中的race-condition。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-15
      • 2010-11-29
      • 2018-04-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多