【问题标题】:How to make GNU make run in batches?如何让 GNU make 批量运行?
【发布时间】:2020-07-11 07:40:27
【问题描述】:

我想使用make 使用脚本(例如 python)处理大量输入到输出。问题是脚本需要非常短的时间来运行每个输入,但是初始化需要一段时间(python 引擎 + 库初始化。)因此,一个只有输入->输出规则的天真的 makefile 最终会被这个初始化时间所支配。并行性对此无济于事。

python 脚本可以接受多个输入和输出,如下所示:

python my_process -i in1 -o out1 -i in2 -o out2 ...

这是使用脚本的推荐方式。

如何通过批量发送过时的输入-输出对来制定最能使用 my_process 的 Makefile 规则? parallel 之类的东西,但知道哪些输出已过时。

如果可能的话,我宁愿避免递归 make

【问题讨论】:

  • 听起来像是针对分组目标的工作。无法自己尝试,因为发行版卡在旧版本的 GNU Make 上。 gnu.org/software/make/manual/html_node/Multiple-Targets.html
  • @Andreas 不,分组目标在这里没有帮助。一方面,分组目标目前不适用于模式规则(我认为这是 bcs。这将是一个非常不寻常的模式,需要 N:N:1 三元关系),其次你没有得到列表需要从分组目标中更新的目标,至少不需要使用通常的特殊变量。
  • @Vroomfondel 是的,模式行不通。正在考虑与您的答案非常相似的事情,在 SOURCES 上使用 patsubst 来获取输出文件,而不是占位符目标“lastrun”。

标签: makefile gnu-make


【解决方案1】:

我没有完全理解你的问题:你真的希望make 批量操作,还是你想要一种永久的make 进程在运行中检查文件系统并在任何时候提供给 Python 进程觉得有必要?如果是后者,这与批处理模式完全相反,而是一个管道。

对于批处理模式,有一个解决方法需要一个记录最后运行时间的虚拟文件。在这种情况下,我们滥用了make,因为在这一部分中,makefile 是一头小马,不直观且违反了良好的规则:

SOURCES := $(wildcard in*)                                                                                                                                                                                                                                                                                                                                                                                                                                                                
lastrun : $(SOURCES)
        python my_process $(foreach src,$?,-i $(src) -o $(patsubst in%,out%,$(src)))
        touch lastrun                                                                                                                                                                                                                        

PS:请注意,此解决方案有一个重大缺陷,即在 makefile 运行期间发生的 in-file 更新时,它不会检测到更新。总而言之,最好只收集由更新过程本身更新的 in-files 的文件名,并避免make althogether。

【讨论】:

  • 这似乎对 all 输入运行 my_process 一次,这没有利用 make 的并行性,此外,如果任何输入发生变化,这将为所有输入重新运行 my_process。
  • 抱歉,忘记将 $(SOURCES) 替换为 $?。现在它只重建更改的文件。对于平衡的并行性,例如由于您拥有的核心进程如此之多,因此有必要动态创建lastrunX 目标,并将其先决条件列表划分和分离,并希望make 在并行化方面做得足够好。总而言之,这看起来就像make 是完全不适合这项工作的工具,尽管我完全承认更好的构建系统应该不会满足您的要求。
  • 我会将您的示例添加到我正在秘密构建的make-successor 的功能列表中,谢谢! ;)
  • 包括$? 上的文档:所有比目标新的先决条件的名称,它们之间有空格。如果目标不存在,则将包括所有先决条件。对于存档成员的先决条件,仅使用命名成员(请参阅存档)。 ` 这行得通,谢谢!
【解决方案2】:

这就是我最终的结果,一个带有一层递归的 makefile。

我尝试使用 $?都具有分组和未分组的目标,但无法获得所需的确切行为。如果输出目标之一被删除,规则将重新运行,但 $?不一定有一些输入文件但没有正确对应的输入文件,很奇怪。

生成文件:

all:

INDIR=in
OUTDIR=out

INFILES=$(wildcard in/*)
OUTFILES=$(patsubst in/%, out/%, $(INFILES))

ifdef FIRST_PASS
#Discover which input-output pairs are out of date
$(shell mkdir -p $(OUTDIR); echo -n > $(OUTDIR)/.needs_rebuild)
$(OUTFILES) : out/% : in/%
    @echo $@ $^ >> $(OUTDIR)/.needs_rebuild

all: $(OUTFILES)
    @echo -n
else
#Recurse to run FIRST_PASS, builds .needs_rebuild:
$(shell $(MAKE) -f $(CURDIR)/$(firstword $(MAKEFILE_LIST)) FIRST_PASS=1)
#Convert .needs_rebuild into batches, creates all_batches phony target for convenience
$(shell cat $(OUTDIR)/.needs_rebuild | ./make_batches.sh 32 > $(OUTDIR)/.batches)
-include $(OUTDIR)/.batches

batch%:
    #In this rule, $^ is all inputs needing rebuild.
    #The corresponding utputs can be computed using a patsubst:
    targets="$(patsubst in/%, out/%, $^)"; touch $$targets

clean:
    rm -rf $(OUTDIR)

all: all_batches

endif

make_batches.sh:

#!/bin/bash
set -beEu -o pipefail

batch_size=$1

function _make_batches {
    batch_num=$1
    shift 1
    #echo ".PHONY: batch$batch_num"
    echo "all_batches: batch$batch_num"
    while (( $# >= 1 )); do
        read out in <<< $1
        shift 1
        echo "batch$batch_num: $in"
        echo "$out: batch$batch_num"
    done
}
export -f _make_batches

echo ".PHONY: all_batches"

parallel -N$batch_size -- _make_batches {#} {} \;

不幸的是,makefile 是一个小技巧,并且有相当多的样板来完成这个配方。

【讨论】:

  • 题外话:对于你的场景,这真的比让 my_process 并行处理更简单吗?例如使用分叉,每个输入/输出对都有一个分叉。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-12-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-12
  • 2013-01-24
  • 1970-01-01
相关资源
最近更新 更多