OpenMP函数多调用的线程分配与内层循环并行问题咨询
OpenMP多线程函数调用问题解答
用户代码(已修正语法错误)
void multiple_func_calling () { int x[6]{0,1,2,3,4,5}; double y[60000]; omp_set_num_threads(6); #pragma omp parallel #pragma omp for for(int i=0; i<6; ++i) { A(x[i], y); } } void A(const int& xi, double *y) { int count{0}; for(int i=0; i<100; ++i) for(int j=0; j<100; ++j) { y[count+10000*xi]=xi*10.0; count++; } }
注:原代码存在两处语法错误,已修正:double y[60000]()为非法数组声明,改为double y[60000];A(x[i], y)缺少分号,补充为A(x[i], y);。
问题1:是否每个线程会对应调用一次A(x[i], y)?
- 通常情况下是这样的。当线程数等于循环迭代次数(6次)时,OpenMP默认的**静态调度(static)**会给每个线程分配恰好1次迭代,也就是每个线程调用一次
A函数。 - 这不是绝对规则,OpenMP运行时可能根据系统线程亲和性、负载情况做细微调整,但绝大多数场景下,6线程对应6次迭代,每个线程执行一次
A。
问题2:当设置的线程数大于6时,for循环会如何在多线程间分配?
- 总共有6次迭代,最多只有6个线程能分到任务,剩下的线程会在并行区入口处闲置等待,直到所有任务完成。
- 比如设置8个线程:静态调度下,前6个线程各执行1次
A调用,后2个线程全程空转;如果用动态调度(schedule(dynamic)),线程会竞争迭代任务,但总任务数只有6,最终还是只有6个线程能抢到执行机会,其余线程无事可做。
问题3:是否可以并行化内层循环?如何避免count变量错误?或是保留串行更合适?
- 可以并行化内层循环,但必须重构
count的使用:原代码中count是串行迭代的计数器,并行化后多个线程同时递增count会触发竞态条件,导致索引计算完全错误。 - 解决方法:直接通过循环变量计算索引,完全去掉
count。原代码中count的本质就是i*100 + j,所以赋值语句可以改成:
之后就可以用OpenMP并行化内层的双层循环,比如在A函数中添加指令:y[(i*100 + j) + 10000*xi] = xi*10.0;#pragma omp parallel for collapse(2) for(int i=0; i<100; ++i) for(int j=0; j<100; ++j) { y[(i*100 + j) + 10000*xi] = xi*10.0; } - 是否要并行化:看实际计算量。如果
A函数内是示例中的简单赋值,并行化的线程调度开销会超过性能收益,保留串行更合适;如果A函数内是复杂计算,并行化内层循环能有效提升运行效率。
内容的提问来源于stack exchange,提问作者CityOfHope
相关产品推荐
相关产品推荐

