[C] Multiplication matrice multiprocessus avec fork()

Multiplication matrice multiprocessus avec fork() [C] - C - Programmation

Marsh Posté le 28-03-2006 à 22:06:03    

Bonsoir tout le monde.
 
J'ai un petit problème en C. Je dois créer un programme qui effectue la multiplication de deux matrices d'entiers, en utilisant plusieurs processus.
Voici le code source :
 
Dans le fichier Matrice.h :
 
typedef struct Matrice{
int nbLignes, nbColonnes;
int **matrice;
}Matrice;
 
**********************
 
Dans le fichier Matrice.c :
 
Matrice* Matrice_creation(int nbL, int nbC){
 
int i;
 
Matrice* tmp=(Matrice*)malloc(sizeof(Matrice));
tmp->nbLignes=nbL;
tmp->nbColonnes=nbC;
tmp->matrice=(int**)malloc(sizeof(int*)*nbL);
for(i=0;i<nbL;i++){
tmp->matrice[i]=(int*)malloc(sizeof(int)*nbC);
}
return tmp;
 
 
}
 
void calcul_ligne(Matrice* M1, Matrice* M2, Matrice* result, int i){
int x,y;
for(x=0;x<M2->nbLignes;x++){
for(y=0;y<M1->nbColonnes;y++){
result->matrice[i][y]+=M1->matrice[i][y]*M2->matrice[x][i];
}
}
}
 
 
*************************
 
Dans le fichier main.c :
 
(Je passe sur les fonctions de remplissage des deux matrices, qui fonctionnent bien)
 
int nbC1; //nombre de colonnes de la matrice 1
int nbL1; //nombre de lignes de la matrice 1
int nbC2;
int nbL2;
int i, j;
int diag;
 
Matrice *M1=Matrice_creation(nbL1,nbC1);
Matrice *M2=Matrice_creation(nbL1,nbC1);
Matrice *M3=Matrice_creation(nbL1,nbC1);
 
/* Je crée autant de processus que de lignes dans
la matrice résultat (M3). Chaque processus calcule
une ligne de la matrice */
 
for(i=0; i<nbL1; i++){
diag=fork();
if(diag<0)
perror("fork" );
else
if(diag==0){
calcul_ligne(M1,M2,M3,i);
exit(0);
}
}
 
/* J'attend que tous les fils terminent leurs calculs */
 
for(i=0;i<nbL1;i++){
diag=wait(0);
if(diag<0)
perror("wait" );
}
 
 
*********************************************************
 
Bon alors tout ceci se compile très bien, le problème c'est que la matrice résultat n'est constituée que de zéros au final. C'est comme si les fils faisaient bien leur travail, mais que cela n'avait aucune incidence sur la matrice M3.
Si quelqu'un voit de quoi cela peut provenir...
 
Merci d'avance ^^.

Reply

Marsh Posté le 28-03-2006 à 22:06:03   

Reply

Marsh Posté le 28-03-2006 à 22:25:08    

faudrait que la matrice M3 soit partagée entre les processus, sinon les fils calculent sur une copie de l original.


Message édité par nargy le 28-03-2006 à 22:25:25
Reply

Marsh Posté le 28-03-2006 à 22:29:45    

Ok, et tu pourrais m'expliquer comment faire ça, je pense avoir saisi ce que tu voulais dire, mais alors comment faire ça... Merci.

Reply

Marsh Posté le 28-03-2006 à 22:32:16    

Voir les fonctions posix:
shmat()
shmdt()
shmget()

Reply

Marsh Posté le 28-03-2006 à 22:33:33    

tu as aussi:
shm_open()
shm_close()
et mmap()

Reply

Marsh Posté le 28-03-2006 à 22:36:30    

> en utilisant plusieurs processus
tu peut aussi utiliser des threads, la mémoire y est automatiquement partagée.
voir pthread_create(), pthread_exit(), pthread_join(), et autres pthread_*

Reply

Marsh Posté le 28-03-2006 à 22:39:58    

Merci pour toutes tes réponses, c'est vraiment sympa.
En fait on nous a demandé de faire ça sous unix, uniquement avec les fonctions fork() et wait(), donc c'est pour ça, je me retrouve coincé. Pourtant je passe bien l'adresse de la matrice 3 aux fils, je vois vraiment pas où ça bloque...


Message édité par Fred051 le 28-03-2006 à 22:40:18
Reply

Marsh Posté le 28-03-2006 à 22:47:48    

Quand tu fork un process, il crée une copie de sa mémoire pour ses fils, et la copie n est jamais retrouvée par le père sauf si tu as explicitement partagé un espace mémoire avec une des fonction shm* donnée plus haut.
 
