如何衡量一个非常大的程序的上下文切换开销?

How to measure the context switching overhead of a very large program?

我正在尝试衡量 CPU 调度程序对大型 AI 程序 (https://github.com/mozilla/DeepSpeech) 的影响。

通过使用 strace,我可以看到它使用了很多 (~200) CPU 个线程。

我曾尝试使用 Linux Perf 来衡量这一点,但我只能找到 数量 的上下文切换事件,而不是 开销 其中。

我想要实现的是在上下文切换上花费的总 CPU 核心秒数。由于它是一个相当大的程序,我更喜欢非侵入性工具,以避免不得不编辑这个程序的源代码。

我该怎么做?

您确定这 200 个线程中的大部分实际上是在同时等待 运行,而不是等待来自系统调用的数据吗?我想您可以从 perf stat 看出上下文切换实际上非常高,但部分问题是它们是否对于执行关键工作的线程来说很高。

线程再次 运行ning 后,上下文切换的成本反映在缓存未命中中。(并阻止 OoO exec 找到尽可能多的 ILP 就在中断边界)。此成本比 saves/restores 注册的内核代码的成本更重要。因此,即使有一种方法可以测量 CPU 在内核上下文切换代码中花费了多少时间(只要您的 perf_event_paranoid 设置允许记录内核地址, perf record 采样分析器就可以),这不能准确反映真实成本。

即使进行系统调用也具有与序列化 OoO exec 以及令人不安的缓存(和 TLB)相似(但更低且更频繁)的性能成本。在 Livio 和 Stumm 的一篇论文中,真正的现代 CPUs(从 2010 年开始)对此有一个有用的描述,尤其是 IPC 第一页上的图表(每个周期的指令数)在系统调用后下降 returns,并花时间恢复:FlexSC: Flexible System Call Scheduling with Exception-Less System Calls. (Conference presentation: https://www.usenix.org/conference/osdi10/flexsc-flexible-system-call-scheduling-exception-less-system-calls)


您可以通过 运行在具有足够内核的系统上运行程序来估计上下文切换成本,而根本不需要太多上下文切换(例如,大型多核 Xeon 或 Epyc),与. 在更少的内核上,但具有相同的 CPUs / 缓存 / 内核间延迟等。因此,在同一系统上使用 taskset --cpu-list 0-8 ./program 来限制它可以使用的内核数。

查看使用的总用户 -space CPU 秒:更高的数量是由于上下文切换导致的减速而需要的额外 CPU 时间。当相同的工作必须竞争更少的核心时,挂钟时间当然会更长,但是 perf stat 包括一个“任务时钟”输出,它告诉你总时间 CPU-毫秒您的进程的线程花费了 CPU 秒。对于相同的工作量,这将是不变的,完美地扩展到更多线程,and/or 到竞争更多/更少内核的相同线程。

但这会告诉您在具有大缓存和内核间延迟比小型桌面更高的大型系统上的上下文切换开销。