IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Programmation et administration système Perl Discussion :

Aide fork() petit-fils gérés par le père ?


Sujet :

Programmation et administration système Perl

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Inscrit en
    Mai 2011
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mai 2011
    Messages : 13
    Points : 8
    Points
    8
    Par défaut Aide fork() petit-fils gérés par le père ?
    Bonjour à tous,
    tout d'abord, bravo pour ce forum, très souvent, je trouve la solution sur ce dernier .
    Je me tourne vers vous après avoir rechercher longuement une aide particulière à mon problème.

    Je développe actuellement un script PERL pour analyser plusieurs fichiers en parallèle (j'ai accès à un joli serveur que j'apprends à utiliser, n'étant pas informaticien de formation, ça me prends du temps ).
    Bref, mon script prend chaque fichier, et fais quelques prétraitements dessus. Pour cela, et afin d'accélerer la chose, je crée des processus fils (via la fonction fork()) pour chaque fichier.
    Malheureusement (j'aime bien compliquer les choses), après ces prétraitements, chacun de ces fils crée plusieurs petits-fils pour d'autres traitements sur chaque fichier.
    Mon problème est que j'aimerai que le père contrôle l'arrêt des petits-fils et non des fils (car ce sont les petits-fils qui sont les plus longs).
    Mon programme fonctionne correctement et donne de bon résultats, seulement, il indique qu'il a fini alors que les petits-fils tournent encore quand je fais sauter la ligne 315. Par contre, c'est optimal au niveau temps de calcul.
    Si je la laisse, ce n'est pas optimal, car il attend que tous les petits-fils pour un fichier aient fini, pour passer à l'autre fichier.

    Voici le code (je l'ai annoté en anglais, désolé, je travaille principalement avec des étrangers ):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
     
    #!/usr/bin/perl
    #Print errors during the implementation of the perl program
    use strict; use POSIX;
     
    #C core to increase the efficiency of the comparison program
    #This program takes 3 arguments (2 strings and one threshold: respectively str_a, str_b and max). This 
    #program will then compare the two strings, and if the number of differences is higher than max, then
    #the program returns the number of differences and stop, or returns the real number of differences.
    use Inline C => <<'END_OF_C';
     
    int c_compare( SV* str_a, SV* str_b, int max ) {
      int diff = 0;
      STRLEN len_a, len_b, len, i;
      char *a, *b;
      a = SvPV( str_a, len_a );
      b = SvPV( str_b, len_b );
      len = len_a < len_b ? len_a : len_b;
     
      for( i = 0; i < len; i++ ) {
        if( a[i] != b[i] ) diff++;
        if(diff > max) break;
      }
     
      return diff;
    }
     
    END_OF_C
     
    #Defined variables
    my @childs = (); my $pid = 0;
    my @childs2 = (); my $pid2 = 0;
    my $file = "";
    my $tmp = "";
    my $dist_cutoff = 0;
    my $dist_cutoff_stored = 0;
    my $dist_cutoff_step = 0;
    my $dist_cutoff_step_stored = 0;
    my $mean_length = 0;
    my $i, my $j, my $k, my $h, my $x= 0,0,0,0,0;
    my $nb_char_treated = 0;
    my $nb_treated_lines = 0;
    my $max_abund = 0;
    my $max_abund_pos = 0;
    my $nb_seqs_aligned_class = 0;
    my $exchange = "";
    my $count = 0;
    my $count_diff = 0;
    my $column_analysis = "";
    my $descr_line = "";
    my $char1 = "";
    my @tmp, my @tmp2 = (),();
    my @tab_descr = ();
    my @tab_descr_occur = ();
    my @tab_align_seq = ();
    my @tab_align_seq_clean = ();
    my $nb_seq_tot = 0;
    my $nb_seq_tot_derep = 0;
    my @seqs_already_clustered = ();
    my @seq1 = ();
    my @seq2 = ();
    my $seq1 = "";
    my $seq2 = "";
    my @defined_clusters = ();
    my $nb_clusters = 0;
    my $length_seq1, my $length_seq2 = 0,0;
     
    #Asking for the desired maximum dissimilarity percentage tolerated for clustering
    print ("Please define the maximum percentage dissimilarity threshold for clustering\n (percent) ?\n");
    #Deleting the last character of the string and transforming it in integer,
    chomp($dist_cutoff = <STDIN>);
    $dist_cutoff = 0 + $dist_cutoff;
    $dist_cutoff_stored = $dist_cutoff;
     
    #Asking for the step size between 0 and the defined threshold
    print ("Please define the step size percentage for clustering (percent) ?\n");
    #Deleting the last character of the string and transforming it in integer
    chomp($dist_cutoff_step = <STDIN>);
    $dist_cutoff_step = 0 + $dist_cutoff_step;
    $dist_cutoff_step_stored = $dist_cutoff_step;
     
    #=======================================================================================================
    #First step, store all descriptive lines and corresponding sequences in two tables: @tab_descr and 
    #@tab_align_seq for further analysis.
    #=======================================================================================================
     
    #Open the directory containing all files needed to be treated
    opendir (DIR, "IN/") || die "can't opendir IN: $!";
    #For each file found in the directory IN/
    BOUCLE:while (defined($file = readdir(DIR)))
    {
    	#No treatment for files '.' and '..'
      	if ($file =~ /^\.\.?$/){next BOUCLE;}
      	else
      	{
      		$pid = fork();
      		#If the program is the parent! (only one)
    		if ($pid) {push(@childs, $pid);}
    		#If the program is a child (max 10)
    		elsif ($pid == 0)
    		{
        			#Open file needed to be treated
        			open(F1, "IN/$file")|| die "==> File Not Found: $file<==";
        			#Needed empty variables for each step (several files)
        			$mean_length = 0;
    			$nb_seq_tot_derep = 0;
        			$nb_seq_tot = 0;
        			@tab_descr = ();
        			@tab_align_seq = ();
        			@tmp = ();
        			#For every line of the file given by the user
        			BOUCLE1:while (<F1>)
        			{
          			#If the line contains the character : ">"
          			if ($_ =~ s/>//)
          			{
            				#We do not keep the last line of the alignment, corresponding to the template
            				if ($_ =~ m/#=GC_RF/) {next BOUCLE1;}
            				else
            				{
            					#Split the line to store it in @tmp based on the '_' character
    						@tmp = split("_",$_);
    						#Count the number of sequences (not dereplicated to give in results file)
    						$nb_seq_tot_derep += $tmp[1];
    						#Store in $tab_descr_occur the number of occurences for each sequence for further sorting
    						$tab_descr_occur[$nb_seq_tot]=$tmp[1];
    						#Determine the mean length for sequences using dereplicated sequences
    						$tmp[2] =~ /length=(\d*)/;
    						$mean_length += $1*$tmp[1];
    						#Store the descriptive line in @tab_descr and increment the needed value $nb_seq_tot
    						#after deletion of potential spaces or \n
    						$_=~ s/\s//g;
    						$tab_descr[$nb_seq_tot++] = $_;
            				}
          			}
          			#If the line is the sequence itself
          			else
          			{
          				#We not keep the last line of the alignment, corresponding to the template
          				if ($_ =~m/x/) {next BOUCLE1;}
    					$tab_align_seq[$nb_seq_tot-1] = $_;
          			}
        		}
        			#We close the file as it is not needed anymore
        			close F1;
        			#Computation of the mean length to determine the number of tolerated differences
        			$mean_length = int($mean_length/$nb_seq_tot_derep+0.5);
        			#Determine the number of tolerated differences to cluster sequences and the step size
        			$dist_cutoff = ceil($mean_length*$dist_cutoff_stored/100);
        			$dist_cutoff_step = floor($mean_length*$dist_cutoff_step_stored/100);
        			#We cleared out the @tmp table to reuse it
        			@tmp = ();
     
    #===================================================================================================
    #Second step, reorganize sequences and descriptive lines based on their decreased abundance.
    #===================================================================================================
     
    			#Needed empty variables for next step
    	    		@tmp = ();
    	    		$nb_seqs_aligned_class = 0;
     
    	    		#Loop to read all sequences one by one
    	    		BOUCLE2:for ($i=0;$i<$nb_seq_tot;$i++)
    	    		{
    	    			#Definition of a new table containing three elements, the number of occurences, the descriptive 
    				#line and the corresponding sequence
    				@tmp[$i] = [$tab_descr_occur[$i],$tab_descr[$i],$tab_align_seq[$i]];
    			}
    			#Reorganizing the table @tmp defined previouly by decreasing abundance based on the occurences
    	     	@tmp2 = reverse sort { $a->[0] <=> $b->[0] } @tmp;
    	     	#Needed empty variables
    	     	@tmp = ();
    	    		@tab_descr = ();
    	    		@tab_align_seq = ();
    	    		#Open the temporary file in the Tmp/ directory
    	    		#Loop to recreate reorganized tables
        			BOUCLE3:for ($i=0;$i<$nb_seq_tot;$i++)
        			{
          			$tab_descr[$i] = $tmp2[$i][1];
     
          			$tab_align_seq[$i] = $tmp2[$i][2];
        			}
     
        			#Opening needed files to to store results (details and summary)
    	    		$file =~ /(\w*)\./;
    	    		open (FILE_R_DETAILS, ">OUT/$1_clust.clust");
    	    		open (FILE_R, ">OUT/$1_clust.txt");
    	    		#Print needed data in files for further steps
    	    		printf (FILE_R_DETAILS "File(s):\t$file\nSequences:\t$nb_seq_tot_derep \n\n");
    	    		printf (FILE_R "Total sequences\t$nb_seq_tot_derep \n\nCutoff\tClusters(OTUs)\n");
    	    		#Close files to give them for child processes
    	    		close (FILE_R_DETAILS);
    	    		close (FILE_R);
     
    	    		#Needed empty variables for next step
    	    		@tab_align_seq_clean = ();
    	    		@tmp = ();
    	    		$count = 0;
    	    		$nb_treated_lines = 0;
    	    		$column_analysis = "";
     
    	    		BOUCLE10:for($h=$dist_cutoff_step;$h<=$dist_cutoff;$h=$h+$dist_cutoff_step)
    	    		{
    	    			#Empty variable needed to treat several clustering for one file
    	    			$descr_line = "";
    	    			@defined_clusters = ();
    	    			$nb_clusters = 0;
     
    	    			$pid2 = fork();
    	    			#If the program is the parent! (only one)
    				if ($pid2) {push(@childs2, $pid2);}
    				#If the program is a child
    				elsif ($pid2 == 0)
    				{
    					#Definition of a table to determine if each sequence is already clustered (1) or not (0) to
          				#increase the speed analysis.
          				$i = 0;
          				BOUCLE6:foreach $tmp (@tab_descr)
          				{
            					$seqs_already_clustered[$i] = 0;
            					$i++;
          				}
     
          				#Loop to test each sequence one after one
          				BOUCLE7:for ($i=0;$i<$nb_seq_tot;$i++)
          				{
            					#Test to verify if this sequence is already clustered or not based on the table defined
            					#previously and named @seqs_already_clustered (1, already clustered)
            					if ($seqs_already_clustered[$i]==1) {next BOUCLE7;}
            					#$seqs_already_clustered = 0, need to be clustered
            					else
            					{
              					#Store the descriptive line for further treatment and creation of result files.
              					$descr_line = $tab_descr[$i];
              					#As this sequence is used to define the cluster, we put 1 in the right position of
              					#the @seqs_already_clustered table
              					$seqs_already_clustered[$i] = 1;
     
              					#For each treated sequence compared to the first one chosen by BOUCLE7
              					BOUCLE8:for ($j=1+$i;$j<$nb_seq_tot;$j++)
              					{
                						#Verifying if this sequence is already clustered (1), then go to the next one
                						if ($seqs_already_clustered[$j]==1) {next BOUCLE8;}
                						#If this sequence is not clustered yet (0)
                						else
                						{
    									#Determine using the C core at the top of the program the number of differences 
                  							#between two sequences passed as input
                  							$count_diff = c_compare($tab_align_seq[$i], $tab_align_seq[$j], $h);
                  							#If the two sequences are sufficiently similar, then we clustered them
                  							if ($count_diff <= $h)
                  							{
                    							#We indicate in the table @seqs_already_clustered the clustering to not treat
                   							#anymore this sequence and add its descriptive line in $descr_line
                    							$seqs_already_clustered[$j] = 1;
                    							$descr_line = $descr_line." ".$tab_descr[$j];
                  							}
     
    							}
              					}
              					#At the end of the comparison between one sequence chosen by BOUCLE7 and all others, we create a
              					#new cluster in the table @defined_clusters and we increment the number of clusters ($nb_clusters)
              					$defined_clusters[$nb_clusters] = $descr_line;
              					$nb_clusters++;
            				}
          				}
     
    #===================================================================================================
    #Last step, store results in two new result files. The first giving details of clusters for each
    #step of clustering (max and step size defined by the user). The second file gives only the number
    #of clusters for each step. All results are given with the taking account for the number of
    #dereplicated sequences.
    #===================================================================================================
     
    	    				#Calculation of each step size to determine each clustering
    	    				$j = ceil($h/$mean_length*1000);
    	    				$j = $j/1000;
    	    				#Print only three numbers after the '.'
    	    				$j = sprintf ("%0.3f", $j);
    	    				open (FILE_R_DETAILS, ">>OUT/$1_clust.clust");
    	    				flock(FILE_R_DETAILS,2);
    	    				open (FILE_R, ">>OUT/$1_clust.txt");
    	    				flock(FILE_R,2);
    	   				#Print needed data in result files
    	    				printf (FILE_R_DETAILS "distance cutoff:\t$j\nTotal Clusters:\t$nb_clusters\n");
    	    				printf (FILE_R "$j\t$nb_clusters\n");
    	    				#Loop to print each defined cluster
    	    				for ($i=0;$i<$nb_clusters;$i++)
    	    				{
    	    					#Split the cluster to determine the number of real sequences (not dereplicated for further analysis)
            					@tmp = split(" ",$defined_clusters[$i]);
            					#Needed empty variable to determine the real number of sequences (not dereplicated)
            					$j = 0;
            					#For each sequence in the cluster
            					foreach $char1 (@tmp)
            					{
              					#Split based on the '_' character to found the real number of dereplicated sequences
              					@tmp2 = split("_",$char1);
              					#Count the number of sequences
              					$j = $j+$tmp2[1];
            					}
            					#Print the cluster in the result file
            					printf(FILE_R_DETAILS "$i\t$file\t$j\t$defined_clusters[$i]\n");
          				}
          				printf (FILE_R_DETAILS "\n");
          				flock(FILE_R_DETAILS,8);
          				close (FILE_R_DETAILS);
          				flock(FILE_R,8);
          				close (FILE_R);
          				exit(0);
          			}
          			#If we can't fork (create parent and child processes, die the process)
          			else {die "couldn’t fork: $!\n";}
          		}
          		#foreach (@childs2) {waitpid($_, 0);}
          		exit(0);
          	}
        		else {die "couldn’t fork: $!\n";}
    		#The parent process wait for all child results
    		foreach (@childs) {waitpid($_, 0);}
        }
    }
    closedir DIR;
    Ce que j'aimerai, c'est arriver à faire que le parent s'arrête au bon moment, cad quand tous les petits-fils ont fini de tourner (et qu'il ne tienne pas compte des fils). J'espère être clair.
    Merci d'avance pour vos conseils.

  2. #2
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Points : 5 753
    Points
    5 753
    Par défaut
    Ne faudrait-il pas déplacer
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
           #The parent process wait for all child results
           foreach (@childs) {
             waitpid($_, 0);
           }
    juste avant
    et donc, restituer la ligne 315 ?

  3. #3
    Futur Membre du Club
    Homme Profil pro
    Inscrit en
    Mai 2011
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mai 2011
    Messages : 13
    Points : 8
    Points
    8
    Par défaut
    Bonjour Philou67430,

    D'abord merci pour ta réponse, cependant, je viens de la tester, mais ce n'est pas encore ça.
    La programme fonctionne toujours parfaitement, mais les petits-fils tournent toujours quand le programme PERL me rends la main . Mais, en effet, j'avais fait une belle erreur à ce niveau, ça en fait donc déjà une de moins .
    Je continue à creuser de toute façon pour trouver la solution . Si tu trouves de ton côté, n'hésite pas.

  4. #4
    Futur Membre du Club
    Homme Profil pro
    Inscrit en
    Mai 2011
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mai 2011
    Messages : 13
    Points : 8
    Points
    8
    Par défaut
    Rebonjour à tous !!

    Alors, je viens de vérifier mes dires, qui étaient FAUX !!! La solution de Philou fonctionne parfaitement !!!
    Merci beaucoup Philou

    C'est moi qui ai encore collé au mauvais endroit les lignes

    Bref, ça fonctionne, par contre, je ne comprends pas pourquoi. Quelqu'un pourrait m'expliquer svp ? (je suis autodidacte en programmation, je n'apprends que par les forums et le Web, et je n'ai pas encore trouvé de réponse claire...).
    Philou ?? tu m'expliques ?

  5. #5
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Points : 5 753
    Points
    5 753
    Par défaut
    Pour comprendre les imbrications de ton programme, j'ai supprimé tout le fonctionnel (dont on pourrait au passage, apporter quelques améliorations), pour ne conserver que la structure des forks.
    Ceci donne cela :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
     #Open the directory containing all files needed to be treated
     opendir (DIR, "IN/") || die "can't opendir IN: $!";
     #For each file found in the directory IN/
     BOUCLE:while (defined($file = readdir(DIR)))
       {
         #No treatment for files '.' and '..'
         if ($file =~ /^\.\.?$/) {
           next BOUCLE;
         } else {
           $pid = fork();
           #If the program is the parent! (only one)
           if ($pid) {
             push(@childs, $pid);
           }
           #If the program is a child (max 10)
           elsif ($pid == 0) {
             for($h=$dist_cutoff_step;$h<=$dist_cutoff;$h=$h+$dist_cutoff_step) {
     
               $pid2 = fork();
               #If the program is the parent! (only one)
               if ($pid2) {
                 push(@childs2, $pid2);
               }
               #If the program is a child
               elsif ($pid2 == 0) {
                 exit(0);
               }
               #If we can't fork (create parent and child processes, die the process)
               else {
                 die "couldn’t fork: $!\n";
               }
             }
             #foreach (@childs2) {waitpid($_, 0);}
             exit(0);
           } else {
             die "couldn’t fork: $!\n";
           }
           #The parent process wait for all child results
           foreach (@childs) {
             waitpid($_, 0);
           }
         }
       }
     closedir DIR;
    On s’aperçois alors que la boucle d'attente de fin de enfant est faite dans la boucle de traitement des fichiers, c'est à dire à la fin du traitement du premier fichier. Tu t'es sans doute pris les pieds dans le tapis des imbrications à cause du if ($file =~ /^\.\.?$/) qui évite de traiter les répertoires . et ..

  6. #6
    Futur Membre du Club
    Homme Profil pro
    Inscrit en
    Mai 2011
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mai 2011
    Messages : 13
    Points : 8
    Points
    8
    Par défaut
    D'accord, c'est plus clair pour moi maintenant, merci.

    J'en profites, tu parles d'améliorations du programme ? Si tu as des idées, n'hésites pas , je suis dessus depuis quelques jours, et je n'en vois pas comme ça.
    Merci

  7. #7
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Points : 5 753
    Points
    5 753
    Par défaut
    Une erreur en premier lieu (qui, devrait être détectée à l'exécution si l'usage du pragma warnings était en oeuvre) :
    cette ligne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    my $i, my $j, my $k, my $h, my $x= 0,0,0,0,0;
    n'initialise que $x.
    Pour initialiser toutes les variables, il faut réaliser une affectation de liste :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    my ($i, $j, $k, $h, $x)= (0,0,0,0,0);
    Au passage, donc, intégrer en début de script cette ligne (après use strict par exemple) :
    Je continue l'exploration

  8. #8
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Points : 5 753
    Points
    5 753
    Par défaut
    Dans le même genre d'erreur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    my @tmp, my @tmp2 = (),();
    devient

  9. #9
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Points : 5 753
    Points
    5 753
    Par défaut
    Dans le cadre du traitement des listes, autant que faire se peut, privilégie les opérateurs de liste (foreach, push, ...) par rapport à l'usage des index de tableau.
    Exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $tab_descr[$nb_seq_tot++] = $_;
    remplacé par
    et par la suite, l'usage de $nb_seq_tot peut être remplacé par scalar(@tab_descr).

    Pour le reste, ça me semble pas trop vilain. En fin de compte, c'est assez propre. En tout cas, ça ne ressemble pas à du code de débutant.

  10. #10
    Futur Membre du Club
    Homme Profil pro
    Inscrit en
    Mai 2011
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mai 2011
    Messages : 13
    Points : 8
    Points
    8
    Par défaut
    D'accord, merci pour ces conseils et pour le compliment, je note ça pour les prochains programmes que je ferai et je vais modifier les anciens aussi.
    Encore merci.

  11. #11
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Points : 5 753
    Points
    5 753
    Par défaut
    Cela étant dit, j'ai une question : as-tu d'abord tester la solution séquentielle, sans les fork ? La différence de temps d'exécution est-elle significative ? Cette opération est-elle répétée régulièrement ou bien s'agit-il d'un oneshot ?

  12. #12
    Futur Membre du Club
    Homme Profil pro
    Inscrit en
    Mai 2011
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mai 2011
    Messages : 13
    Points : 8
    Points
    8
    Par défaut
    Salut Philou67430,
    Je ne vois pas ce que tu entends par "solution séquentielle". Mais ce programme est amené à traiter un grand nombre de fichiers (en gros, 300), et ce avec plusieurs traitements (7 à 8, ce qui explique la création des différents petits-fils). Je n'avais pas d'autre solution pour traiter cela rapidement, les fichiers étant volumineux.

    J'ai fait un test sur un fichier avec un seul coeur (le premier programme que j'avais fait le faisait au fur et à mesure, sur le même coeur), j'avais mis en gros 9h00. Avec les fork(), sur le même fichier, je ne mets pas 01h00 pour le faire, avec les mêmes résultats.

    De plus, ce programme sera amené a être utilisé fréquemment, donc autant qu'il soit efficace et rapide .
    J'espère avoir répondu à ta question.

  13. #13
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Points : 5 753
    Points
    5 753
    Par défaut
    Ta réponse me convient parfaitement.

    Une autre option que les fork aurait été d'utiliser les threads, qui minimise l'espace mémoire utilisé pour le contexte du programme (qui est commun, alors qu'il est copié avec fork).

  14. #14
    Futur Membre du Club
    Homme Profil pro
    Inscrit en
    Mai 2011
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mai 2011
    Messages : 13
    Points : 8
    Points
    8
    Par défaut
    Oui, c'est une option que j'avais regardé. Mais n'ayant ni les notions de l'une ou l'autre option, j'ai pris celle qui me paraissait la plus simple à mettre en place pour moi. Or, j'ai trouvé plus de choses (tutoriaux, exemples) sur les fork que sur les Threads dans PERL.
    Il faudra que je creuse ça pour les autres programmes à transférer sur le serveur.
    Encore merci pour ton aide et tes conseils

  15. #15
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Points : 5 753
    Points
    5 753
    Par défaut
    Un petit benchmark réalisé sur ta fonction c_compare m'a permis d'identifier une amélioration qui apporte un gain d'environ 45% de temps d'exécution si le taux de différences des textes est inférieur à 1/1000 à 1/10000.

    La modification proposée :
    au lieu de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
      for( i = 0; i < len; i++ ) {
        if( a[i] != b[i] ) diff++;
        if(diff > max) break;
      }
    faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
      for( i = 0; i < len; i++ ) {
        if( a[i] != b[i] ) {
          if (++diff > max) break;
        }
      }
    Ainsi, on ne test diff que s'il change, et pas à chaque itération.

  16. #16
    Futur Membre du Club
    Homme Profil pro
    Inscrit en
    Mai 2011
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mai 2011
    Messages : 13
    Points : 8
    Points
    8
    Par défaut
    Salut Philou,
    je viens de tomber sur ton message, et j'ai fait les modifications, en effet, ça accélère fortement le système et me fais encore gagner du temps
    Encore merci.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 0
    Dernier message: 30/10/2012, 21h34
  2. fork : créer UN fifo entre le père et SES fils
    Par ankou29666 dans le forum Langage
    Réponses: 3
    Dernier message: 09/09/2007, 17h33
  3. Problème d’héritage. (si deux fils ont le même père !)
    Par jarod_ab dans le forum PostgreSQL
    Réponses: 4
    Dernier message: 04/03/2006, 13h42
  4. Réponses: 9
    Dernier message: 23/02/2004, 19h14

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo