使用OpenMP归约数组触发SIGSEGV错误的原因及解决方法
错误原因与解决方法
错误原因
你代码里的#pragma omp parallel for reduction(+:arr[x][:Ny])是非法的OpenMP语法:
- OpenMP的
reduction子句仅支持单个标量变量,不支持数组切片(arr[x][:Ny]这种形式)。 - 编译器无法识别这种错误写法,导致内部处理时出现内存访问越界,最终触发
SIGSEGV段错误。
另外,你的场景里每个线程处理的y索引互不重叠,完全不需要reduction——reduction是用于多个线程对同一变量累加的场景,这里每个arr[x][y]只被一个线程修改,不存在竞争。
解决方法
直接移除错误的reduction子句即可修正代码,修改后的并行循环部分如下:
for (int x = 0; x < Nx; ++x) { #pragma omp parallel for for (int y = 0; y < Ny; ++y) { arr[x][y] += 1; } }
额外优化建议
- 二维指针数组的内存是分散的,对缓存不友好,会降低并行效率。可以改用一维数组模拟二维结构:
// 分配连续内存 double *arr = new double[Nx * Ny](); // 访问时用 arr[x * Ny + y] 代替 arr[x][y]
- 也可以把外层的
x循环也并行化,进一步提升效率(注意内层循环的粒度,避免线程开销过大):
#pragma omp parallel for collapse(2) for (int x = 0; x < Nx; ++x) { for (int y = 0; y < Ny; ++y) { arr[x][y] += 1; } }
内容的提问来源于stack exchange,提问作者Peter
相关产品推荐
相关产品推荐

