为何OpenMP归约报错‘未找到avgs的用户自定义归约’?
解决OpenMP数组归约的错误问题
错误原因
OpenMP默认的reduction(+:var)只支持int、long这类基本数据类型,而avgs是指向数组的指针,OpenMP没有内置的数组归约规则,因此会抛出user defined reduction not found for 'avgs'的错误。另外原代码里的count变量存在竞态条件,多线程同时自增会导致结果错误。
方案一:手动实现线程私有数组与汇总
这种方式兼容性更好,不依赖高版本OpenMP:
void parallel_avg_pixel(long img[DIM_ROW][DIM_COL][DIM_RGB], long *avgs) { int row, col, pixel; // 直接计算总像素数,避免竞态问题 const long total_pixels = DIM_ROW * DIM_COL; // 初始化avgs为0 for (pixel = 0; pixel < DIM_RGB; pixel++) { avgs[pixel] = 0; } #pragma omp parallel { // 每个线程创建私有临时数组,独立累加负责行的像素值 long private_avgs[DIM_RGB] = {0}; #pragma omp for nowait for (row = 0; row < DIM_ROW; row++) { for (col = 0; col < DIM_COL; col++) { for (pixel = 0; pixel < DIM_RGB; pixel++){ private_avgs[pixel] += img[row][col][pixel]; } } } // 临界区安全汇总线程私有数组到全局avgs #pragma omp critical { for (pixel = 0; pixel < DIM_RGB; pixel++) { avgs[pixel] += private_avgs[pixel]; } } } // 计算平均值 for (pixel = 0; pixel < DIM_RGB; pixel++) { avgs[pixel] /= total_pixels; } }
核心改动
- 直接通过
DIM_ROW * DIM_COL计算总像素数,规避count变量的竞态风险 - 每个线程分配私有数组
private_avgs,避免多线程直接修改全局数组的冲突 - 用
critical指令保证汇总操作的原子性,确保结果正确
方案二:使用OpenMP自定义归约(OpenMP 4.0+)
如果编译器支持OpenMP 4.0及以上,可以自定义数组归约规则:
// 定义针对long类型数组的加法归约操作 #pragma omp declare reduction(avg_reduction : long[DIM_RGB] : \ for (int i = 0; i < DIM_RGB; i++) omp_out[i] += omp_in[i]) \ initializer( \ for (int i = 0; i < DIM_RGB; i++) omp_priv[i] = 0) void parallel_avg_pixel(long img[DIM_ROW][DIM_COL][DIM_RGB], long *avgs) { int row, col, pixel; const long total_pixels = DIM_ROW * DIM_COL; // 初始化avgs为0 for (pixel = 0; pixel < DIM_RGB; pixel++) { avgs[pixel] = 0; } #pragma omp parallel for reduction(avg_reduction: avgs) for (row = 0; row < DIM_ROW; row++) { for (col = 0; col < DIM_COL; col++) { for (pixel = 0; pixel < DIM_RGB; pixel++){ avgs[pixel] += img[row][col][pixel]; } } } // 计算平均值 for (pixel = 0; pixel < DIM_RGB; pixel++) { avgs[pixel] /= total_pixels; } }
核心改动
- 用
#pragma omp declare reduction定义名为avg_reduction的归约规则,明确数组的加法逻辑和初始化方式 - 并行循环中使用自定义的
avg_reduction替代默认加法归约,让OpenMP正确处理数组的归约逻辑
内容的提问来源于stack exchange,提问作者rabbitcoder
相关产品推荐
相关产品推荐

