// version 0.1 modifed by ian a. mason // may 21 @ u.n.e // // replaced "mmult" by "mm.0.1" in pvm_spawn. // added some time info for comparison // added VERBOSE mode #include #include #include #include #include "block.h" /* Maximum number of children this program will spawn */ #define MAXNTIDS 100 #define MAXROW 10 /* Message tags */ #define ATAG 2 #define BTAG 3 #define DIMTAG 5 #define VERBOSE 1 int main(int argc, char* argv[]){ int ntask = 2; int info; int mytid, mygid; int child[MAXNTIDS-1]; int i, m, blksize; int myrow[MAXROW]; int *a, *b, *c, *atmp; int row, col, up, down; int crow, ccol; //real time for the time being int start_time = time(NULL); mytid = pvm_mytid(); pvm_setopt(PvmRoute, PvmRouteDirect); if (mytid < 0){ pvm_perror(argv[0]); return -1; } mygid = pvm_joingroup("mmult"); if (mygid < 0){ pvm_perror(argv[0]); pvm_exit(); return -1; } if (mygid == 0) { if (argc == 3) { m = atoi(argv[1]); blksize = atoi(argv[2]); } if (argc < 3) { fprintf(stderr, "usage: mmult m blk\n"); pvm_lvgroup("mmult"); pvm_exit(); return -1; } ntask = m*m; if ((ntask < 1) || (ntask >= MAXNTIDS)) { fprintf(stderr, "ntask = %d not valid.\n", ntask); pvm_lvgroup("mmult"); pvm_exit(); return -1; } if (ntask == 1) goto barrier; info = pvm_spawn("mm.0.1", (char**)0, PvmTaskDefault, (char*)0, ntask-1, child); if(info != ntask-1){ pvm_lvgroup("mmult"); pvm_exit(); return -1; } pvm_initsend(PvmDataDefault); pvm_pkint(&m, 1, 1); pvm_pkint(&blksize, 1, 1); pvm_mcast(child, ntask-1, DIMTAG); } else { pvm_recv(pvm_gettid("mmult", 0), DIMTAG); pvm_upkint(&m, 1, 1); pvm_upkint(&blksize, 1, 1); ntask = m*m; } barrier: info = pvm_barrier("mmult",ntask); if (info < 0) pvm_perror(argv[0]); for (i = 0; i < m; i++) myrow[i] = pvm_gettid("mmult", (mygid/m)*m + i); a = (int*)malloc(sizeof(int)*blksize*blksize); b = (int*)malloc(sizeof(int)*blksize*blksize); c = (int*)malloc(sizeof(int)*blksize*blksize); atmp = (int*)malloc(sizeof(int)*blksize*blksize); if (!(a && b && c && atmp)) { fprintf(stderr, "%s: out of memory!\n", argv[0]); free(a); free(b); free(c); free(atmp); pvm_lvgroup("mmult"); pvm_exit(); return -1; } row = mygid/m; col = mygid % m; up = pvm_gettid("mmult", ((row)? (row-1): (m-1))*m+col); down = pvm_gettid("mmult", ((row == (m-1))? col: (row+1)*m+col)); InitBlock(a, b, c, blksize, row, col); for (i = 0; i < m; i++) { if (col == (row + i)%m) { pvm_initsend(PvmDataDefault); pvm_pkint(a, blksize*blksize, 1); pvm_mcast(myrow, m, (i+1)*ATAG); BlockMult(c,a,b,blksize); } else { pvm_recv(pvm_gettid("mmult", row*m + (row +i)%m), (i+1)*ATAG); pvm_upkint(atmp, blksize*blksize, 1); BlockMult(c,atmp,b,blksize); } pvm_initsend(PvmDataDefault); pvm_pkint(b, blksize*blksize, 1); pvm_send(up, (i+1)*BTAG); pvm_recv(down, (i+1)*BTAG); pvm_upkint(b, blksize*blksize, 1); } info = pvm_barrier("mmult",ntask); if (info < 0) pvm_perror(argv[0]); for (i = 0 ; i < blksize*blksize; i++) if (a[i] != c[i]) printf("Error a[%d] (%d) != c[%d] (%d) \n", i, a[i],i,c[i]); if(VERBOSE){ printf("Block C at [%d,%d] managed by task %d in:\n", row, col, mytid); for(crow = 0; crow < blksize; crow++){ for(ccol = 0; ccol < blksize; ccol++) printf("%5d ", c[(crow*blksize) + ccol]); printf("\n"); } printf("Block A at [%d,%d] managed by task %d in:\n", row, col, mytid); for(crow = 0; crow < blksize; crow++){ for(ccol = 0; ccol < blksize; ccol++) printf("%5d ", a[(crow*blksize) + ccol]); printf("\n"); } } printf("mm.0.1 %d %d task %d done after %ld seconds.\n", m, blksize, mytid, time(NULL) - start_time); free(a); free(b); free(c); free(atmp); pvm_lvgroup("mmult"); pvm_exit(); return 0; }