为什么人们在使用双核 CPU 时推荐 make 使用 -j3 选项?

为什么人们在使用双核 CPU 时推荐 make 使用 -j3 选项?

在 Gentoo Linux 中,可以设置变量MAKEOPTS/etc/portage/make.conf告诉make构建包时应该并行运行多少个作业。由于我有一个双核 CPU,所以我天真地选择使用该-j2选项:每个核心一个作业,因此两者都有事可做。 “问题”是有很多参考资料告诉拥有双核 CPU 的用户-j3改为设置该选项。他们之中有一些是:

例如,Gentoo 手册说:

一个不错的选择是系统中 CPU(或 CPU 核心)的数量加一,但该准则并不总是完美的。

但“CPU + 1”规则的基本原理是什么?为什么要做额外的工作?

make.conf(5) 手册页甚至说:

建议的设置介于 CPU+1 和 2*CPU+1 之间。

我还阅读了信息页面中的第 5.4 节(并行执行)makemake手册页对该选项的解释-j,但似乎没有答案。

答案1

没有一条简单的规则总是有效。人们可能会推荐一个特定的数字,因为他们在特定的机器上尝试了特定的编译并且这是最佳设置,或者因为他们遵循了一些可能与现实有关系或没有关系的推理。

如果您拥有大量 RAM,那么长时间编译的限制因素将是 CPU 时间。然后,每个 CPU 执行一个任务,再加上一个针对那些偶尔出现的 I/O 块的待处理任务,这是一个不错的设置。这使得它-j3适用于双核 CPU(或者更准确地说,适用于双 CPU 机器 - 如果每个核心都是超线程,那么将有 4 个 CPU,所以-j5)。

如果您的 RAM 很少,那么一个限制因素可能是您不能有很多并发作业,否则它们会不断地相互交换。例如,如果您无法轻松地将两个编译器实例放入内存中,make -j2则可能已经比make.由于这取决于 RAM 中可以同时容纳多少个编译器进程,因此无法得出一般数字。

在这两者之间,拥有更多的工作可能是有益的。如果每个编译器进程都很小,但整个构建涉及大量数据,那么磁盘 I/O 可能是阻塞因素。在这种情况下,您需要每个 CPU 同时执行多个作业,以便始终有一个作业在使用每个 CPU,而其他作业则在等待 I/O。同样,这很大程度上取决于构建作业和可用 RAM,这里取决于可用于数据缓存的内容(有一个最佳值,在此之后过多的作业会过多地污染缓存)。

答案2

我想这有点启发式— 允许make启动CPUs + 1进程是为了确保:

  1. 刚刚完成的工作进程和尚未运行的工作进程之间不会有间隙——有点像预填充运行队列。
  2. 不会有太多的竞争进程来通过运行队列预填充带来明显的开销。

但话又说回来,那就是启发式FreeBSD 的手册仍然推荐 make -j4对于单个CPU。

答案3

一般来说,启动比核心数量更多的作业是有原因的。对于使用 gcc 进行 C 编译,如果 gcc 选项中未定义 -pipe,它将使用临时文件按顺序执行其操作(预处理、首次运行、优化和汇编); -pipe 将其更改为在子进程之间使用管道。 (添加 -pipe 是 FreeBSD 的默认设置,但在 Linux 上不是传统的。)因此,如果您有 2 个核心并允许并行 2 个作业,它们将在磁盘 I/O 上花费一些时间。添加 1 份工作的建议似乎与此细节相关。但要获得最终答案,您应该找到谁以及何时添加了此建议,并询问他:) 或在 Gentoo 开发者的邮件列表中询问。

答案4

基本上这个数字就是作者所说的常识。充其量,这是一个很好的猜测。据我所知,当您键入时生成的 make 进程make已经被计算在内,因此-j3您最终可能会导致主进程等待,而其他两个进程正在编译。

然而,当我使用 Gentoo 时,经验法则是<#cpus>*2 + 1.

这一切都取决于你的小鸡踪迹、茶叶或神奇的 8 球告诉你需要发生的磁盘 I/O 以及当前 Linux 内核的调度。 [开始这篇文章的核心]从我个人的经验来看(-j不是 Gentoo 特有的),#cpus + 1 和 #cpus *2 +1 之间的所有内容都会产生很好的结果[结束这篇文章的核心]并且平均来说你几乎不会注意到任何差异。现在的处理器和内核都非常好。

但是,当以下情况发生时,所有这些都会发生变化:a)您实际上使用多个盒子来编译(du'h)或 b)正在开发自己的代码

较高的-j属性更有可能显示以前未知的依赖性。

顺便说一句:不要按核心数量,而是按 CPU 占用的并发流数量。 (超标题!)

相关内容