OpenMP collapse(5)并行5层循环结果异常的问题排查与解决
问题原因
你遇到的是整数溢出问题。当使用collapse(5)时,OpenMP会把5层循环合并成一个总迭代次数为100^5=10,000,000,000的单一迭代空间。但你的循环变量都是32位int类型,32位有符号int的最大值仅为2,147,483,647,远小于100亿。OpenMP内部计算总迭代次数时用了32位整数,直接溢出成错误数值,导致线程分配的任务量异常,最终reduction累加的结果也就错了。
而collapse≤4时,总迭代次数是100^4=100,000,000,这个数值在32位int的范围内,不会触发溢出,所以结果正确。
解决方法
最简单直接的办法是把所有循环变量的类型从int改成long long,让OpenMP用64位整数计算迭代次数,彻底避免溢出。修改后的代码如下:
void doStuff() { long long loop = 0; int a = 100; #pragma omp parallel for reduction(+:loop) collapse(5) for (long long i = 0; i < a; i++) { for (long long j = 0; j < a; j++) { for (long long k = 0; k < a; k++) { for (long long l = 0; l < a; l++) { for (long long m = 0; m < a; m++) { loop++; } } } } } std::cout << loop << std::endl; } int main() { doStuff(); return 0; }
另外也可以通过编译器选项强制OpenMP使用64位迭代器(比如GCC的-fopenmp-large-scale),但修改循环变量类型的方法更通用,不受编译器限制。
内容的提问来源于stack exchange,提问作者Pixel
相关产品推荐
相关产品推荐

