4

我有一堆我想并行执行的命令。命令几乎相同。预计它们将花费大约相同的时间,并且可以完全独立运行。它们可能看起来像:

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可用内核的数量在哪里。

我不想重新发明轮子。这个问题已经在 Unixmake程序中解决了(当与-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在这方面非常好),我对此持开放态度。

4

5 回答 5

4

这是不依赖于大括号扩展的更可移植的 shell 代码:

日志 := $(shell seq 1 1024)

请注意使用 := 来定义更有效的变量:简单扩展的“风味”。

于 2010-11-09T10:12:45.817 回答
3

查看模式规则

另一种方法,如果这是您需要 的唯一原因make,是使用-n-P的选项xargs

于 2010-11-05T14:58:23.160 回答
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)
于 2010-11-05T16:01:09.917 回答
3

xargs -P 是执行此操作的“标准”方式。请注意,根据磁盘 I/O,您可能希望限制为主轴而不是内核。如果您确实想限制核心,请注意最近 coreutils 中的新 nproc 命令。

于 2010-11-05T16:19:33.730 回答
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

于 2013-11-05T21:30:10.530 回答