Q1: Reading questions are due 2/18/2013, 9pm. Q2 (added 2/16, 9:30pm): Here is my 'cute' bit-mask based implementation of a reduction in Chapel using sync vars for reference, hoisted from the message boards: ----------------------------------------------------------------------- config var debug = false; var buff$: [1..numTasks] sync int; proc reduction(mytid:int, myval:int): int { var mask = 0x1; var result = myval; while (1) { if (mask & mytid) { // If my masked bit is 1, I'm done -- store my result and exit if debug then writeln("tid ", mytid, " storing ", result); buff$[mytid] = result; break; } else { // Otherwise, I'm combining -- figure out from whom const srcTid = mytid ^ mask; if ((srcTid) < numTasks) { // Is our partner in-bounds? // If so, read the value stored there if debug then writeln("tid ", mytid, " reading from ", srcTid); result += buff$[srcTid]; } else { if (mytid == 0) { // If we're tid 0 and our partner is out-of-bounds, we're done break; } else { // Otherwise, we sit this round out and wait for the next } } } mask <<= 1; } // This result will only be good on task 0 return result; } ----------------------------------------------------------------------- Q3 (added 2/16, 9:30pm): Coordinating output from MPI processes. In order to print out the array in a logical manner, you'll need to coordinate between the MPI processes such that each prints a part of the matrix before letting the next process take its turn. This was anticipated. What I forgot to anticipate is that not all MPI implementations guarantee that each process' printfs to stdout will come out in the logical order, even if you're very careful to have each process print one at a time. The reason is that the console I/O may be buffered in a way that cause printf()s to be reordered w.r.t. one another. And sadly, executing on the VM can run afoul of this issue. As a motivating example, consider the following program which is designed such that each process will print out its rollcall information in sorted order: ----------------------------------------------------------------------- #include #include #include "mpi.h" int main(int argc, char* argv[]) { int numProcs, myProcID; MPI_Init(&argc, &argv); MPI_Comm_size(MPI_COMM_WORLD, &numProcs); MPI_Comm_rank(MPI_COMM_WORLD, &myProcID); int myturn = 0; MPI_Status status; // Wait for my turn if (myProcID != 0) { MPI_Recv(&myturn, 1, MPI_INT, myProcID-1, 0, MPI_COMM_WORLD, &status); } // Do our printing printf("Process %d of %d checking in\n", myProcID, numProcs); fflush(stdout); // Signal the next process' turn if (myProcID != numProcs-1) { MPI_Send(&myturn, 1, MPI_INT, myProcID+1, 0, MPI_COMM_WORLD); } MPI_Finalize(); return 0; } ----------------------------------------------------------------------- Though in this example, we are very careful to print in a very specific order, the output may come out in a different order. In practice, there are two typical ways to deal with the issue of writing output in a coordinated manner: 1) The elegant, but complex approach (not particularly recommended for this assignment) is to have only one process do the I/O and have other processes communicate with that process. For example, process 0 could print when it needs to print, and otherwise sit in a receive "any tag"/"any source" loop. It might then receive one of three message types: (a) "please print this for me, process 0"; (b) "your turn to print again, process 0"; or (c) "we're all done with this printing stage, process 0, let's move on." Based on which message it gets, it takes the appropriate action and then goes on to the next receive (unless it gets message type (c) in which case it breaks out of the receive loop). 2) The less elegant, but simpler approach, which I recommend for this assignment: Have all files write to a single file in a coordinated manner such that none of them has it open at the same time. Start by open-for-creation and close the output file before anyone writes to it to ensure that it's empty. Then, when it's each process' turn to print, have it open the file for appending, write to the file, close the file, and then signal the next process that for its turn to write. This coordinated "one process opens, writes to, and closes the file at a time" idiom should be sufficient to ensure that the output is coherent. To get the output to appear on the console, you can then have a single process cat the output of the file to the console when everyone's done. Here's the same rollcall program as above, written using this idiom. Changes are noted with *** in comments: ----------------------------------------------------------------------- #include #include #include "mpi.h" int main(int argc, char* argv[]) { int numProcs, myProcID; MPI_Init(&argc, &argv); MPI_Comm_size(MPI_COMM_WORLD, &numProcs); MPI_Comm_rank(MPI_COMM_WORLD, &myProcID); int myturn = 0; MPI_Status status; // // *** Create a new, empty file *** // if (myProcID == 0) { FILE* outfile = fopen("out.txt", "w"); } MPI_Barrier(MPI_COMM_WORLD); // Wait for my turn if (myProcID != 0) { MPI_Recv(&myturn, 1, MPI_INT, myProcID-1, 0, MPI_COMM_WORLD, &status); } // // *** Open file for appending *** // FILE* outfile = fopen("out.txt", "a"); // *** Do our printing, but to the outfile rather than stdout *** fprintf(outfile, "Process %d of %d checking in\n", myProcID, numProcs); fflush(outfile); // *** Close the file for the next process *** fclose(outfile); // Signal the next process' turn if (myProcID != numProcs-1) { MPI_Send(&myturn, 1, MPI_INT, myProcID+1, 0, MPI_COMM_WORLD); } // *** Once everyone's done, have processor 0 cat the file to stdout *** MPI_Barrier(MPI_COMM_WORLD); if (myProcID == 0) { system("cat out.txt"); } MPI_Finalize(); return 0; } -----------------------------------------------------------------------