OpenMP实现串行与并行区域均可调用并行化函数且避免代码冗余
解决方案
你要的能力OpenMP原生就支持,直接用parallel指示的if条件子句即可完全消除代码重复,不需要手动写分支判断。
修改后的inParallel函数实现如下:
template<typename Callable> void inParallel( Callable&& func ){ #pragma omp parallel for if(!omp_in_parallel()) for ( int i=0; i<nIter; ++i ){ func(i); } }
原理解释
parallel构造的if子句会根据表达式的求值结果决定是否启动新的并行团队:
- 从串行区域调用
inParallel时,omp_in_parallel()返回false,!omp_in_parallel()为真,parallel for正常生效,启动新的并行线程执行循环 - 从并行区域内部调用
inParallel时,omp_in_parallel()返回true,!omp_in_parallel()为假,OpenMP会忽略本次的parallel语义,仅保留for的循环拆分逻辑,将循环任务分配给当前外层已存在的并行团队线程执行,和你原来分支里的#pragma omp for效果完全一致。
嵌套并行段错误原因
你之前开启嵌套并行出现的段错误和OpenMP本身无关,问题出在复现代码中的std::stringstream s是外层并行区域的线程私有变量,开启嵌套并行后,每个外层线程衍生的多个子线程会同时无锁写入同一个s对象,而std::stringstream不支持多线程并发写入,因此触发内存访问错误。如果确实需要使用嵌套并行,只需对s的写入操作加锁,或者为每个子线程分配独立的输出缓冲区即可解决。
其他可选方案
如果出于特殊原因不想使用if子句,也可以把循环逻辑抽成独立的通用实现,两个分支共用同一段代码,也能避免重复,只是代码量比原生if子句方案略高。
内容的提问来源于stack exchange,提问作者RL-S
相关产品推荐
相关产品推荐

