【发布时间】:2019-03-08 02:52:21
【问题描述】:
我有以下 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(我以前从未使用过)时做错了。我的目标只是用它来并行化我的工作,然后等到所有工作都完成,然后在我的脚本中继续前进。
任何帮助将不胜感激,谢谢!
【问题讨论】:
-
乍一看你的用法对我来说是正确的。确保您使用的是严格和警告,最好在您需要它们的范围内声明您的变量,而不是在文件顶部。例如
foreach my $RunId ...和my $SampId = ...我假设您在开始循环之前以某种方式填充了%hash? -
是的,他们之前填充了哈希,我没有在这里添加它,因为它并不真正相关。正如我所写,foreach 循环运行顺利,只是 forkmanager 在孩子仍在运行时退出了父级,你们知道为什么吗?
-
大胆猜测:您的一个子进程可能导致了 SIGPIPE。尝试在循环之前在父级中设置
$SIG{PIPE} = 'IGNORE';。 -
(1) 为什么要使用排队系统——有必要吗?这可能会对任何事情产生影响,当然也会影响到这一点。 (2) 您是否确认子代码按顺序正确运行(甚至仅针对一种情况)?您可以通过注释掉几行来做到这一点。
-
删除
$pm->finish;是完全错误的。$pm->finish;与exit;相同。如果你删除它,孩子将开始执行父母的代码并声明创建自己的孩子。
标签: perl parallel-processing fork