bash - 即使我添加了 --jobs 并且 --max-load 甚至没有关闭,为什么 GNU Make 会按顺序运行?
问题描述
这是在 GNU Make 3.82、RHEL 7 上的。即使我传入 .Make 似乎是按顺序运行的--jobs
。
我正在做大约 700K 的琐碎工作——将大型 gzip 文件连接到其他 gzip 文件上。如果只有一个文件要连接,那么我创建一个符号链接。这是命令:
# Pattern to rebuild gzip file - concatenate if needed, otherwise just link
$(THISDIR)/%.tgz:
mkdir -p $$(dirname $@) && \
if [ $$(echo '$^' | wc -w) -gt 1 ]; then cat $^ > $@; else ln -s $^ $@; fi
我已经分开&&
以避免另一个shell调用,没有区别。
70 万个作业中约有 60 万个只是创建符号链接。对于其余部分,要连接的平均文件数为四个。
为什么这么慢?我得到 5-8 TPS。更重要的是,即使我指定(在具有 64 个 CPU 的机器上):
make --jobs --max-load=48
我在top
. 因此,Make 似乎根本没有运行并行作业。并行性在 GNU Make 上有效工作是否有最小的工作长度?
top
从现在开始的平均负载是
top - 22:50:32 up 3 days, 13:13, 32 users, load average: 7.96, 7.44, 5.73
一些可能有帮助的进一步细节:
- Make 本身以接近 100% 的 CPU 运行。
- 当然,除了目标和对同一规则的依赖关系之外,任何文件之间都没有依赖关系。换句话说,没有文件同时出现在
$@
和中$^
。 - 正在从 NFS 挂载创建和读取文件
- 我已经生成了 700K 依赖项作为规则,这些规则使用
include
. 该过程本身需要 25 分钟左右。
解决方案
可以提高性能,尤其是在使用 (gnu) make 函数替换 shell 命令来重建大量文件时。这将减少完成任务所需的“fork”和“exec”的数量:
%.tgz:
mkdir -p $(<D) && \
$(if $(findstring $(words $^),1),ln -s $^ $@, cat $^ > $@)
对于 mkdir 命令,使用$(<D)
将消除对dirname
对于cat
/ln
命令,使用$(findstring ...)
andwords
将替换echo ... | wc
管道,并且$if(...)
将替换 shell if 语句。
总体而言,每个目标只有 2 个命令(mkdir、cat/ln),而不是 5 个命令(mkdir、dirname、echo、wc、cat/ln)。性能约为 2X
推荐阅读
- asp.net-core - 如何向客户端发送其令牌已过期?
- bash - 使用 bash 从网站中抓取特定的超链接
- sql - 我希望有人检查我的代码并确定语法错误
- c# - 以功能方式将整数列表聚合或连接成字符串
- python - 获取边界内最近邻居列表
- android - Flutter Listview 在从视频 url 加载缩略图时冻结,我的应用程序崩溃了
- r - joining two dataframes between dates together
- react-native - Stacknavigatior 导航到已经在堆栈中的屏幕
- php - 在 Laravel 中提交 POST 表单后出现 302 错误
- xamarin - Azure OCR 识别PrintedTextInStreamAsync 无效图像