c++ - 为什么 OMP 嵌套并行执行的输出与线性执行不同?
问题描述
我试图在以线性方式和并行方式检测图像边缘时比较执行时间的值。一切都以线性方式正常工作,但以并行方式写入的图像在图像的一部分中有太多的白色像素。为了更好地表达我的意思,请参见下图:
左图是线性执行代码的输出,右图是使用并行性。您可以在两个图像中看到建筑物的边缘,而右侧图像靠近其边界的底部没有相同的问题,其余部分没有相同的问题。
我裁剪了执行此任务的代码的“关键”部分,希望有人知道可能是什么原因造成的。
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 变量定义为关键变量,因为它们用于读取和写入数据,而且我相信其他一切都正常工作。
解决方案
没有更多的上下文,很难说。尽管如此,这两个嵌套的并行区域没有意义,因为您没有在线程之间分配任务;相反,您只是由多个线程执行相同的代码,变量更新等可能存在竞争条件。从以下更简单的并行代码开始:gradient_x
gradient_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;
}
}
当然,您需要检查已裁剪代码中的竞态条件。
推荐阅读
- javascript - 错误 Javascript ReferenceError: 要求未在 miIO 设备库中定义
- ios - 无法将“__NSArray0”类型的值转换为“NSDictionary”
- python - 无法在 cmd 中执行带有 .py 扩展名的 python 脚本
- c# - HttpClient GetAsync 与 URL 中的哈希
- javascript - 异步/等待无法在 javascript 中进行 fetch API 调用
- c# - 需要帮助了解使用 LINQ Join 和 HashSet 的意外行为
- sql - 协助 SQL Server SELECT 查询
- php - 如何在sql中使用超过2个外键显示数据?
- awk - 将 file1 的 id 替换为 file2 的 id
- c++ - CMake - 来自 find_path 的错误 _INCLUDE_DIR 和来自 find_library 的错误 _LIB_DIR