O GNU Parallel não executa os jobs até que o programa tenha saído

4

Quando eu corro (o código do rss-notifier é incluído no final),

rss-notifier.zsh https://www.wuxiaworld.com/feed/chapters ".*"|parallel --null -k --lb echo {}

Eu recebo

Title: Sovereign of the Three Realms -                     
por HappyFace 18.11.2018 / 09:57

1 resposta

1

Você está sendo atingido por dois problemas.

Isso

(seq 200; sleep 20) | parallel -j10  -k echo

impressões:

1
2

e depois pára até que o sleep 20 seja concluído.

Uma correção parcial parece ser mover start_more_jobs() fora do loop while :

--- a/src/parallel
+++ b/src/parallel
@@ -4062,9 +4062,8 @@ sub reaper {
        # $stiff = pid of dead process
        if(wantarray) {
            push(@pids_reaped,$stiff);
-       } else {
-           $children_reaped++;
        }
+       $children_reaped++;
         if($Global::sshmaster{$stiff}) {
             # This is one of the ssh -M: ignore
             next;
@@ -4112,12 +4111,12 @@ sub reaper {
             }
         }
        $job->cleanup();
-       start_more_jobs();
        if($opt::progress) {
            my %progress = progress();
            ::status_no_nl("\r",$progress{'status'});
        }
     }
+    if($children_reaped) { start_more_jobs(); }
     $opt::sqlmaster and $Global::sql->run("COMMIT;");
     debug("run", "done ");
     return wantarray ? @pids_reaped : $children_reaped;

Isso pode custar algum desempenho se você tiver muitos trabalhos de curta duração. Eu não medi o quanto.

A outra parte do problema é devido a uma decisão de projeto no GNU Parallel.

Argumentos no GNU Parallel são lidos usando o operador de diamante (< >). Isto lê uma linha completa antes de continuar. A leitura de (sleep 20) gera apenas um fim de arquivo após sleep terminar e, assim, bloqueia até sleep terminar.

Então, quando o GNU Parallel lê o byte final, ele tem que esperar que o sleep termine de descobrir que esse é realmente o fim do arquivo.

Não vejo uma maneira fácil de alterar essa parte do design.

Felizmente, isso não impede que os trabalhos sejam executados, como você pode ver se você executar date . As tarefas são iniciadas imediatamente, é apenas a saída que está aguardando o sleep :

(seq 20; sleep 5) | parallel -j10  -k 'date;echo'

Em outras palavras: Seu problema não está relacionado a -N2 . Você não pode ver o problema aqui:

(printf '%s
(printf '%s
(printf '%s
(printf '%s
(seq 200; sleep 20) | parallel -j10  -k echo
' {1..40}; sleep 2) | parallel -j4 --null -k --lb -N 2 'date;'echo {1} {2}
' {1..40}; sleep 2) | parallel -j8 --null -k --lb -N 2 echo {1} {2}
' {1..40}; sleep 2) | parallel -j4 --null -k --lb -N 2 echo {1} {2}
' {1..4}; sleep 2) | parallel --null -k --lb -N 2 echo {1} {2}

Mas você pode ver o problema aqui. Isso pausa antes dos últimos 4-8 elementos:

1
2

Esta pausa antes dos últimos 8-10 elementos:

--- a/src/parallel
+++ b/src/parallel
@@ -4062,9 +4062,8 @@ sub reaper {
        # $stiff = pid of dead process
        if(wantarray) {
            push(@pids_reaped,$stiff);
-       } else {
-           $children_reaped++;
        }
+       $children_reaped++;
         if($Global::sshmaster{$stiff}) {
             # This is one of the ssh -M: ignore
             next;
@@ -4112,12 +4111,12 @@ sub reaper {
             }
         }
        $job->cleanup();
-       start_more_jobs();
        if($opt::progress) {
            my %progress = progress();
            ::status_no_nl("\r",$progress{'status'});
        }
     }
+    if($children_reaped) { start_more_jobs(); }
     $opt::sqlmaster and $Global::sql->run("COMMIT;");
     debug("run", "done ");
     return wantarray ? @pids_reaped : $children_reaped;

Ao executar date , você pode ver que o problema não é o início dos trabalhos - está apenas adiando a impressão:

(seq 20; sleep 5) | parallel -j10  -k 'date;echo'
    
por 19.11.2018 / 17:35