并行运行现有可执行文件的通用方法

时间:2012-03-29 19:50:58

标签: c++ c language-agnostic cross-platform parallel-processing

我正在尝试考虑一种有关并行运行现有可执行文件的方法的解决方案。到目前为止我提出的是制作一个将指定的可执行文件放入队列(由'服务器'管理)的包装器。我遇到的问题是当我需要运行多个可执行文件时,其输出是另一个可执行文件输入。

示例:

我有一个可执行文件 A ,其输出是一个文件(图像)。 我有另一个可执行文件 B ,其输入是一个文件列表(考虑从 A 的图像创建缩略图,将它们存储在存档中等)

问题是:有没有办法让 B 可执行文件等待多个 A 进程完成?

有没有一种标准的方法可以做到这一点?我对这个概念很感兴趣,如果可能的话,而不是语言。如果解决方案是跨平台的话会很好,但目前我没有任何解决方案,所以请随意分享您的想法。我认为这将以某种方式在C / C ++中完成,因为它需要一些低级别的交互。

简化为:

  

我有一些在后台运行的可执行文件( A )和另一个使用其输出作为输入的可执行文件( B )。如何阻止执行 B ,直到所有需要的输入文件都可用。

注意: 可执行文件 A 在计算机上连续运行,但某些输入文件由 B 定期“收集”。

  

感谢您的任何建议,

尤利安

6 个答案:

答案 0 :(得分:1)

如果您正在谈论为您执行此操作的程序,GNU Parallel将为您执行此操作。您可以将其设置为在cron作业上运行,或者您认为需要的任何内容。我们经常从脚本运行它来重写大量文本(或代码)并充分利用机器的所有内核来完成这项工作。通常你可以使用Parallel和脚本以及sed / awk来获得你真正需要做的事情。但是,如果您想以编程方式执行此操作,我并不完全清楚,所以这可能不是最佳答案。

答案 1 :(得分:1)

你可能不需要写任何东西:

whenjobs是一个cron替代品,它不仅允许您指定作业(可能重复),还会考虑作业依赖性:

答案 2 :(得分:0)

通常的方法是使用同步原语,例如信号量或障碍。但是,这不(仅)取决于语言,但需要与平台(通常是操作系统)进行交互。

但是,C ++ 11标准在库级别部署了标准化的线程模型。

答案 3 :(得分:0)

我认为这样做的方法是创建一个依赖树,其中子节点依赖于父节点的输出。然后,您可以并行运行树的每个级别。

例如:

P1的输出转到P2和P3

P2的输出转到P4

P3的输出转到P4。

然后你的树看起来像:

                     P1
                    /  \
                   P2  P3
                    \  /
                     P4

你必须首先运行P1,P2和P3可以并行运行,然后P4最后执行。

此外,它不一定是C ++,任何旧语言都可以使用我确定的技巧

修改 如果您不知道上一个作业何时结束以启动下一个作业,您可以设置一个循环,在每个设置的时间间隔内遍历您要运行的所有可执行文件,并检查是否创建了所需的文件,如果它们是他们运行它,否则等到下一次迭代再次检查。

一般概念(在C ++中)可能类似于:

    struct Job
    {
      bool PreconditionsSatisfied();
      void Run();
    };

    std::vector<Job> jobs;

    //Fill up with appropriate info

    while(jobs.size() != 0)
      {
        for(int i = 0; i < jobs.size(); i++)
          {
             if(jobs[i].PreconditionsSatisfied())
              {
                //start new thread and run job
                jobs.erase(jobs.begin() + i);
                i--;
              }
          }
        sleep(TIME_INTERVAL);
      }

答案 4 :(得分:0)

人们经常使用make(或其他构建工具)来实现这一点,因为这正是这些工具的作用:基于具有依赖性的输入构建事物,并且大多数 - 当然是make - 可以并行执行此操作。如果你有一个可执行文件从(例如)数据文件中生成一系列图像,并且你有两批要处理它们(比如通过将它们相互附加),你必须分别在每个批处理上运行第二个可执行文件,然后是以下Makefile

execA=./gnuplotwrapper
execB=convert

all: figure1.png figure2.png

# convert txt files to png files using a gnuplot script "gnuplotwrapper"

%.png: %.txt
    $(execA) $^ $@

# take two figures and append them using imagemagick's "convert"

figure1.png: data1.png data2.png
    $(execB) $^ +append $@

figure2.png: data3.png data4.png
    $(execB) $^ +append $@

clean:
    rm -f *.png

将使用可执行文件A从数据文件生成图像文件,使用可执行文件B来处理批量图像文件。通过使用(例如)make -j 4来运行它,make将尝试并行使用最多4个进程来构建最终结果(此处为figure1.png和figure2.png)。

答案 5 :(得分:0)

如果您需要在系统上运行不同的可执行文件,我认为最干净的解决方案是使用scheduler。 Slurm或TORQUE应该是不错的选择。

此外,您要求的特定功能有时被称为多步作业调度。如果调度程序本身不支持,那么很容易通过一系列作业获得相同的结果,如果成功,将提交他们的继续。