首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在makefile中仅对列表中的目标使用.NOTPARALLEL?

如何在makefile中仅对列表中的目标使用.NOTPARALLEL?
EN

Stack Overflow用户
提问于 2020-05-19 14:27:48
回答 1查看 670关注 0票数 0

我使用make来执行一个复杂的计算,它涉及到几个不同程序的运行,其计算结果相互依赖。其中包括对高度优化/矢量化/多线程程序的几次执行,以及对单线程python脚本的多次执行。因此,Makefile有以下部分:

代码语言:javascript
复制
slow_target/%: fast_target/%
   python $<
   #run of the unparalleled single-threaded python program

fast_target/%: #some dependencies for each %
   #run of the multi-core paralleled program

fast_target/%可以存储在变量中,但不能手工枚举(其中有几十个)。

我想按顺序计算所有fast_target/%,但其他目标并行计算。该怎么做呢?

这个问题有点类似于How can I use .NOTPARALLEL in makefile only on specific targets?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-05-19 21:48:50

一种可能的方法是在食谱中的文件级别上使用同步。它当然不是最好的(因为它仍然会消耗make的工作),但是不应该通过运行n个多线程程序来使系统超载。

示例Makefile:

代码语言:javascript
复制
$ cat Makefile
all: $(foreach number,1 2 3 4 5 6 7 8 9 10,$(addsuffix /$(number),slow_target fast_target))

slow_target/%:
        @echo $@
        @python3 -c 'import time; time.sleep(5)'

fast_target/%:
        @( \
          flock 9 || exit 1; \
          echo $@; \
          python3 -c 'import time; time.sleep(5)' \
        ) 9> fast_target.lock

输出:

代码语言:javascript
复制
$ make -j8 | ts
May 19 23:45:06 slow_target/1
May 19 23:45:06 slow_target/2
May 19 23:45:06 fast_target/1
May 19 23:45:06 slow_target/3
May 19 23:45:06 slow_target/4
May 19 23:45:11 fast_target/2
May 19 23:45:11 slow_target/5
May 19 23:45:11 slow_target/6
May 19 23:45:11 slow_target/7
May 19 23:45:16 fast_target/3
May 19 23:45:16 slow_target/8
May 19 23:45:16 slow_target/9
May 19 23:45:21 fast_target/4
May 19 23:45:21 slow_target/10
May 19 23:45:26 fast_target/5
May 19 23:45:31 fast_target/6
May 19 23:45:36 fast_target/7
May 19 23:45:41 fast_target/8
May 19 23:45:46 fast_target/9
May 19 23:45:51 fast_target/10

注意,slow_targets是并行启动的,但每次只启动一个fast_target。

编辑

flock获取给定文件或给定文件描述符的锁。默认情况下,锁是独占的,这意味着只有一个flock调用可以继续,所有其他调用都会阻塞,直到锁被释放。因此,如果并行调用多个目标,则只有一个flock将继续执行,而其他目标将等待锁释放。

菜谱中的语句是基于flock的手册。它打开给定块的fast_target.lock文件上的文件描述符9。开始时,flock获取该描述符的独占锁(因此是fast_target.lock文件),当描述符关闭时(即重定向块结束时),该描述符将自动释放。当这种情况发生时,其他flock之一将继续进行,实际上只允许执行一个fast_target配方。

编辑2

如果已知并始终执行所有fast_targets,则可以按顺序动态调度它们,如下所示:

代码语言:javascript
复制
$ cat Makefile2
SLOW_TARGETS := $(addprefix slow_target/,1 2 3 4 5 6 7 8 9 10)
FAST_TARGETS := $(addprefix fast_target/,1 2 3 4 5 6 7 8 9 10)

all: $(SLOW_TARGETS) $(FAST_TARGETS)

slow_target/%:
        @echo $@
        @python3 -c 'import time; time.sleep(5)'

fast_target/%:
        @echo $@: $^
        @python3 -c 'import time; time.sleep(5)'

$(foreach target,$(FAST_TARGETS), \
  $(eval evaluated_targets += $(target)) \
  $(eval next_target := $(word 2,$(wordlist $(words $(evaluated_targets)),$(words $(FAST_TARGETS)),$(FAST_TARGETS)))) \
  $(eval $(if $(next_target),$(next_target): $(target))) \
)

这将迭代已知的fast_targets列表,对于每个目标,它将定义对前一个目标的依赖关系。这将导致严格的序列运行,因此它们都不会并行运行。此外,它不会阻止make作业,因此执行器将可用于其他目标,而不是在flock上被阻塞。

代码语言:javascript
复制
$ make -f Makefile2 -j8 | ts
May 20 22:38:35 slow_target/1
May 20 22:38:35 slow_target/2
May 20 22:38:35 slow_target/3
May 20 22:38:35 slow_target/4
May 20 22:38:35 slow_target/5
May 20 22:38:35 slow_target/6
May 20 22:38:35 slow_target/7
May 20 22:38:35 slow_target/8
May 20 22:38:40 slow_target/9
May 20 22:38:40 slow_target/10
May 20 22:38:40 fast_target/1:
May 20 22:38:45 fast_target/2: fast_target/1
May 20 22:38:51 fast_target/3: fast_target/2
May 20 22:38:56 fast_target/4: fast_target/3
May 20 22:39:01 fast_target/5: fast_target/4
May 20 22:39:06 fast_target/6: fast_target/5
May 20 22:39:11 fast_target/7: fast_target/6
May 20 22:39:16 fast_target/8: fast_target/7
May 20 22:39:21 fast_target/9: fast_target/8
May 20 22:39:26 fast_target/10: fast_target/9

注意,由于依赖关系,不需要进一步的逻辑操作,就不可能运行例如fast_target/10,因为前面的所有目标也将被运行。flock方法的情况并非如此。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61893540

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档