Запуск нескольких заданий в Perl-скрипте одновременно - PullRequest
0 голосов
/ 27 января 2019

Мне нужно запустить программу кодирования видео, где у меня разные параметры квантования 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 -fs0 -f 2 --InputBitDepth = 16 --OutputBitDepth = 16 --InternalBitDepth = 16 --InputChromaFormat = 400 --ConformanceMode = 1 --SEIDecodedPictureHash >> BSEQ_1.txt

В каждой итерации Iизменить только QP.Теперь в моем скрипте Perl, когда я выполняю строку выше, он ожидает завершения и затем переходит к следующей итерации в цикле (например, qp=2).

Также верхний уровень вызывал скрипт 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`;
    }

Ответы [ 2 ]

0 голосов
/ 27 января 2019

Как насчет наивного подхода, основанного на 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 для управления потоками выполнения и зависимостями, но в вашем случае я думаю, что в этом нет необходимости.

0 голосов
/ 27 января 2019

Я использую подобный код в течение многих лет

#!/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

, которую вы можете установить Parallel::ForkManager из CPANНапример, sudo cpanm Parallel::ForkManager или много других способов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...