GNU Make -j8并没有并行运行的问题

3
我正在使用ndk-build运行Android NDK make文件,这只是正常的gnu make,使用Google makefile模板运行。我使用ndk-build -j8来运行它,确实可以确认make命令行带有-j8
然而,编译过程会逐个编译我的源文件,从不同时运行clang++超过一次。以前并不是这样的。就在几天前,我使用完全相同的脚本,它使用了所有8个核心,速度更快。
可能会导致gnu make突然不遵守-j8的原因是什么?
是否有办法让gnu make生成任何关于此的解释信息?各种--debug选项似乎没有提到它。
操作系统为OSX 10.10.5,gnu make版本为3.81。
更新:如果我在之前运行ndk-build clean,我立即进行的构建将在所有8个核心上运行。一天后进行的后续构建仍然只使用1个核心。

1
我猜你的 Makefile 中有一些奇怪的依赖关系。在看到它之前,我们无法回答你的问题。也许一些 -include 的文件正在造成混乱。 - Basile Starynkevitch
顺便说一句,你真的应该将你的GNU make升级到4.1版本和/或使用remakemake --trace来调试这些问题;尝试执行make clean和/或make distclean - Basile Starynkevitch
你的问题应该被关闭,因为它在这里是双重不相关的:没有展示代码(你应该展示你的Makefile),但却要求调试,并且更适合在超级用户上讨论。 - Basile Starynkevitch
@BasileStarynkevitch,不同意基于离题的关闭,这个问题直接属于stackoverflow的范畴。然而,在这里我们确实需要代码示例。 - Jonathan Howard
第一次构建运行后,后续构建是否立即并行运行?问题在于干净构建与非干净构建之间的区别吗?将-d参数添加到两个运行中会得到什么输出?(输出将非常。) - Etan Reisner
1
正如其他人所说,没有代码就无法诊断问题。但是,我猜测可能是由于您引入了新的依赖链,导致没有并行编译。这不会很明显。ndk-build包含文件在幕后执行一些棘手的操作。这与干净的构建显示并行执行,但增量构建则不同。使用您的版本控制系统将代码回滚到几天前的状态进行验证。然后查看自那时以来您编写的内容。在那段时间内有责任的东西。 - Gene
3个回答

3
您可以通过使用which maketype make来检查make是否实际上是make(看看是否涉及包装脚本、函数或别名)。
这也可能是一个解决方法:向子make传递选项
引用如下:

-j选项是一个特例(请参见并行执行)。如果您将其设置为某个数字值N,并且您的操作系统支持它(大多数UNIX系统都支持;其他系统通常不支持),则父make和所有子make将进行通信,以确保它们之间只有N个作业在同时运行。请注意,标记为递归的任何作业(请参阅替代执行配方)都不计入总作业数(否则我们可能会得到N个子make正在运行,没有剩余的插槽可用于任何真正的工作!)

与您相关的信息如下:
引用如下:

如果您的操作系统不支持上述通信,则-j 1始终放入MAKEFLAGS,而不是您指定的值。这是因为如果将-j选项传递给子make,则会并行运行比您要求的更多作业。如果没有数字参数地提供-j,意味着尽可能并行运行尽可能多的作业,则会传递此参数,因为多个无限大不超过一个。


1
没有子make,我只看到一个make进程。 - shoosh
@shoosh 为了确保不是你的 make 出了问题,创建一个虚拟的 makefile,其中包含一系列仅仅执行 echo 语句的目标,并执行 make all --jobs=16 命令。请参考我的问题 - Bob

1

仅供猜测:

  1. 在您的 make 文件中搜索 .NOTPARALLEL 伪目标。它可以防止 GNU Make 并行构建。
  2. 您是否设置了 -l,并且负载高于该值?那么 make 将一次只启动一个作业。
  3. 您确定在重新构建时有独立的构建内容吗?当然,make 只会并行处理彼此独立的任务。

1

以上答案已经提供了关于您问题的已知链接。

如果不了解更多有关您的设置,我只能猜测:

也许运行您的构建脚本会影响MAKEFLAGS。

您可以尝试直接将作业数量传递到ndk-build脚本中。编辑您的ndk-build脚本如下:

$GNUMAKE -j8 -f $YourProgramDir/.../build-local.mk "$@"


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接