ForkManager(Perl)在子级作业准备好之前退出了父级作业

时间:2018-10-02 22:50:50

标签: perl parallel-processing fork

我有以下perl代码:

use Parallel::ForkManager;
  my $maxpro = 15;
  my $pm = Parallel::ForkManager->new($maxpro);
my $SampId;
my $SampDir;
my $RunId;
my $Runfile;
my %hash;
 foreach $RunId(keys(%hash)) {
 $pm->start and next;
 $SampId = $hash{$RunId};
 $Runfile = $rundir . $RunId . "fastq";

 if ($SampId =~ m/16S/) {
     $SampDir = $SiXSSdir . $SampId . "_Split/"; 
 }
 elsif ($SampId =~ m/ITS/) {
     $SampDir = $ITSdir . $SampId . "_Split/";
 }
 #make a directory for each file
 my $dirouteach = $outdir . $SampId . "Single_directory.out";
 my $dirm4 = "bsub -o $dirouteach mkdir $SampDir";

 system('bash', '-c', "$dirm4") == 0 or die "Can't create each single subdirectories for either 16S or ITS, or both, see line 114" . "\n";
$pm ->finish;
}

$pm -> wait_all_children();

但是,当我像这样运行它时,所有子项目都在运行,但是主脚本过早退出,即使在子项完成之前,它也不会给出任何错误消息。我还尝试删除$pm ->finish;来运行它,但是在那种情况下,脚本被卡住并永远等待直到子级完成。 我确信我在fork manager上做错了(我以前从未使用过)。我的目标是仅使用它来并行化我的工作,然后等待所有工作完成,然后继续执行我的脚本。 任何帮助将不胜感激,谢谢!

2 个答案:

答案 0 :(得分:4)

bsub已经成为并行计算框架的一部分。 bsub命令本身运行很快;它只是将作业提交给作业调度程序并退出。它不应该等待计划的作业完成,因此您的所有子进程都应快速完成,并且主程序也将快速退出。

如果要自己控制并行处理,则应在不使用bsub的情况下执行每个命令。如果您使用的是bsub,则无需自己进行分叉或使用Parallel::ForkManager之类的后台进程管理器。

答案 1 :(得分:1)

我没有调试Parallel :: ForkManager的想法,但这是一个使用IO::Async的示例,它稍微灵活一些,同时为原始fork和waitpid提供了一个不错的包装器。

use strict;
use warnings;
use IO::Async::Loop;
use Future;

my $loop = IO::Async::Loop->new;
my @futures;
my %hash;
... # populate %hash
foreach my $RunId (keys %hash) {
  my $dirm4;
  ... # build $dirm4
  my $future = $loop->new_future;
  my $process = $loop->open_process(
    command => ['bash', '-c', $dirm4],
    on_finish => sub { $future->done(@_) },
    on_exception => sub { $future->fail(@_) },
  );
  push @futures, $future;
}

# run event loop until all the futures are done, or throw an exception if one fails to start the command
my @exit_codes = Future->needs_all(@futures)->get;

如果您不想一次全部启动队列,也可以使用Future::Utils来实现队列,我最近在this answer中写了一个示例。