[C] Utiliser fork() correctement

Résolu/Fermé
Sauvegarde2 Messages postés 205 Date d'inscription dimanche 14 décembre 2008 Statut Membre Dernière intervention 11 janvier 2015 - 6 août 2012 à 19:25
Sauvegarde2 Messages postés 205 Date d'inscription dimanche 14 décembre 2008 Statut Membre Dernière intervention 11 janvier 2015 - 8 août 2012 à 17:15
Bonjour ou bonsoir,

Je travaille sur un programme de traitement d'image qui s'exécute en 8 secondes. Pour améliorer ce temps je souhaite introduire des forks, voici ce que ça donne :

for(i = 0 ; i < NB_IZOOM ; i++)
    {
        if(i > 0)
        {
            source[i] = resize(source[0], subname[i], pzoom[i]);
        }
        wait(0);
        pid = fork();
        switch(pid)
        {
            case -1: perror("fork()"), exit(-1);
            case 0 : crop(source[i], subname[i], subdir[i], geometry); exit(0);
            default: break;
        }
    }


J'ai respecté la structure que j'ai vu en faisant des recherches sur internet, pourtant mon programme est anormalement lent (en fait il se bloque sur la deuxième miniature).

Pouvez-vous m'aider et me dire ce qui ne va pas s'il vous plait ?

Context :

source[] étant un tableau de NB_IZOOM images,
pzoom[] la liste des pourcentage de réduction (zoom),
subname[] et subdir[] des chemins de fichiers,
geometry vaut ici "256x256", c'est la taille des tuiles que je désire.

resize() renvoie une image miniaturisée de la source à hauteur de pzoom,
crop() découpe la source en tuiles et les enregistre sur le disque.

Le wait(0) est ici pour empêcher le programme de découper l'image avant qu'elle ne soit créée. Cela limite aussi le nombre de fils à un seul.

2 réponses

Char Snipeur Messages postés 9696 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 1 297
7 août 2012 à 13:53
Déjà on sais maintenant que c'est le wait qui pose problème.
As tu lus le man de wait ? Je comprends qu'un enfant qui se termine correctement doit avoir un exit(2) ou exit(3). Peut être que comme tu retournes un exit(0), le wait détecte un problème ?
Tu peux aussi récupérer les retours de wait ainsi que le status (paramètre de wait() ) pour voir si quelques chose se passe mal.

Je pense que ton algorithme est mal pensé, faire un fork prend du temps car il faut dupliquer le processus, et là tu fait un fork à chaque itération que tu détruit ensuite, donc tu fais NB_IZOOM fork. Selon la valeur de NB_ZOOM, ça peut être très pénalisant.
Pour moi, la bonne façon de faire et ton script s'y prete bien, c'est de faire le fork avant le for et de couper ta boucle en deux.
pid=fork();
if(pid==0)
{
     for (i=0;i<NB_IZOOM/2;++i)
     {
            if(i!=0)source[i] = resize(source[0], subname[i], pzoom[i]);
            crop(source[i], subname[i], subdir[i], geometry); 
      }
      exit(2);
}else
{
     for (i=NB_IZOOM/2;i<NB_IZOOM;++i)
     {
            source[i] = resize(source[0], subname[i], pzoom[i]);
            crop(source[i], subname[i], subdir[i], geometry); 
      }
}
wait(0);// attend la fin de l'enfant pour être certain de ne pas avoir de problème de synchronisation dans la suite.
...
1
Sauvegarde2 Messages postés 205 Date d'inscription dimanche 14 décembre 2008 Statut Membre Dernière intervention 11 janvier 2015 261
7 août 2012 à 16:56
Je n'ai pas vu mention de exit(2) de le man de wait. En tout cas l'idée est bonne mais je n'ai toujours pas de meilleurs temps qu'en séquentiel (loin de là). Je profite peut-être mieux des effets de cache en séquentiel..? Bon en tout cas merci pour ta réponse.
0
Char Snipeur Messages postés 9696 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 1 297
8 août 2012 à 07:52
Donne un ordre de grandeur de NB_IZOOM, qu'on sache un peu mieux ce qui se passe.
Ce que je vois : fork prend du temps à être fait, donc il faut vraiment que la boucle soit longue en calcul. 8s ça me parait exploitable, si tu passe bien la majorité du temps dans la boucle que tu donnes. Je pense que tu devrais descendre à 5s.
Je vois une autre cause possible au ralentissement : l'écriture sur disque. Il faut d'abord vérifier que ça ne soit pas ça qui prenne le plus de temps. Du coup en parallèle, peut être que les deux processus se marchent un peu sur les pieds pour écrire.
=> profilage ou test du programme en supprimant la fonction d'écriture.
0
Sauvegarde2 Messages postés 205 Date d'inscription dimanche 14 décembre 2008 Statut Membre Dernière intervention 11 janvier 2015 261
8 août 2012 à 13:35
NB_IZOOM vaut généralement 5 (100%, 80%, 60%, 40%, 20%) et l'écriture sur disque, ainsi que le découpage, est très rapide. Ce qui prend le plus de temps c'est le redimensionnement des images.
0
Char Snipeur Messages postés 9696 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 1 297
8 août 2012 à 14:47
je ne sais pas ce que tu fais dans le redimensionnement, mais si ça fait appel à des fonctions système (new, open etc.) il est possible que les fonctions se marchent sur les pieds.
Ou alors c'est le recopiage des données qui est long à cause de comme tu dit l'histoire du cache, en parallèle tu es obligé de faire pleins d'aller retour dans la RAM ce qui doit prendre du temps ? Après, il y a des méthodes d'optimisation pour aller plus vite, sinon il va falloir se contenter des 8s.
0
Sauvegarde2 Messages postés 205 Date d'inscription dimanche 14 décembre 2008 Statut Membre Dernière intervention 11 janvier 2015 261
8 août 2012 à 17:15
Je suis en train de voir ce que ça donne avec des threads. Bon j'ai des soucis intermédiaire comme par exemple stocker mon subname[NB_IZOOM][BUF_SIZE] dans une structure routine_arg (puisqu'on ne peut passer qu'un seul argument à un thread, je met tout dans une struct), mais ça pourrait être plus intéressant. Il me semble que les accès concurrents en lecture ne posent pas de problèmes, si ?
0
Char Snipeur Messages postés 9696 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 1 297
7 août 2012 à 08:43
essai sans le wait(0). Le fork prend du temps tout de même !
0
Sauvegarde2 Messages postés 205 Date d'inscription dimanche 14 décembre 2008 Statut Membre Dernière intervention 11 janvier 2015 261
7 août 2012 à 13:18
Effectivement ça marche. J'ai un temps de 48 secondes mais ça marche. Mais je comprend pas pourquoi ça fonctionne mieux sans le wait(0)...
0