如何在多核Linux机器上使用GNU make --max-load?

时间:2012-12-17 06:31:15

标签: gnu-make multicore uptime

来自GNU make的文档:http://www.gnu.org/software/make/manual/make.html#Parallel

  

当系统负载很重时,您可能希望运行更少   工作比轻载时。您可以使用'-l'选项   告诉make限制一次运行的作业数量,基于   平均负载。 '-l'或'--max-load'选项后跟a   浮点数。例如,

 -l 2.5
     如果平均负载高于2.5,

将不会让make启动多个作业。   没有以下编号的'-l'选项会删除加载限制(如果有)   使用之前的'-l'选项给出。

     

更准确地说,当make开始创作时,它已经有了   至少一个工作正在运行,它检查当前的负载平均值;如果是   不低于'-l'给出的限制,等待直到负载   平均值低于该限制,或直到所有其他工作完成。

从Linux手册页中获取正常运行时间:http://www.unix.com/man-page/Linux/1/uptime/

  

系统负载平均值是平均进程数   要么处于可运行状态,要么处于不间断状态。可运行的进程   state正在使用CPU或等待使用CPU。一个过程   处于不间断状态正在等待一些I / O访问,例如等待   对于磁盘。平均值是在三个时间间隔内取得的。   对于系统中的CPU数,负载平均值没有标准化,   因此,平均负载为1表示单个CPU系统全部加载   在4 CPU系统上的时间意味着它在75%的时间内处于空闲状态。

我有一个并行的makefile,我想做一件显而易见的事情:make make继续添加进程,直到我获得完全的CPU使用率,但我不会引起颠簸。

今天的许多(所有?)机器都是多核的,因此这意味着负载平均值不是应该检查的数量,因为需要针对核心数调整该数量。

这是否意味着GNU make的--max-load(又名-l)标志现在没用了?在多核计算机上运行并行makefile的人在做什么?

3 个答案:

答案 0 :(得分:7)

我的简短回答:--max-load如果您愿意投入时间来充分利用它,那将非常有用。凭借其目前的实施,没有简单的公式可以选择好的价值,或者是一个用于发现它们的预制工具。

我维护的构建相当大。在我开始维护它之前,构建是6个小时。在ramdisk上使用-j64,现在它在5分钟内完成(使用-j12进行NFS挂载时为30)。我的目标是为-j-l找到合理的上限,允许我们的开发人员快速构建,但不会使服务器(构建服务器或NFS服务器)无法用于其他所有人。

首先:

  • 如果您选择合理的 -jN值(在您的计算机上)并找到合理的平均上限(在您的计算机上),它们可以很好地协同工作以保持平衡。
  • 如果您使用非常大的-jN值(或未指定;例如,-j没有数字)并限制平均负载,gmake将:
    • 继续产生进程(gmake 3.81添加了一个限制机制,但这只能帮助缓解一点问题),直到达到最大作业数或者直到负载平均值超过阈值
    • 当负载平均值超过您的阈值时:
      • 在所有子流程完成之前不执行任何操作
      • 一次产生一份工作
    • 重新做一遍

至少在Linux上(可能还有其他* nix变体),load average isexponential moving average(UNIX Load Average Reweighed,Neil J. Gunther)代表等待CPU时间的平均进程数(可能是由过多的进程,等待IO,页面错误等引起的。由于它是一个指数移动平均线,因此它的加权使得较新的样本对当前值的影响比旧样本更强。

如果你能找到一个合适的最大负荷和平行工作数量的良好“甜蜜点”(通过有根据的猜测和经验测试的结合),假设你有一个长期运行的建立:你的1分钟平均值将达到平衡点(不会波动很大)。但是,如果您的-jN数字对于给定的最大平均负载而言过高,则会出现相当大的波动。

发现最佳位置基本上等于找到微分方程的最佳参数。由于它将受初始条件的影响,因此重点是找到使系统保持平衡的参数,而不是提出“目标”负载平均值。 “平衡”是指:1m负载平均值不会波动很大。

假设您没有受到gmake限制的瓶颈:当您找到-jN -lM组合时,可以提供最短的构建时间:该组合将推动您的计算机达到极限。如果机器需要用于其他目的......

compiling

...当你完成优化时,你可能想稍微缩小它。

不考虑加载平均值,我在构建时看到的增加-jN的改进似乎是[粗略]对数。也就是说,我发现-j8-j12之间的差异大于-j12-j16之间的差异。

事情在我-j48-j64之间的某个地方达到了顶峰(在Solaris机器上它是-j56),因为最初的gmake进程是单线程的;在某些时候,线程无法比完成更快地开始新的工作。

我的测试是在:

进行的
  • 非递归构建
    • 递归构建可能会看到不同的结果;他们不会遇到我在-j64
    • 周围遇到的瓶颈
    • 我尽最大努力减少配方中的make-isms(变量扩展,宏等)的数量,因为配方解析发生在产生并行作业的同一个线程中。配方越复杂,它在解析器中花费的时间就越多,而不是产生/收割作业。例如:
      • 配方中没有使用$(shell ...)个宏;这些是在第一次解析过程中运行并缓存
      • 大多数变量都分配有:=以避免递归扩展
  • Solaris 10 / sparc
    • 256核心
    • 没有虚拟化/逻辑域
    • 构建在ramdisk上运行
  • x86_64 linux
    • 32核(4x超线程)
    • 无虚拟化
    • 构建在快速本地驱动器上运行

答案 1 :(得分:0)

  

今天的许多(所有?)机器都是多核的,因此这意味着负载   平均值不是应该检查的数字,作为该数字   需要根据核心数量进行调整。

     

这是否意味着现在是GNU make的--max-load(aka -l)标志   无用?

没有。想象一下要求磁盘i / o的工作。如果您启动了与CPU相同数量的作业,则仍然无法很好地利用CPU。

就个人而言,我只是使用-j,因为到目前为止它对我来说效果还不错。

答案 2 :(得分:0)

即使对于CPU是瓶颈的构建,-l也不理想。我使用-jN,其中N是存在或我想在构建上花费的核心数。选择一个更大的数字并不能加快我的情况。它也不会减慢它,只要你不过分(例如通过-j指定无限)。

使用-lN大致相当于-jN,并且如果机器还有其他独立工作可以更好地工作,但有两个怪癖(除了你提到的那个,核心数量)没有考虑到):

  • 初始峰值:当构建开始时, make 会启动大量N个以上的作业。系统加载编号在分叉进程时不会立即增加。这在我的情况下不是问题。
  • 饥饿:当某些构建作业与其他作业相比需要很长时间时,在前M个快速作业结束时,系统负载仍然是> N.很快系统负载下降到N - M,但只要拖动那些少量的慢速作业,就不会启动新的作业,并且核心仍然处于饥饿状态。 Make 只考虑在旧工作结束时和开始时启动新工作。它没有注意到系统负载在两者之间下降。
相关问题