Sinon sans shm (shared memory) tu peut utiliser un pipe ou un fichier sur disque (les fichiers sont partagés automatiquement via fork mais pas la mémoire).

Reply

Marsh Posté le 28-03-2006 à 22:56:32    

Oué, je crois avoir saisi là ! En fait, il me suffirai d'ajouter dans la fonction calcul ligne, la possibilité pour le fils d'écrire dans un fichier texte, chose que l'on nous demande de toute façon, récupérer la matrice résultat en fichier texte. Je pensais que c'était au processus père de s'occuper de cela en dernier. Bon par contre, il faut que je trouve un moyen pour que les fils écrivent dans l'ordre dans le fichier texte...
 
[edit] En fait M3 au départ je n'ai rien dedans, donc je ne peux pas la "partager" entre les fils.


Message édité par Fred051 le 28-03-2006 à 23:00:32
Reply

Marsh Posté le 28-03-2006 à 23:03:27    

tu as le droit d utiliser un pipe?
c est plus propre.
 
> faut que je trouve un moyen pour que les fils écrivent dans l'ordre dans le fichier texte...
 
à la rigueur tu peut utiliser un signal du fils vers le père pour indiquer que le fils a terminé, puis quand tous on terminés, le père envoie les signaux dans l ordre vers les fils qui enregistrent et se terminent. Le père attends qu un fils se termine avec wait pour demander à un autre d enregistrer.
edit: tu va quand même galérer, tu aura besoin de shm...


Message édité par nargy le 28-03-2006 à 23:06:04
Reply

Marsh Posté le 28-03-2006 à 23:03:27   

Reply

Marsh Posté le 28-03-2006 à 23:04:11    

> En fait M3 au départ je n'ai rien dedans, donc je ne peux pas la "partager" entre les fils.
si tu peut! tu alloue de la mémoire avec shm* au lieu de malloc/free

Reply

Marsh Posté le 28-03-2006 à 23:05:36    

Non malheureusement, je n'ai pas le droit d'utiliser ni les pipes, ni les signaux... sûrement pour corser le tout...
 
Pour shm, en fait on ne l'a pas encore vu (c'est même la première fois que j'en entend parler).


Message édité par Fred051 le 28-03-2006 à 23:07:03
Reply

Marsh Posté le 28-03-2006 à 23:07:28    

ben, avec des fichiers......... tu crée un fichier temporaire par fils, et quand ils ont tous fini, le père lit les fichiers et les concatènent dans un fichier de sortie.

Reply

Marsh Posté le 28-03-2006 à 23:08:42    

comme les fichiers sont partagés, le père peut se charger de les ouvrir/fermer.

Reply

Marsh Posté le 28-03-2006 à 23:12:25    

Et en les concaténant, ça reviendrait pas au même problème que tout à l'heure, c'est à dire qu'il n'y a pas un risque qu'un fils finisse avant un autre et que donc le père concatène dans le mauvais ordre ?
 
Je pense aussi à quelquechose, le prof a dit que ce programme devait fonctionner avec des matrices très grandes, du genre 10000 ligne, ce qui me ferait donc 10000 fichiers temporaires.
 
Je vais regarder pour shm sinon, selon toi ça permettrait de résoudre le problème des fils qui écrivent dans une copie, avec shm ils écriront bien tous dans la "vraie" matrice M3 ?
Encore merci pour toutes tes réponses. ^^

Reply

Marsh Posté le 28-03-2006 à 23:15:18    

c est un cours de préparation pour shm ou un exercice sur fork?

Reply

Marsh Posté le 28-03-2006 à 23:16:24    

- avec shm ils écriront bien tous dans la "vraie" matrice M3 ?
oui si elle est partagée.
 
tu est sûr aussi de ne pas avoir à utiliser un pipe? un pipe est en mémoire.

Reply

Marsh Posté le 28-03-2006 à 23:16:52    

oui utilise la shm, c'est plus efficace
 
pourquoi tu créés un processus pour chaque ligne, quel est l'interet ?

Reply

Marsh Posté le 28-03-2006 à 23:19:09    

En fait c'est un exercice sur les processus, avec fork() vu qu'on doit le faire tourner sur unix uniquement. Les pipes et signaux ont été vus après, et ne sont pas autorisés pour cet exercice. Le prof n'a jamais mentionné shm... tout va  bien quoi  :pt1cable:.

Reply

Marsh Posté le 28-03-2006 à 23:21:15    

sketler > ba en fait on nous a demandé de répartir les calculs sur plusieurs processus, donc je pense qu'on peut faire cette répartition. L'interêt à mon avis ce sera juste pour comparer le gain de temps qu'on aura par rapport au cas où un seul processus calcule tout.

