Précédent   Forum des professionnels en informatique > PHP > Langage
Langage Forum sur le langage PHP, la POO, les conventions, la sécurité, etc. Avant de poster : FAQ Langage, toutes les FAQ PHP, cours langage et sources PHP
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 27/05/2011, 09h57   #1
Invité de passage
 
Inscription : janvier 2006
Messages : 5
Détails du profil
Informations forums :
Inscription : janvier 2006
Messages : 5
Points : 0
Points : 0
Par défaut Utilisation de proc_open et pcntl : conflit ?

Bonjour,

Je suis actuellement en train de paralléliser des calculs écris en PHP.

Il y a 12 familles de calcul à paralléliser, puis, dans chaque famille, on veut lancer 1 à n calculs en //.

La première étape a consisté à tester les 2 parallélisation séparément:

Le script "Père" lance 12 scripts "fils" (les 12 familles de calcul) en // avec proc_open. Celà fonctionne correctement.

Un script fils lance des calculs en parallèle avec la fonction pcntl_fork. Celà fonctionne correctement.

Cependant, si l'on fait tout fonctionner en même temps, il y a trop de calculs lancés. Chaque famille de calcul est lancée plusieurs fois. Je n'arrive pas à comprendre ce qui se passe.

Voici un extrait du script "Père" qui va lancer les 12 familles de calcul:
Code :
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
 
// Boucle sur les id_group_table des familles à traiter
foreach ( $listGroupTable as $id_group_table => $tableau_info_famille )
{
    $descriptorspec = array();
    $pipes          = array();
    $env            = array( "env_id_group_table" => $id_group_table );
    displayInDemon( "Launch compute raw process for group table $id_group_table" );
    $procFile = dirname( $PHP_SELF )."/le_fils.php";
    $h = proc_open("php $procFile", $descriptorspec, $pipes, NULL, $env  );
 
    // Test si le process s'est bien lancé
    if( $h !== false )
    {
        $listHandle[]= $h;
    }
    else
    {
        displayInDemon( 'Error lors du lancement du group table '.$id_group_table, 'alert' );
    }
}
 
displayInDemon( 'All processes started, now check end execution every milliseconds...' );
$listPidExecuted = array();
$nbProcesses     = count( $listHandle );
while( count( $listPidExecuted ) !== $nbProcesses )
{
    foreach( $listHandle as $oneHandle )
    {
        $a = proc_get_status( $oneHandle ); // Lecture de l'état du process
        // 
        // Si le process vient de se terminer
        if( $a['running'] == false && !in_array( $a['pid'], $listPidExecuted ) )
        {
            $listPidExecuted[] = intval( $a['pid'] );
            displayInDemon( "{$a['pid']} est terminee" );
        }
    }
    usleep( 1000 ); // On attend 1ms avant le prochain test
}
displayInDemon( 'Process execution ended' );
Et voici un extrait de la classe appelée dans "le_fils.php" pour la parallélisation des calculs

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 
// Dans la boucle des calculs:
                        if( !$pcntl_started )
                        {
                            declare(ticks=1);
                            $pcntl_started = true;
                            $this->parentPID = getmypid();
                            $this->currentJobs = $this->signalQueue = array();
                            pcntl_signal(SIGCHLD, array($this,"childSignalHandler") );
                        }
 
                        // On attend qu'un slot se libère pour lancer un processus
                        while( count($this->currentJobs) >= $maxProcesses )
                            usleep(100);
 
                        // Lancement d'un calcul
                        $jobID = current($this->freeJobs);
                        displayInDemon("Lancement d'un calcul dans le slot $jobID");
                        $this->launchProcess($currentInstructions['queries'], $jobID, $index);
 
// [...]
// Après la boucle des calculs:
                // On attend que les requêtes en cours soient terminées
                while(count($this->currentJobs) > 0) usleep(100);
Méthode launchProcess:
Code :
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
 
        public function launchProcess(array $queries, $jobID, $index)
        {
            // Création d'un processus fils
            $pid = pcntl_fork();
            if($pid == -1)
            {
                // Impossible de créer le processus
                displayInDemon("Unable to fork compute calculation. Calculation failed.",'alert');
                return false;
            }
            else if ( $pid )
            {
                // Parent process
                // Sometimes you can receive a signal to the childSignalHandler function before this code executes if
                // the child script executes quickly enough!
                $this->currentJobs[$pid] = $jobID;
                $this->freeJobs = array_diff($this->freeJobs, $this->currentJobs);
                // In the event that a signal for this pid was caught before we get here, it will be in our signalQueue array
                // So let's go ahead and process it now as if we'd just received the signal
                if(isset($this->signalQueue[$pid]))
                {
                    $this->childSignalHandler(SIGCHLD, $pid, $this->signalQueue[$pid]);
                    unset($this->signalQueue[$pid]);
                }
            }
            else
            {
                // Lacement des calculs
                $db = new DataBaseConnection();
                $queryResults = $this->executeComputeQuery($queries, $db);
                $this->setQueryResults($index, $queryResults);
                $db->close();
                exit(0);
            }
        }
La méthode utilisée avec pcntl est tirée d'un exemple dans la page de doc:
http://www.php.net/manual/fr/functio...fork.php#98711

Mer de votre aide.

PHP 5.2.13
RedHat Linux EL 5.5 64bits
obibann est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 19h57.


 
 
 
 
Partenaires

Hébergement Web