/*************************************************************** Distributed matrix multiplication using message passing. Uses a coordinator and W worker processes, as in Section 1.8 of the MPD book. Each worker computes N/W rows of results; assumes N is a multiple of W. Usage: a.out N numWorkers ***************************************************************/ resource distributed_matrix_mult() # read command line arguments for matrix sizes and numWorkers int n; getarg(1, n); int numWorkers; getarg(2, numWorkers); if ((n % numWorkers) != 0) { write("N must be a multiple of numWorkers"); stop(1); } int stripSize = n/numWorkers; op data[numWorkers] (real m[*,*]); # channels to Workers op result[numWorkers] (real m[*,*]); # channels to Coordinator process Coordinator { real a[n,n] = ([n] ([n] 1.0)), b[n,n] = ([n] ([n] 1.0)), c[n,n]; # send strips of a[*,*] and all of b[*,*] to Workers for [w = 1 to numWorkers] { int startRow = stripSize*(w-1) + 1; int endRow = startRow + stripSize - 1; send data[w] (a[startRow:endRow,*]); send data[w](b[*,*]); } # gather results from Workers for [w = 1 to numWorkers] { int startRow = stripSize*(w-1) + 1; int endRow = startRow + stripSize - 1; receive result[w](c[startRow:endRow,*]); } # print results for [i = 1 to n] { for [j = 1 to n] { writes(c[i,j]); writes(" "); } write() } } process Worker[w = 1 to numWorkers] { real a[stripSize,n], b[n,n], c[stripSize,n]; # receive strip of a and all of b from Coordinator receive data[w](a[*,*]); receive data[w](b[*,*]); # compute inner products of a[i,*] * b[*,j] for [i = 1 to stripSize, j = 1 to n] { real sum = 0.0; for [k = 1 to n] { sum += a[i,k] * b[k,j]; } c[i,j] = sum; } # send results back to Coordinator send result[w](c[*,*]); } end distributed_matrix_mult