我必须运行视频编码程序,其中我具有不同的量化参数QP。 QP从0到51。在我的perl脚本中,我遍历此参数并执行命令行。命令行如下:
TAppEncoder encoder_intra_main_rext.cfg -i BSEQ.RAW -b BSEQ_1.bin -o / dev / null -qp 1 -wdt 7811 -hgt 7911 -fr 1 -fs 0 -f 2 -InputBitDepth = 16 -OutputBitDepth = 16 --InternalBitDepth = 16 --InputChromaFormat = 400 --ConformanceMode = 1 --SEIDecodedPictureHash >> BSEQ_1.txt
在每次迭代中,我仅更改qp。现在,在我的Perl脚本中,当我执行上面的代码行时,它等待完成,然后继续进行循环中的下一个迭代(例如qp=2
)。
顶级shell脚本也调用了perl脚本:
test.sh ---> test.pl ---> command1 with qp=1
---> command2 with qp=2
---> command3 with qp=3
---> command4 with qp=4
---> until the end of the for loop
我想知道如何并行运行两个(或多个)进程。例如,运行qp=1
并在qp=2
之后立即运行,而不必等待qp=1
完成。并且比这两个中的一个完成时(无论qp = 1或qp = 2先完成)运行qp = 3,依此类推。
因此,基本上,我不想并行运行perl脚本,不需要perl脚本的多个实例。我需要脚本(这是循环的一部分)中的命令并行运行。但是,如果还有其他方式可以做到这一点,请告诉我。
代码的一部分在下面,现在它一次运行一个qp。我想一直并行运行2个,一次完成就转到下一个,所以2个进程一直都在运行。
我正在Linux Mint上运行脚本。我在一台计算机上运行它(我没有群集)。想法是将其调整为两个核心。
任何想法如何做到这一点,或者至少从哪里开始? 谢谢。
$QP_end = $Configuration->{nb_QPs}-1;
foreach $QP_index (0 .. $QP_end)
{
$QP = $Configuration->{QP_list}[$QP_index];
print($QP," ");
set_command_line(); # HERE I CHANGE THE QP TO SET NEW COMMAND LINE, AND THEN EXECUTE THE NEW COMMAND
@RunCommand = ($command_line);
`@RunCommand`;
}
答案 0 :(得分:0)
多年来我一直在使用这样的代码
#!/usr/bin/env perl
use strict;
use warnings 'FATAL' => 'all';
use Cwd 'getcwd';
use feature 'say';
my $TOP_DIRECTORY = getcwd();
use autodie qw(:all);
sub execute {
my $command = shift;
print "Executing Command: $command\n";
if (system($command) != 0) {
my $fail_filename = "$TOP_DIRECTORY/$0.fail";
open my $fh, '>', $fail_filename;
print $fh "$command failed.\n";
close $fh;
print "$command failed.\n";
die;
}
}
use Parallel::ForkManager;
sub run_parallel {
my $command_array_reference = shift;
unless ((ref $command_array_reference) =~ m/ARRAY/) {
say "run_parallel requires an array reference as input.";
die;
}
my $manager = new Parallel::ForkManager(2);
foreach my $command (@{ $command_array_reference }) {
$manager->start and next;
execute( $command );
$manager->finish;
}
$manager->wait_all_children;#necessary after all lists
}
使用一系列命令run_parallel
@cmd
您可以从CPAN安装Parallel::ForkManager
,例如sudo cpanm Parallel::ForkManager
或许多其他方式。
答案 1 :(得分:0)
基于fork()
的幼稚方法又如何呢?
# --- Prepare job queues ---
my @jobs = ( ['cmd01'..'cmd10'], ['cmd11'..'cmd20'] ) ;
# --- If fork returns PID means we're in the parent proc ---
# --- otherwise we're in the child proc ---
worker( fork ? $jobs[0] : $jobs[1] ) ;
# --- Worker ---
sub worker {
# --- Do jobs ---
foreach my $cmd ( @{ $_[0] } ){
# --- Do system command or die if RC > 0 ---
die $! if system($cmd) ;
}
}
主要概念是将您的作业队列分成多个块,然后分叉以使并行度为2(或您想要的任何值)的进程,然后每个进程将处理其作业队列。
这是一个工作正常的示例,并行度为2。如果需要更多并行处理,则必须根据所需的并行性和fork()
进行parallelism - 1
次来实现作业队列的划分。
由于每个分叉的进程都在其自己的地址空间中运行,因此它们彼此之间是不可知的。这意味着,根据您的需要,您可能必须实施IPC机制来控制执行流和依赖关系,但是对于您而言,我认为这是不必要的。