我正在运行一个基准测试来计算出我应该允许 GNU Make 使用的作业数量,以获得最佳的编译时间。为此,我使用make -j<N>
N 为 1 到 17 之间的整数来编译 Glibc。到目前为止,我为每个 N 选择执行了 35 次(总共 35*17=595 次)。我也在运行它GNU 时间确定 Make 花费的时间和使用的资源。
当我分析结果数据时,我注意到一些奇怪的事情。当我达到 时,主要页面错误的数量出现了非常明显的峰值-j8
。
我还应该注意,8 是我的计算机上的 CPU 核心数(或更具体地说是超线程数)。
我还可以在自愿上下文切换的数量中注意到同样的事情,但不太明显。
为了确保我的数据没有偏差或任何其他情况,我又运行了两次测试,但仍然得到相同的结果。
我正在使用 Linux 内核 5.15.12 运行 artix linux。
这些峰值背后的原因是什么?
编辑:我在 4 核 PC 上再次进行了相同的实验。这次我在 4 个工作岗位上也观察到了同样的现象。
另外,请注意 2 个作业标记中主要页面错误的跳跃。
编辑2:
@FrédéricLoyer 建议将页面错误与效率(所用时间的倒数)进行比较。这是一个箱线图:
我们可以看到,当我们从 1 个工作变成 4 个工作时,效率越来越好。但对于更多的工作岗位来说,它基本上保持不变。
我还应该提到,我的系统有足够的内存,因此即使有最大数量的作业,我也不会耗尽内存。我还记录了 PRSS(峰值驻留集大小),这是它的箱线图。
我们可以看到作业数量根本不影响内存使用。
EDIT3:正如 MC68020 所建议的,这里分别是 4 核和 8 核系统的 TLBS(事务后备缓冲区击倒)值的图:
答案1
因为显示全局效率的图表为您的任务提供了正确的答案,所以我将尝试重点解释。
A/ 效率\工作安排
理论上,(假设在 make 启动时所有 CPU 都处于空闲状态,并且没有其他任务在运行,并且在启动第 n 个 > i 时没有 i 作业已完成),我们可能期望 CFS 分发 1,2,3,4,5, 6、7、8 个作业分配给 CPU 0、2、4、6(因为缓存共享没有带来任何好处),然后是 1、3、5、7(仍然没有从缓存共享中得到好处,但由于缓存在同级之间共享,锁增加争用因此对全球效率产生负面影响)这是否足以解释从工作 5 开始全球效率缺乏改善?
B/页面错误
正如 Frédéric Loyer 所解释的那样,在作业启动时预计会出现重大页面错误(由于必要的读取系统调用)。您的图表显示,从 5 个作业到 8 个作业,增长几乎是恒定的。4+4 核上 -j4 处的显著增加(由 2+2 核上 -j2 处的显著增加证实)在我看来更有趣。这可能是由于某个 <=4 cpu 的突然活动(由任何其他任务引起)导致某个作业线程在 > 4 cpu 上重新安排的证据吗?-j(n>8) 的页面错误数量恒定,这是因为所有可选的 cpu 都已经具有适当的映射。
顺便说一句:只是为了证明我对杂项的要求是合理的。 OP 评论中的缓解信息,我想首先确保所有核心都完全运行。看来是的。
答案2
当make
启动一个进程时,进程的内存被映射到它的文件(可执行文件、库)。然后预计会出现页面错误。系统效率越高,我们可以预见的页面错误就越多。将页面错误率与效率(所花费的时间的倒数make
)进行比较可能会很有趣。
当系统没有足够的 RAM 并与 HDD 交换数据时,我们也可能会出现页面错误。这并不是效率的标志。