【问题标题】:Using make to execute independent tasks in parallel使用make并行执行独立任务
【发布时间】:2011-05-05 14:27:51
【问题描述】:

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

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 在这方面非常好)。

【问题讨论】:

    标签: unix shell makefile buildfarm


    【解决方案1】:

    pattern rules

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

    【讨论】:

    • echo {1..1024} | xargs -n 1 -P 4 echo 给予1 3 2 5 4 ... (bash 3) 似乎是我想要的。我当时没有考虑,但我也可以为切片编写n顺序脚本1..N/nN/n+1..2N/n,...只要切片平均出来到同一时间(不是给定的)。
    【解决方案2】:

    首先是简单的部分。正如 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)
    

    【讨论】:

    • 您好,感谢您的帮助。 Bash 3 的模式 {1..1024} 可能可以用于第二部分。
    【解决方案3】:

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

    【讨论】:

    • 在我的情况下,如果需要,我可以将任务的整个输入和输出放在一个 ramdisk 中,但感谢您向我介绍“spindle”的概念。
    【解决方案4】:

    这是不依赖于大括号扩展的更便携的 shell 代码:

    LOGS := $(shell seq 1 1024)

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

    【讨论】:

      【解决方案5】:

      使用 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.htmlhttps://www.youtube.com/playlist?list=PL284C9FF2488BC6D1

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-09-28
        • 2020-07-15
        • 2013-08-20
        • 2016-09-25
        • 2020-02-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多