Tengo un problema al intentar usar el módulo de subprocesos de perl (obviamente no soy bueno en esto).
Leí muchos temas y probé algunos "trucos", pero nada me ayudó.
Mi objetivo es cumplir mi matriz @allMember con varios hash (% memberInfo).

Aquí hay una versión simplificada de mi código:

#!/usr/bin/perl
use strict ;
use warnings ;
use threads ;
use threads::shared ;

my %memberInfo:shared ;
my @member:shared ;
my @allMember:shared ;

my @list = ( 'toto:1.1.1.1:111', 'tata:2.2.2.2:222', 'titi:3.3.3.3:333') ;

@member = @list ;

my $nbThread = 5 ;
for ( 1..$nbThread ) { threads -> create ( \&job_to_parallelize ) ; }
foreach my $thr ( threads -> list() ) { $thr -> join(); }

sub job_to_parallelize {

  while ( my $member = shift(@member)) {
    my ($name,$ip,$port) = split(/:/,$member) ;

    $memberInfo{ip} = $ip ;
    $memberInfo{name} = $name ;
    $memberInfo{port} = $port ;
    push(@allMember,\%memberInfo) ;
           
  }
}

Si inserto un print Dumper(\%memberInfo) ; arriba de push(@allMember,\%memberInfo) ;, tengo la información que quiero:

$VAR1 = {
          'ip' => '1.1.1.1',
          'name' => 'toto',
          'port' => '111'
        };
$VAR1 = {
          'ip' => '2.2.2.2',
          'name' => 'tata',
          'port' => '222'
        };
$VAR1 = {
          'ip' => '3.3.3.3',
          'name' => 'titi',
          'port' => '333'
        };

Pero si pruebo un print Dumper(\@allMember) ; al final de mi secuencia de comandos (después de mi función "job_to_parallelize"), la información es solo el último hash% memberInfo clonado 3 veces:

$VAR1 = [
          {
            'ip' => '3.3.3.3',
            'name' => 'titi',
            'port' => '333'
          },
          {
            'ip' => '3.3.3.3',
            'name' => 'titi',
            'port' => '333'
          },
          {
            'ip' => '3.3.3.3',
            'name' => 'titi',
            'port' => '333'
          }
        ];

Para obtener información, mi matriz @list se completa (en mi secuencia de comandos real) desde un archivo grande (miles de hosts).
Pongo los hosts en @list y luego creo una copia en mi matriz compartida de @member.

Espero ser lo suficientemente claro.

¿Dónde me equivoco? Gracias por su ayuda en este tema.

1
Stephane Proud 3 mar. 2021 a las 13:12

1 respuesta

La mejor respuesta

Vacía la matriz @member en el primer hilo haciendo shift(@member) aquí:

while ( my $member = shift(@member)) {

De modo que los siguientes subprocesos solo vean una matriz vacía. Pruebe la siguiente modificación:

use feature qw(say);
use strict;
use warnings;
use threads ;
use threads::shared ;
use Data::Dumper qw(Dumper);

my @allMember:shared;
my @member = ( 'toto:1.1.1.1:111', 'tata:2.2.2.2:222', 'titi:3.3.3.3:333') ;
my $nbThread = 5 ;
for ( 1..$nbThread ) { threads -> create ( \&job_to_parallelize ) ; }
foreach my $thr ( threads -> list() ) {
    $thr -> join();
}

sub job_to_parallelize {
  for my $member (@member) {
      my ($name,$ip,$port) = split(/:/,$member);
      {
          lock @allMember;
          my %memberInfo:shared = ( ip => $ip, name => $name, port => $port );
          push(@allMember,\%memberInfo);
      }
  }
}

print Dumper(\@allMember);

Salida :

$VAR1 = [
          {
            'port' => '111',
            'ip' => '1.1.1.1',
            'name' => 'toto'
          },
          {
            'port' => '222',
            'ip' => '2.2.2.2',
            'name' => 'tata'
          },
          {
            'port' => '333',
            'ip' => '3.3.3.3',
            'name' => 'titi'
          },
          {
            'ip' => '1.1.1.1',
            'port' => '111',
            'name' => 'toto'
          },
          {
            'ip' => '2.2.2.2',
            'port' => '222',
            'name' => 'tata'
          },
          {
            'name' => 'titi',
            'port' => '333',
            'ip' => '3.3.3.3'
          },
          {
            'name' => 'toto',
            'port' => '111',
            'ip' => '1.1.1.1'
          },
          {
            'port' => '222',
            'ip' => '2.2.2.2',
            'name' => 'tata'
          },
          {
            'name' => 'titi',
            'ip' => '3.3.3.3',
            'port' => '333'
          },
          {
            'ip' => '1.1.1.1',
            'port' => '111',
            'name' => 'toto'
          },
          {
            'name' => 'tata',
            'ip' => '2.2.2.2',
            'port' => '222'
          },
          {
            'port' => '333',
            'ip' => '3.3.3.3',
            'name' => 'titi'
          },
          {
            'port' => '111',
            'ip' => '1.1.1.1',
            'name' => 'toto'
          },
          {
            'ip' => '2.2.2.2',
            'port' => '222',
            'name' => 'tata'
          },
          {
            'ip' => '3.3.3.3',
            'port' => '333',
            'name' => 'titi'
          }
        ];

Editar :

Si desea vaciar la variable @member (no me quedó claro si lo deseaba o no), puede probar esto en su lugar:

use feature qw(say);
use strict;
use warnings;
use threads ;
use threads::shared ;
use Data::Dumper qw(Dumper);

my @allMember:shared ;
my $lockvar:shared;
my @member:shared = ( 'toto:1.1.1.1:111', 'tata:2.2.2.2:222', 'titi:3.3.3.3:333') ;

my $nbThread = 5 ;
for ( 1..$nbThread ) { threads -> create ( \&job_to_parallelize ) ; }
foreach my $thr ( threads -> list() ) {
    $thr -> join();
}

sub job_to_parallelize {
    while (@member) {
        lock $lockvar;
        my $member = shift @member;
        my ($name,$ip,$port) = split(/:/, $member);
        {
            my %memberInfo:shared = ( ip => $ip, name => $name, port => $port );
            push(@allMember,\%memberInfo);
        }
    }
}

print Dumper(\@allMember);

Salida :

$VAR1 = [
          {
            'name' => 'toto',
            'port' => '111',
            'ip' => '1.1.1.1'
          },
          {
            'name' => 'tata',
            'port' => '222',
            'ip' => '2.2.2.2'
          },
          {
            'name' => 'titi',
            'port' => '333',
            'ip' => '3.3.3.3'
          }
        ];
2
Håkon Hægland 3 mar. 2021 a las 12:21