#include <stdio.h>
#include <sys/types.h>
#include "pvm3.h"
#define GRPNAME "tokenring"
void main
(int argc,
char ** argv
) {
int NPROC
= 8;
/* default nb of proc */
int mytid;
/* my task id */
int *tids;
/* array of task id */
int me;
/* my process number */
int i;
int N;
char nom
[255];
char nomsortie
[255];
//vérification du nombre d'argument
if (argc
!= 4){
printf ("Usage: %s <matrix size><matrix name><matrix name out>\n", argv
[0]);
exit
(-1);
}
// taille de la ligne de la matrice
N
= atoi
( argv
[1] );
//localité de la matrice
strcpy
(nom, argv
[2]);
strcpy
(nomsortie, argv
[3]);
/* enroll in pvm */
mytid
= pvm_mytid
();
/* determine the size of my sibling list */
NPROC
= pvm_siblings
(&tids
);
/* WARNING: tids are in order of spawning, which is different from
the task index JOINING the group */
me
= pvm_joingroup
( GRPNAME
);
/* me: task index in the group */
pvm_barrier
( GRPNAME, NPROC
);
pvm_freezegroup
( GRPNAME, NPROC
);
for ( i
= 0; i < NPROC; i
++) tids
[i
] = pvm_gettid
( GRPNAME, i
);
/*--------------------------------------------------------------------------*/
/* all the tasks are equivalent at that point */
dowork
( me, tids, NPROC, nom, N, nomsortie
);
pvm_lvgroup
( GRPNAME
);
pvm_exit
();
}
void matrix_load
( char nom
[],
double *tab,
int N,
int nproc,
int tids
[]) {
FILE
*f;
int i,j;
double buf
[N
];
double toto;
int num_envoi;
int ligne_courant
=0;
if ((f
= fopen
(nom,
"r")) == NULL) { perror
("matrix_load : fopen ");
}
for (i
=0; i<N; i
++) {
if(i
%nproc
== 0){
for (j
=0; j<N; j
++) {
fscanf
(f,
"%lf ",
&toto
);
*(tab
+ligne_courant
*N
+j
) = toto;
//printf ("%lf ",*(tab+ligne_courant*N+j));
}
ligne_courant
++;
}else{
num_envoi
= i
%nproc;
for (j
=0; j<N; j
++) {
fscanf
(f,
"%lf ",
&buf
[j
] );
}
pvm_initsend
(PvmDataDefault
);
pvm_pkdouble
(buf,N,
1);
pvm_send
(tids
[num_envoi
],
0);
}
}
fclose
(f
);
}
void matrix_save
( char nom
[],
double *tab,
int N ,
int nproc,
int tids
[]) {
FILE
*f;
int i,j;
double buf;
if ((f
= fopen
(nom,
"w")) == NULL) { perror
("matrix_save : fopen ");
}
for (i
=0; i<N; i
++) {
if(i
%nproc
== 0){
for (j
=0; j<N; j
++){
fprintf
(f,
"%8.2f",
*(tab
+ i
*(N
/nproc
)+j
));
}
fprintf
(f,
"\n");
}else {
pvm_recv
(tids
[i
%nproc
],
-1);
for (j
=0; j<N; j
++) {
pvm_upkdouble
(&buf,
1,
1);
fprintf
(f,
"%8.2f", buf
);
}
fprintf
(f,
"\n");
}
}
fprintf
(f,
"\n");
fclose
(f
);
}
void matrix_display
( double *tab,
int N
) {
int i,j;
for (i
=0; i<N; i
++) {
for (j
=0; j<N; j
++) {
printf ("%8.2f ",
*(tab
+i
*N
+j
) );
}
printf ("\n");
}
}
void gauss
( double * tab,
int N,
int nproc,
int me,
int tids
[] ) {
int i,j,k,l;
double pivot;
double buffer
[N
];
double buf;
int decalage
= 0;
for(k
=0;k<
(N
-1);k
++)
{
//le processeur a le pivot en cour
if(k
%nproc
==me
)
{
for(j
=k; j < N ;j
++){
buffer
[j
] = *(tab
+ ((k
/nproc
)*N
) + j
);
}
//envoi de la ligne
pvm_initsend
(PvmDataDefault
);
pvm_pkdouble
(&buffer
[k
],N
-k,
1);
for(l
=0; l<nproc;l
++){
if(l
!= me
){
pvm_send
(tids
[l
],
0);
}
}
}
else
{
pvm_recv
(tids
[k
%nproc
],
-1);
pvm_upkdouble
(&buffer
[k
],N
-k,
1);
}
if(me>
(k
%nproc
)){
decalage
=(k
/nproc
);
}else{
decalage
=(k
/nproc
) + 1;
}
for(i
=decalage;i<
(N
/nproc
);i
++)
{
pivot
= (*(tab
+ i
* N
+ k
)/buffer
[k
]);
for(j
=k;j<N;j
++)
{
*(tab
+ i
* N
+j
) = *(tab
+ i
* N
+ j
) - pivot
*buffer
[j
];
}
}
}
}
/* Simple example passes a token around a ring */
dowork
( int me,
int tids
[],
int nproc,
char nom
[255],
int N,
char nomsortie
[255]) {
FILE
*f;
struct timeval tv1, tv2;
/* for timing */
int duree;
double *tab, pivot;
int i,j,k
= 0,l;
double buf;
double buffer
[N
];
int num_envoi;
int decalage
= 0;
int ligne_courant
= 0;
double coeff;
if ( (tab
= malloc
(N
*(N
/(nproc
))*sizeof(double))) == NULL ) {
printf ("Cant malloc %d bytes\n", N
*N
*sizeof(double));
exit
(-1);
}
if(me
== 0)
{
gettimeofday
( &tv1,
(struct timezone
*)0 );
matrix_load
( nom , tab, N, nproc, tids
);
gettimeofday
( &tv2,
(struct timezone
*)0 );
duree
= (tv2.
tv_sec - tv1.
tv_sec) * 1000000 + tv2.
tv_usec - tv1.
tv_usec;
printf ("me : %d, loading time: %10.8f sec.\n", me, duree
/1000000.0 );
}else{
for(i
=0; i<
(N
/nproc
);i
++){
pvm_recv
(-1,
-1);
for (j
=0; j<N; j
++) {
pvm_upkdouble
(&buf,
1,
1);
*(tab
+ i
*N
+ j
) = buf;
}
}
}
pvm_barrier
( GRPNAME, nproc
);
if (me
== 0){
gettimeofday
( &tv1,
(struct timezone
*)0 );
}
gauss
(tab,N,nproc,me,tids
);
if (me
==0){
gettimeofday
( &tv2,
(struct timezone
*)0 );
duree
= (tv2.
tv_sec - tv1.
tv_sec) * 1000000 + tv2.
tv_usec - tv1.
tv_usec;
printf ("me : %d, calcul time: %10.8f sec.\n", me, duree
/1000000.0 );
}
pvm_barrier
( GRPNAME, nproc
);
ligne_courant
= 0;
if(me
== 0)
{
gettimeofday
( &tv1,
(struct timezone
*)0 );
matrix_save
(nomsortie, tab, N, nproc, tids
);
gettimeofday
( &tv2,
(struct timezone
*)0 );
duree
= (tv2.
tv_sec - tv1.
tv_sec) * 1000000 + tv2.
tv_usec - tv1.
tv_usec;
printf ("me : %d, save time: %10.8f sec.\n", me, duree
/1000000.0 );
}else{
//num_envoi = i%nproc;
for (i
=0; i < N
/(nproc
); i
++) {
for (j
=0; j < N; j
++) {
buffer
[j
] = *(tab
+ N
*i
+ j
);
}
pvm_initsend
(PvmDataDefault
);
pvm_pkdouble
(buffer,N,
1);
pvm_send
(tids
[0],
0);
ligne_courant
++;
}
}
free
(tab
);
}