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

标签 multithreading profiling perf microbenchmark context-switch

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

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

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

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

我该怎么做?

最佳答案

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

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

即使进行系统调用,也会因序列化 OoO exec 以及干扰缓存(和 TLB)而产生类似(但更低且更频繁)的性能成本。在 Livio 和 Stumm 的一篇论文中,在真正的现代 CPU(从 2010 年开始)上对此进行了有用的描述,特别是 IPC(每个周期指令)第一页上的图表在系统调用返回后下降,并需要时间来恢复:FlexSC: Flexible System Call Scheduling with Exception-Less System Calls 。 ( session 简报:https://www.usenix.org/conference/osdi10/flexsc-flexible-system-call-scheduling-exception-less-system-calls)


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

查看使用的总用户空间 CPU 秒数:较高的数量是由于上下文切换导致的速度减慢而需要的额外 CPU 时间。当相同的工作必须竞争更少的核心时,挂钟时间当然会更长,但是 perf stat 包含一个“任务时钟”输出,它告诉您以 CPU 毫秒为单位的总时间进程的线程消耗在 CPU 上。对于相同的工作量来说,这将是恒定的,可以完美地扩展到更多线程,和/或竞争更多/更少核心的相同线程。

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

关于multithreading - 如何衡量一个非常大的程序的上下文切换开销?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66311172/

相关文章:

Python:同时多个HTTP请求

尽管运行代码来显示菜单,Java 小程序仍显示白屏

c# - MemoryBarrier 是否保证所有内存的内存可见性?

python - 计算数据框中列的汇总统计信息

regex - 从终端中的命令输出中提取单行

kernel - 如何使用 perf 测量程序执行期间的缺页时间?

c - 为什么 write() 终止我的线程?

c - 使用显式 openMP 任务分析 OpenMP 程序

java - 查找 java 源代码中执行次数最多的部分

linux - "perf sched record"使用什么时间范围?