多核以并行方式而不是“线程化”方式进行。执行?

发布于 2024-08-09 00:30:59 字数 950 浏览 1 评论 0原文

我有一个 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.
...

也许您可以看到问题;在发现测试是否失败之前,它已经为每个其他测试运行了所有 PDF 生成和 PNG 转换。

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

I have a Makefile to execute a test suite that looks roughly like this:

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

%.test.png: %.pdf
    echo '$*: Converting PDF to PNG.'

%.pdf: %.tex
    echo '$*: Generating PDF output.'

with all the echo statements supplemented with the actual tests in the real Makefile.

When I execute all of these tests with make test (the test target is not shown above), I obviously get linear output:

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

When I run these tests with multi-job make (make -j2 test, say), the tests are executed in a "threaded" order:

...
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.
...

Perhaps you can see the problem; before discovering if the test fails it's already run through all of the PDF generations and PNG conversions for every single other test.

Is there a way to organise the tests so that even when run with multiple jobs the tests are run to completion before moving on to the next test? Or is this a task for a better make?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

や三分注定 2024-08-16 00:30:59

除非明确指定目标的执行顺序,否则 make 将以任意顺序执行它们——并行和非并行模式。该命令经过 make 的内部算法,在您的情况下会产生令人不快的结果。

解决方案是对您的测试强制执行明确的顺序。

从您的 makefile 部分来看,我假设存在一个未公开的“源”变量,其中包含要测试的目标列表(隐式目标取决于这些目标)。该变量的立即扩展也会产生正确的结果。

假设变量是这样的:

list=file1 file2 file3 ... fileN

那么,为了解决这个问题,生成以下依赖就足够了:

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

我们应该如何生成它?让我们在 list 变量获取其值之后编写一个 foreach-eval 循环:

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

这将生成 makefile 的一部分,就像 C 预处理器一样(或者更准确地说,LISP 宏) 。它将像这样工作:对于通过joining(将第一个列表的每个元素与第二个列表的相应元素连接)形成的列表中的每个项目t,列表file2 file3 ... fileN run_tests,每个元素添加后缀 : (从而形成 file2: file3: ... fileN: run_tests: ),带有源列表 file1 file2 ... fileN; - 对于带有连接元素的列表中的每个这样的项目 t ,将其作为 makefile 源代码的一部分进行评估,从而按照上面所示的规则进行操作。

现在您只需调用 run_tests 目标,它将一一进行。

Unless the order of execution of targets is explicitly specified, make executes them in an arbitrary order--both in parallel and in non-parallel mode. This order undergoes internal algorithms of make and in your case yields unpleasant results.

The solution is to impel an explicit ordering to your tests.

From your part of makefile, I assume that there exists an unrevealed "source" variable that contains a list of targets to test (on these targets implicit ones depend). Also immediate expansion of that variable yields correct results.

Assume the variable's like that:

list=file1 file2 file3 ... fileN

then, to solve the problem, it would suffice to generate the following dependencies:

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

How should we generate it? Let's write an foreach-eval loop after the list variable gets its value:

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

This will generate a part of makefile just like C preprocessor does (or, more correctly, LISP macros). It will work like this: for each item t in the list formed by joining (concatenating each element of first list with corresponding element of the second) the list file2 file3 ... fileN run_tests, to each element of which a suffix : is added (thus forming file2: file3: ... fileN: run_tests:), with source list file1 file2 ... fileN; - for each such item t in list with joined elements evaluate it as part of makefile's source, thus acting as the rules shown above were prescribed.

Now you're only to invoke run_tests target and it will go one-by-one.

陌路终见情 2024-08-16 00:30:59

突然,我的脑海里又冒出了另一个想法!

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

这解决了所有问题,除了测试可能无法按正确的顺序调用(但实际上它们很可能会顺利进行)。

Suddenly, another idea came into my mind!

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

This solves everything except that tests may not be invoked in proper order (but in practice they most likely will go well).

撩发小公举 2024-08-16 00:30:59

我对 -j 标志进行了一些阅读,我认为问题在于这为独立规则启动了新的工作。每个图像的作业都是独立的,因此每个目标的第一个依赖项将像您所看到的那样运行。

我认为这里的主要问题是这个任务本质上是串行的,也就是说每个目标的依赖项必须按顺序运行,一个接一个。因此,在每个目标中,您无法在这种粒度级别上利用多道程序设计的优势。

由于 make 似乎没有按照您想要的顺序处理依赖项,因此支持并行测试的单元测试框架可能更合适。我通过谷歌搜索知道其中有几个退出,但我不能推荐什么时候退出,因为我没有使用过任何退出,并且不确定您正在使用哪种语言。

I did some reading on the -j flag and I think the issue is that this starts new jobs for independent rules. The jobs for every image are independent, so the first dependency for each target will be run like you're seeing.

I think the main problem here is that this task is inherently serial, that's to say that the dependencies for each target must be run in order, one after another. So within each target, you don't have a way to take advantage of multiprogramming, at this level of granularity.

As make doesn't seem to be processing dependencies in the order that you want, perhaps a unit testing framework that supports parallel tests would be a better fit. I know through some Googling that several of these exits, but I can't recommend when as I haven't used any and am not sure which language you're using.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文