如何提高 Makefile 的速度?
Posted
技术标签:
【中文标题】如何提高 Makefile 的速度?【英文标题】:How can I improve the speed of my Makefile? 【发布时间】:2011-06-30 19:30:47 【问题描述】:我正在用 Fortran 中的几个文件在 C++ 和 CUDA 中构建多个二进制文件。我找到了this question,我遇到了类似的问题。一位用户最近要求我重新构建存储库的三年旧版本(在我们执行大规模迁移和重命名之前),我震惊地看到它构建的速度。确切地确定该版本与现在导致构建花费如此长的时间之间的哪些更改是不可能/非常耗时的。
但是,我在回答对上述问题的评论中注意到:
尤其要记住使用 := 而不是 =,因为 := 是展开式 立即,这样可以节省时间。 – 杰克凯利 3 月 23 日 22:38
还有其他我应该注意的建议吗?
注意:
我使用“包含”范例,其中我要构建的每个目录都有一个module.mk
文件,该文件直接包含在唯一的 Makefile 中。
我确实使用了几个函数,例如:
(降价..)
#
# CUDA Compilation Rules
#
define cuda-compile-rule
$1: $(call generated-source,$2) \
$(call source-dir-to-build-dir, $(subst .cu,.cubin, $2)) \
$(call source-dir-to-build-dir, $(subst .cu,.ptx, $2))
$(NVCC) $(CUBIN_ARCH_FLAG) $(NVCCFLAGS) $(INCFLAGS) $(DEFINES) -o $$@ -c $$<
$(call source-dir-to-build-dir, $(subst .cu,.cubin, $2)): $(call generated-source,$2)
$(NVCC) -cubin -Xptxas -v $(CUBIN_ARCH_FLAG) $(NVCCFLAGS) $(INCFLAGS) $(DEFINES) $(SMVERSIONFLAGS) -o $$@ $$<
$(call source-dir-to-build-dir, $(subst .cu,.ptx, $2)): $(call generated-source,$2)
$(NVCC) -ptx $(CUBIN_ARCH_FLAG) $(NVCCFLAGS) $(INCFLAGS) $(DEFINES) $(SMVERSIONFLAGS) -o $$@ $$<
$(subst .o,.d,$1): $(call generated-source,$2)
$(NVCC) $(CUBIN_ARCH_FLAG) $(NVCCFLAGS) $3 $(TARGET_ARCH) $(INCFLAGS) $(DEFINES) -M $$< | \
$(SED) 's,\($$(notdir $$*)\.o\) *:,$$(dir $$@)\1 $$@: ,' > $$@.tmp
$(MV) $$@.tmp $$@
endef
但是我在旧版本中使用的大部分功能......
最后:我如何确定是编译时间还是make
时间真正减慢了速度?
我不想附加整个 Makefile。这是 914 行,但如果有帮助,我很乐意用 sn-ps 更新问题。
更新:这是我的依赖生成规则和编译规则:
#
# Dependency Generation Rules
#
define dependency-rules
$(subst .o,.d,$1): $2
$(CC) $(CFLAGS) $(DEFINES) $(INCFLAGS) $3 $(TARGET_ARCH) -M $$< | \
$(SED) 's,\($$(notdir $$*)\.o\) *:,$$(dir $$@)\1 $$@: ,' > $$@.tmp
$(MV) $$@.tmp $$@
endef
%.d: %.cpp
$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -M $< | \
$(SED) 's,\($(notdir $*)\.o\) *:,$(dir $@)\1 $@: ,' > $@.tmp
$(MV) $@.tmp $@
更新 2: 使用 @Beta 的建议,我能够分出依赖项生成,Makefile 时间大约占总编译时间的 14.2%。因此,我将首先专注于最小化 C++ 代码中包含的标头。谢谢两位的建议!!
【问题讨论】:
【参考方案1】:-
确定哪些更改减慢了一切应该不难。你有过去三年的所有版本(我希望),你说差异是巨大的。所以试试两年前的版本。如果花费的时间太长,请进行二分搜索。你甚至可以自动化这个过程,让它在一夜之间运行,并在早上给你一个图表,在过去的 36 个月中每个月对构建时间进行采样。
如果您正在使用 GNUMake(如我所愿),`make -n` 将打印出它将执行的命令,而不实际执行它们。这将为您提供所有的 Make 时间,而无需编译时间。
不必要的构建时间(甚至比您不使用的递归更大)的最大来源之一是不必要的重新构建、重新编译/重新链接/在您真正不需要的时候。这可能是因为您的 makefile 没有正确处理依赖关系,或者因为您的 C++ 文件“#include”标题鲁莽,或者我不知道的关于 CUDA 或 FORTRAN 的内容。连续运行两次 Make,看看它在第二遍时是否有任何作用。查看生成文件以获取可疑的巨大先决条件列表。让熟练的程序员查看一些源文件,尤其是较新的源文件,并检查不必要的依赖关系。
【讨论】:
我正在使用 GNUMake。我正在使用上面添加的规则构建依赖项 - 在我的开发中,我make distclean
用于我的夜间构建,但我很少在开发时构建整个东西。我不知道make -n
。我现在正在计时。【参考方案2】:
ElectricMake (emake) 是 gmake 的直接替代品,可以非常非常轻松地回答此类问题。 emake 可以生成一个带注释的构建日志,其中包含构建中每个作业的详细时间信息,然后您可以将其加载到 ElectricInsight 中以生成,例如,按类型划分的作业时间 em> 报告:
如果你想试一试,可以get an eval copy。
(免责声明:我是 ElectricMake 和 ElectricInsight 的架构师和首席开发人员!)
【讨论】:
【参考方案3】:我真的怀疑 make 的变量赋值(立即使用 := 或递归 =)总体上会对速度产生重大影响。造成严重影响的一个具体而明显的案例是 shell 命令:
VAR := $(shell ...)
可能还有其他不明显的隐藏消费过程。例如,在我们的环境中,标准临时 Windows 目录位于网络驱动器上。因此,当在该驱动器上存储/更新文件时(即使使用 1G LAN) - 它非常慢。您需要的是调试生成文件。 This maybe helpful.
根据提到的文档,您可以以 $(warning Going to do bla-bla-bla) 的形式放置调试打印,然后观察进程最冻结的位置。
【讨论】:
感谢您的建议@pmod! - 每当我设置一个新的开发环境时,我都会记住这一点。我最近在使用基于主板的 RAID 5 设置时遇到了类似的问题(时间延迟)。 实际上,将 make 变量赋值从 recursive = 更改为 immediate := 帮助我显着加快了 make 过程 @UmairR 感谢您指出这一点,是的,我错过了一个有意义的案例(几乎总是)以上是关于如何提高 Makefile 的速度?的主要内容,如果未能解决你的问题,请参考以下文章
makefile中的.phony作用(防止在Makefile文件中定义的可执行命令的目标规则和工作目录下的实际文件出现名称冲突,并提高执行Makefile的性能)
makefile中的.phony作用(防止在Makefile文件中定义的可执行命令的目标规则和工作目录下的实际文件出现名称冲突,并提高执行Makefile的性能)