首页 > 解决方案 > 为什么 OMP 嵌套并行执行的输出与线性执行不同?

问题描述

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

线性执行(左)vs并行执行(右)

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

我裁剪了执行此任务的代码的“关键”部分,希望有人知道可能是什么原因造成的。

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++cmultithreadingparallel-processingopenmp

解决方案


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

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;
    }
}

当然,您需要检查已裁剪代码中的竞态条件


推荐阅读