OpenMP线程数设置开销及多DLL场景调用疑问
解答
1. omp_set_num_threads()的开销与线程池机制
VS2017使用的OpenMP 2.0运行时中,omp_set_num_threads()并非仅修改内存数值,它会触发线程池的预初始化或规模调整:
- 当首次调用该函数,或设置的线程数与当前线程池规模差异较大时,运行时会预先创建/销毁线程以匹配指定数量,这个过程涉及线程创建、内核对象初始化等系统级调用,本身就存在固定开销。
- 如果后续并行区域使用
num_threads子句显式指定线程数,会直接覆盖omp_set_num_threads()的全局设置,此时之前的线程池调整操作确实属于无用开销——运行时会根据num_threads的要求重新调整线程池规模。
另外,你的测试中循环任务极轻量,并行带来的收益被线程池调整的开销抵消甚至反超是正常现象。OpenMP的并行开销(线程创建、任务分发、同步等)在任务粒度极小时会被放大,这类场景下串行执行反而更高效。
2. 多DLL环境下的OpenMP设置与链接方式
- OpenMP支持动态链接:VS中默认是动态链接OpenMP运行时(
vcomp*.dll),静态链接需要手动设置编译选项(/openmp:lib)。 - 静态链接时的行为:如果每个DLL都静态链接OpenMP运行时,那么每个DLL会拥有独立的OpenMP运行时实例,彼此的线程设置互不影响。这种情况下,每个含OpenMP代码的DLL都需要单独调用
omp_set_num_threads()来设置自己的默认线程数。 - 动态链接时的行为:所有DLL和EXE共享同一个OpenMP运行时实例,此时只需在EXE中(或第一个调用OpenMP的模块中)调用一次
omp_set_num_threads(),设置即可全局生效。
建议使用动态链接OpenMP运行时,这样不仅能避免多实例的设置问题,还能减小二进制体积,同时运行时的线程池管理是全局统一的,效率更高。
内容的提问来源于stack exchange,提问作者Christian Langis
相关产品推荐
相关产品推荐

