我有以下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上做错了(我以前从未使用过)。我的目标是仅使用它来并行化我的工作,然后等待所有工作完成,然后继续执行我的脚本。
任何帮助将不胜感激,谢谢!
答案 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中写了一个示例。