代码之家  ›  专栏  ›  技术社区  ›  Will Robertson

多核并行制造而不是“线程”执行?

  •  1
  • Will Robertson  · 技术社区  · 16 年前

    我有一个Makefile来执行一个大致如下的测试套件:

    %.diff.png: %.test.png
        echo '$*: Comparing with good PNG.'
    
    %.test.png: %.pdf
        echo '$*: Converting PDF to PNG.'
    
    %.pdf: %.tex
        echo '$*: Generating PDF output.'
    

    echo 语句在实际Makefile中用实际测试进行补充。

    当我用 make test test 上面没有显示目标),我明显得到线性输出:

    ...
    umtest200b: Generating PDF output.
    umtest200b: Converting PDF to PNG.
    umtest200b: Comparing with good PNG.
    ...
    

    当我用多任务make运行这些测试时( make -j2 test

    ...
    umtest202a: Generating PDF output.
    umtest202b: Generating PDF output.
    ...
    umtest202a: Converting PDF to PNG.
    umtest202b: Converting PDF to PNG.
    ...
    umtest202a: Comparing with good PNG.
    umtest202b: Comparing with good PNG.
    ...
    

    也许您可以看到问题所在;在发现测试是否失败之前,它已经运行过了 全部的

    是否有一种方法可以组织测试,以便即使在运行多个作业的情况下,测试也能在继续进行下一个测试之前运行到完成?或者这是一个更好的任务 make

    3 回复  |  直到 16 年前
        1
  •  1
  •   P Shved    16 年前

    除非明确规定目标的执行顺序, make 任意的 顺序——并行和非并行模式。此命令经历的内部算法 在你的情况下会产生不愉快的结果。

    在makefile中,我假设存在一个未公开的“source”变量,该变量包含要测试的目标列表(隐式目标依赖于这些目标)。同时,该变量的立即扩展也会产生正确的结果。

    list=file1 file2 file3 ... fileN
    

    然后,要解决此问题,只需生成以下依赖项即可:

    file2: file1
    file3: file2 
    ...
    fileN: fileN-1
    run_tests: fileN
    

    我们应该如何生成它?让我们写一个foreach eval循环 之后 这个 list

    len=$(words $(list))
    $(foreach t,                                                  \
       $(join                                                     \ 
          $(addsuffix : ,$(wordlist 2,$(len),$(list)) run_tests), \
          $(list)                                                 \
       )                                                          \
       , $(eval $(t))                                             \
    )
    

    这将生成makefile的一部分,就像C预处理器(或者更准确地说,LISP宏)一样。它的工作原理是:针对每一项 t 在由 join 连接(将第一个列表的每个元素与第二个列表的相应元素连接)该列表 file2 file3 ... fileN run_tests : 被添加(从而形成 file2: file3: ... fileN: run_tests: ),带源列表 file1 file2 ... fileN t 在具有连接元素的列表中,将其作为makefile源的一部分进行求值,从而充当上述规则的角色。

    现在只需调用run_tests目标,它将逐个执行。

        2
  •  1
  •   Dana the Sane    16 年前

    我读了一些关于 -j 独立规则 . 每个映像的作业都是独立的,因此每个目标的第一个依赖项将像您看到的那样运行。

    依次,一个接一个 . 所以在每个目标中,你没有办法利用多道程序,

    作为 make 似乎没有按照您想要的顺序处理依赖关系,也许支持并行测试的单元测试框架更适合。我通过谷歌搜索知道有几个出口,但我不能推荐什么时候退出,因为我还没有用过,也不知道你用的是哪种语言。

        3
  •  1
  •   P Shved    16 年前

    突然,我想到了另一个主意!

    %.diff.png:
        $(MAKE) $*.test.png
        echo '$*: Comparing with good PNG.'