Reply

Marsh Posté le 28-03-2006 à 23:21:42    

attends, alors il doit y avoir une possibilité avec deux fichiers seulement..

Reply

Marsh Posté le 28-03-2006 à 23:24:11    

Fred051 a écrit :

sketler > ba en fait on nous a demandé de répartir les calculs sur plusieurs processus, donc je pense qu'on peut faire cette répartition. L'interêt à mon avis ce sera juste pour comparer le gain de temps qu'on aura par rapport au cas où un seul processus calcule tout.


 
la parallelisation n'a d'interet que sur une architecture parallele, et le commun des cluster c'est 2, 4 voir 8 processeurs, des monstres avec 10000 processeurs t'en veras pas beaucoup (meme au cea il n'y en a "que" 2500)


Message édité par skelter le 28-03-2006 à 23:24:29
Reply

Marsh Posté le 28-03-2006 à 23:24:13    

J'ai pas été assez précis dans le sujet... En fait, les deux matrices M1 et M2 sont chargées à partir de 2 fichiers texte. On demande d'abord à l'utilisateur les valeurs, puis on écrit dans 2 fichiers avec fwrite(), et enfin on les charge avec fread() (opération un peu inutile, mais c'est juste pour nous faire utiliser ces deux fonctions). A la fin des calculs, la matrice M3 doit aussi être écrite dans un  fichier.


Message édité par Fred051 le 28-03-2006 à 23:25:44
Reply

Marsh Posté le 28-03-2006 à 23:28:47    

Je m explique:
 
- tous les fils font leur sauce de matrices,
- quand ils ont fini, ils écrivent dans un fichier temporaire ``fini n°fils``
- le père lit ce fichier en même temps, quand il lit ``fini n°fils``, il vérifie si tous les fils précédents ont fini, si oui il envoye ``ok n°fils``
- quand le fils a écrit ``fini n°fils``, il attend ``ok n°fils`` pour écrire dans le fichier final, puis se termine
- tous les fils enregistrent dans le même fichier
- le père utilise wait() pour vérifier qu un fils a terminé son enregistrement.
 
(technique utilisé dans des vieux chats)
 
tu doit ouvrir le fichier temporaire dans le fils sinon la tête de lecture est partagée.

Reply

Marsh Posté le 28-03-2006 à 23:29:36    

> la parallelisation n'a d'interet que sur une architecture parallele
ouais, skelter, mais là c est un exo de base sur le fork...

Reply

Marsh Posté le 28-03-2006 à 23:31:54    

nargy> ca serait pas plus simple (seulement je ne sais pas si c'est faisable) que chaque fils à la fin de son traitement attende que le précédent ai terminé, et écrive ensuite sa ligne dans le fichier de sortie

Reply

Marsh Posté le 28-03-2006 à 23:33:38    

nargy a écrit :

> la parallelisation n'a d'interet que sur une architecture parallele
ouais, skelter, mais là c est un exo de base sur le fork...


 
je ne sais pas qu'elles sont les consignes exactes mais mois j'aurais simplement coupée la matrice en 2 ou en 4, c'est déjà pas mal

Reply

Marsh Posté le 28-03-2006 à 23:35:38    

ha ouais, pas con :)
ils comptent les lignes écrites et attendent leur tour.

Reply

Marsh Posté le 28-03-2006 à 23:36:35    

son prof veut qu il coupe la matrice en lignes, même s il y en a 10,000....! il a jamais vérifié si c était faisable le prof ;)

Reply

Marsh Posté le 28-03-2006 à 23:39:39    

les threads c est plus simple, tu va les adorer après cet exercice! :pt1cable:

Reply

Marsh Posté le 28-03-2006 à 23:40:36    

Ok, ca me parait pas mal ça, chaque fils n'écrira que si le nombre de lignes dans le fichier de sortie (qui sera donc unique), est égal à i-1, i correspondant au ième fils créé. Je vais tester. Merci.
 
edit : Oué j'espère que les threads c'est moins "prise de tête". :(


Message édité par Fred051 le 28-03-2006 à 23:41:55
Reply

Marsh Posté le 29-03-2006 à 00:09:57    

Pourquoi ne pas utiliser une lib comme MPI spécialement dedié pour ce genre de problemes.


---------------
Scheme is a programmable programming language ! I heard it through the grapevine !
Reply

Marsh Posté le 29-03-2006 à 00:11:54    

c est un exo sur fork() et le fichiers, sans shm, sans threads, sans pipes, sans signaux...

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed