我有一堆我想要并行执行的命令。命令几乎相同。它们可能需要大约相同的时间,并且可以完全独立运行。他们可能看起来像:
command -n 1 > log.1
command -n 2 > log.2
command -n 3 > log.3
...
command -n 4096 > log.4096
我可以在shell脚本中并行启动所有这些,但系统会尝试加载超过严格必要的负载以保持CPU忙(每个任务占用一个核心的100%直到它完成)。这会导致磁盘颠簸并使整个事情变得比不那么贪婪的执行方法慢。
最好的方法可能是保持n
个任务正在执行,其中n
是可用内核的数量。
我不想重新发明轮子。这个问题已在Unix make
程序中解决(与-j n
选项一起使用时)。我想知道是否有可能为上面的内容编写通用的Makefile规则,以避免线性大小的Makefile看起来像:
all: log.1 log.2 ...
log.1:
command -n 1 > log.1
log.2:
command -n 2 > log.2
...
如果最佳解决方案不是使用make
而是使用另一个程序/实用程序,只要依赖关系合理(make
在这方面非常好),我就会对此持开放态度。
答案 0 :(得分:4)
这是更多可移植的shell代码,不依赖于大括号扩展:
LOGS:= $(shell seq 1 1024)
注意使用:=来定义一个更有效的变量:简单扩展的“味道”。
答案 1 :(得分:3)
另一种方式,如果这是您需要make
的唯一原因,则使用-n
的{{1}}和-P
选项。
答案 2 :(得分:3)
首先是简单的部分。正如Roman Cheplyaka指出的那样,模式规则非常有用:
LOGS = log.1 log.2 ... log.4096
all: $(LOGS)
log.%:
command -n $* > log.$*
棘手的部分是创建该列表LOGS
。 Make不是很擅长处理数字。最好的方法可能是调用shell。 (您可能必须为shell调整此脚本 - shell脚本不是我最强的主题。)
NUM_LOGS = 4096
LOGS = $(shell for ((i=1 ; i<=$(NUM_LOGS) ; ++i)) ; do echo log.$$i ; done)
答案 3 :(得分:3)
xargs -P是执行此操作的“标准”方式。 注意,根据磁盘I / O,您可能希望限制为主轴而不是核心。 如果您确实要限制核心,请记录最近coreutils中的新nproc命令。
答案 4 :(得分:2)
使用GNU Parallel,你会写:
parallel command -n {} ">" log.{} ::: {1..4096}
10秒安装:
(wget -O - pi.dk/3 || curl pi.dk/3/ || fetch -o - http://pi.dk/3) | bash
了解详情:http://www.gnu.org/software/parallel/parallel_tutorial.html https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1