make:禁用某些目标的并行执行
我有一个编译工作,其中链接需要大量 IO 工作。我们有大约十几个核心,因此我们运行 make -j13,但是当涉及到链接 6 个目标时,我希望这些以循环方式完成。我想过让一个依赖于下一个,但我认为这会打破单独的目标。有什么想法如何解决这个小问题吗?
I have a compile job where linking is taking a lot of IO work. We have around a dozen of cores so we run make -j13, but when it comes to linking the 6 targets, I'd like those to be done in a round robin way. I thought about making one depend on the next but I think this would break the individual targets. Any ideas how to solve this small issue?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
make
本身不提供请求“N 个,但一次不超过 M 个”的机制。您可以尝试使用 GNU parallel 包中的
sem
命令你的链接器规则的配方。其文档有一个确保一次仅运行一个工具实例的示例。在您的示例中,您将允许make
一次启动最多 13 个sem
,但一次只有其中一个会运行链接器,而其他的则阻止。缺点是,您可能会遇到这样的情况:
make
的 13 个作业槽位中有 5 个与sem
实例绑定,而这些实例都在等待链接器进程来执行操作。结束。根据构建的结构,这可能意味着浪费一些 CPU 时间。不过,仍然击败了 6 个链接器同时对磁盘造成的影响:-)make
itself doesn't provide a mechanism to request "N of these, but no more than M of those at a time".You might try using the
sem
command from the GNU parallel package in the recipe of your linker rules. Its documentation has an example of ensuring only one instance of a tool runs at once. In your example, you would allowmake
to start up to 13sem
s at a time, but only one of those at a time will run the linker, while the others block.The downside is that you could get into a situation where 5 of your
make
's 13 job slots are tied up with instances ofsem
that are all waiting for a linker process to finish. Depending on the structure of your build, that might mean some wasted CPU time. Still beats 6 linkers thrashing the disk at once, though :-)您应该指定您的六个目标不能并行构建。将这样的行添加到您的 makefile 中:
有关详细信息,请查看此处 https://www.gnu.org/software/make/manual/html_node/Parallel-Disable.html。
You should specify that your six targets cannot be built in parallel. Add a line like this to your makefile:
For more information look here https://www.gnu.org/software/make/manual/html_node/Parallel-Disable.html.
我偶然发现了一个 hacky 解决方案:
对于它运行的每个配方,Make 都会做两件事:它扩展配方中的变量/函数,然后运行 shell 命令。
由于第一步可以读取/写入全局变量,因此它似乎是同步完成的。
因此,如果您在第一步中运行所有 shell 命令(使用
$(shell
)
),则其他配方在运行时将无法启动。例如,考虑这个 makefile:
time make -j2
报告 1 秒。但如果您将其重写为:
time make -j2
现在报告 2 秒。在这里,
@true
不执行任何操作,并抑制Nothing to be did for ??
输出。但这种方法存在一些问题。一是所有输出都将被丢弃,除非重定向到文件或 stderr...
I've stumbled upon a hacky solution:
For each recipe it runs, Make does two things: it expands variables/functions in the recipe, and then runs the shell commands.
Since the first step can read/write the global variables, it seems to be done synchronously.
So if you run all your shell commands during the first step (using
$(shell
)
), no other recipe will be able to start while they're running.E.g. consider this makefile:
time make -j2
reports 1 second.But if you rewrite it to this:
time make -j2
now reports 2 seconds.Here,
@true
does nothing, and suppressesNothing to be done for ??
output.There are some problems with this approach though. One is that all output is discarded unless redirected to file or
stderr
...它不会打破个人目标。
您可以为目标创建任意数量的 (
:
) 规则,只要其中只有一个规则具有构建它的实际配方即可。这似乎是一个很好的用例。It won't break individual targets.
You can create any number of (
:
) rules for a target, as long as only one of them has an actual recipe for building it. This appears to be a good use case for that.