OpenMP线程内代码执行时间测量异常问题排查
回答
你的问题核心是混淆了墙钟时间和CPU时间,再加上并行时的资源竞争,才导致单迭代计时大幅变长,具体解释如下:
1. 你测的是“实际流逝时间”,不是线程真正干活的时间
std::chrono::steady_clock(包括普通boost chrono)测的是墙钟时间——也就是从代码开始到结束的物理时间。当你开20个线程并行时,所有线程会争抢以下资源,导致单个迭代的等待时间被计入计时:
- CPU资源:你机器是16核32线程,开20线程意味着部分线程要共享核心(超线程),线程切换会产生额外开销;
- 磁盘IO:每个迭代都要读取不同文件,20个线程同时发起读请求,磁盘IO成为瓶颈,单个线程的读操作会被迫等待;
- 内存/缓存:20个MIP求解器实例同时运行,会争抢CPU缓存、内存带宽,降低单个求解器的运行效率。
这些等待、资源竞争的时间全被算进t2-t1里,所以单迭代的计时自然比单线程时长得多,并非测量了所有线程的累计时间。
2. 整体耗时的结果是正常的
你贴的整体耗时数据完全符合并行计算的规律:
- 单线程跑完全程要23分钟,并行后只要12分钟,说明并行确实提升了整体任务的吞吐量,让任务完成得更快;
- 并行的
user时间高达156分钟,这是所有CPU核心的累计运行时间——20个线程各自的CPU运行时间相加,肯定远大于实际流逝的real时间;单线程时user接近real,是因为只有一个核心在持续运行。
3. 为什么用thread_clock结果还是一样?
boost的thread_clock统计的是当前线程实际占用CPU的时间,本不该包含IO等待,但你结果一致,大概率是因为:
多个MIP求解器实例在争抢某些隐性全局资源(比如求解器内部的全局缓存、系统内存页),导致线程出现CPU层面的等待,这部分时间会被thread_clock统计到。
正确的测量思路
如果想准确评估单个迭代的计算效率:
- 确认
thread_clock的用法正确,它只统计当前线程实际占用CPU的时间,能排除IO等待和线程切换的影响; - 对比单线程和并行下单个迭代的CPU时间,如果两者接近,说明计时偏差全来自资源竞争的墙钟等待;
- 评估并行效率只看整体
real时间即可——并行的目的是让整体任务更快完成,而非让单个迭代的墙钟时间变短。
内容的提问来源于stack exchange,提问作者Aisec Nory
相关产品推荐
相关产品推荐

