2013-04-30/0002775000017000003100000000000012137670703011246 5ustar borchertsai2013-04-30/mpi-simpson.cpp0000664000017000003100000000414612137670442014230 0ustar borchertsai#include #include #include #include #include using namespace std; const double a = 0; const double b = 1; double f(double x) { return 4 / (1 + x*x); } // numerical integration according to the Simpson rule // for f over the interval [a,b] using n subintervals double simpson(double (*f)(double), double a, double b, int n) { assert(n > 0 && a <= b); double value = f(a)/2 + f(b)/2; double xleft; double x = a; for (int i = 1; i < n; ++i) { xleft = x; x = a + i * (b - a) / n; value += f(x) + 2 * f((xleft + x)/2); } value += 2 * f((x + b)/2); value *= (b - a) / n / 3; return value; } char* cmdname; void usage() { cerr << "Usage: " << cmdname << " [# intervals] " << endl; MPI_Abort(MPI_COMM_WORLD, 1); } int main(int argc, char** argv) { MPI_Init(&argc, &argv); int nofprocesses; MPI_Comm_size(MPI_COMM_WORLD, &nofprocesses); int rank; MPI_Comm_rank(MPI_COMM_WORLD, &rank); // process command line arguments int n; // number of intervals if (rank == 0) { cmdname = argv[0]; if (argc > 2) usage(); if (argc == 1) { n = nofprocesses; } else { istringstream arg(argv[1]); if (!(arg >> n) || n <= 0) usage(); } } // broadcast number of intervals MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD); double value = 0; // summed up value of our intervals; if (rank < n) { int nofintervals = n / nofprocesses; int remainder = n % nofprocesses; int first_interval = rank * nofintervals; if (rank < remainder) { ++nofintervals; if (rank > 0) first_interval += rank; } else { first_interval += remainder; } int next_interval = first_interval + nofintervals; double xleft = a + first_interval * (b - a) / n; double x = a + next_interval * (b - a) / n; value = simpson(f, xleft, x, nofintervals); } double sum; MPI_Reduce(&value, &sum, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); MPI_Finalize(); if (rank == 0) { cout << setprecision(14) << sum << endl; } } 2013-04-30/mpi-chase.cpp0000664000017000003100000000536612137670610013625 0ustar borchertsai#include #include #include #include #include using namespace std; char* cmdname; void usage() { cerr << "Usage: " << cmdname << " [bufsize [count]]" << endl; MPI_Abort(MPI_COMM_WORLD, 1); } int setup_chain(int nofprocesses) { int* indices = new int[nofprocesses]; for (int i = 0; i < nofprocesses; ++i) { indices[i] = i; } // shuffle indices but keep 0 at pos 0 for (int i = 1; i < nofprocesses-1; ++i) { int j = i + lrand48() % (nofprocesses - i); if (i != j) { int tmp = indices[i]; indices[i] = indices[j]; indices[j] = tmp; } } for (int i = 1; i < nofprocesses; ++i) { int next = i + 1; if (next == nofprocesses) next = 0; MPI_Send(&indices[next], 1, MPI_INT, indices[i], 0, MPI_COMM_WORLD); } int next = indices[1]; delete[] indices; return next; } void chase_packets(int bufsize, int count, int next, int rank) { unsigned char* buf = new unsigned char[bufsize]; MPI_Status status; if (rank == 0) { while (count-- > 0) { MPI_Send(buf, bufsize, MPI_UNSIGNED_CHAR, next, 0, MPI_COMM_WORLD); MPI_Recv(buf, bufsize, MPI_UNSIGNED_CHAR, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status); } } else { while (count-- > 0) { MPI_Recv(buf, bufsize, MPI_UNSIGNED_CHAR, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status); MPI_Send(buf, bufsize, MPI_UNSIGNED_CHAR, next, 0, MPI_COMM_WORLD); } } } int main(int argc, char** argv) { MPI_Init(&argc, &argv); int nofprocesses; MPI_Comm_size(MPI_COMM_WORLD, &nofprocesses); int rank; MPI_Comm_rank(MPI_COMM_WORLD, &rank); int bufsize = 32; int count = 32; if (rank == 0) { cmdname = *argv++; --argc; if (argc > 0) { istringstream arg(*argv++); --argc; if (!(arg >> bufsize) || bufsize <= 0) usage(); } if (argc > 0) { istringstream arg(*argv++); --argc; if (!(arg >> count) || count <= 0) usage(); } if (argc > 0) usage(); } MPI_Bcast(&bufsize, 1, MPI_INT, 0, MPI_COMM_WORLD); MPI_Bcast(&count, 1, MPI_INT, 0, MPI_COMM_WORLD); int next; if (rank == 0) { next = setup_chain(nofprocesses); } else { MPI_Status status; MPI_Recv(&next, 1, MPI_INT, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status); } struct timeval tbuf1; gettimeofday(&tbuf1, 0); chase_packets(bufsize, count, next, rank); struct timeval tbuf2; gettimeofday(&tbuf2, 0); long int usec = (tbuf2.tv_sec - tbuf1.tv_sec) * 1000000 + (tbuf2.tv_usec - tbuf1.tv_usec); MPI_Finalize(); if (rank == 0) { double avgTimeInMicrosecs = (double) usec / (double) count / nofprocesses; cout << "avg message time in us: " << avgTimeInMicrosecs << endl; } } 2013-04-30/mpi-gemv.cpp0000664000017000003100000000747012137670703013501 0ustar borchertsai/* multiply a N x N matrix with a vector; Input format: Input ::= Dimension Matrix Vector Dimension ::= Digits Matrix ::= { FloatingPointNumber } # Dimension x Dimension times Vector ::= { FloatingPointNumber } # Dimension times Output format: Output ::= { FloatingPointNumber } # Dimension times */ #include #include #include using namespace std; enum { NEXT_ROW, FINISH }; static void gemv_master(int n, double** A, double *x, double* y, int nofslaves) { // broadcast parameters that are required by all slaves MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD); MPI_Bcast(x, n, MPI_DOUBLE, 0, MPI_COMM_WORLD); // send out initial tasks for all slaves int* tasks = new int[nofslaves]; // remember the task for each of the slaves int next_task = 0; for (int slave = 1; slave <= nofslaves; ++slave) { if (next_task < n) { int row = next_task++; // pick next remaining task MPI_Send(A[row], n, MPI_DOUBLE, slave, NEXT_ROW, MPI_COMM_WORLD); tasks[slave-1] = row; // remember which task was sent out to whom } else { // there is no work left for this slave MPI_Send(0, 0, MPI_DOUBLE, slave, FINISH, MPI_COMM_WORLD); } } // collect results and send out remaining tasks int done = 0; while (done < n) { // receive result of a completed task double value = 0; // initialize it to get rid of warning MPI_Status status; MPI_Recv(&value, 1, MPI_DOUBLE, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status); int slave = status.MPI_SOURCE; int row = tasks[slave-1]; y[row] = value; ++done; // send out next task, if there is one left if (next_task < n) { row = next_task++; MPI_Send(A[row], n, MPI_DOUBLE, slave, NEXT_ROW, MPI_COMM_WORLD); tasks[slave-1] = row; } else { // send notification that there is no more work to be done MPI_Send(0, 0, MPI_DOUBLE, slave, FINISH, MPI_COMM_WORLD); } } // release allocated memory delete[] tasks; } static void gemv_slave() { int n; MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD); double* x = new double[n]; MPI_Bcast(x, n, MPI_DOUBLE, 0, MPI_COMM_WORLD); double* row = new double[n]; // receive tasks and process them for(;;) { // receive next task MPI_Status status; MPI_Recv(row, n, MPI_DOUBLE, 0, MPI_ANY_TAG, MPI_COMM_WORLD, &status); if (status.MPI_TAG == FINISH) break; // process it double result = 0; for (int i = 0; i < n; ++i) { result += row[i] * x[i]; } // send result back to master MPI_Send(&result, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD); } // release allocated memory delete[] x; delete[] row; } static bool read_parameters(int& n, double**& matrix, double*& vector) { if (!(cin >> n) || n <= 0) return false; matrix = new double*[n]; for (int i = 0; i < n; ++i) { matrix[i] = new double[n]; for (int j = 0; j < n; ++j) { if (!(cin >> matrix[i][j])) return false; } } vector = new double[n]; for (int i = 0; i < n; ++i) { if (!(cin >> vector[i])) return false; } return true; } int main(int argc, char** argv) { MPI_Init(&argc, &argv); int rank; MPI_Comm_rank(MPI_COMM_WORLD, &rank); int nofslaves; MPI_Comm_size(MPI_COMM_WORLD, &nofslaves); --nofslaves; assert(nofslaves > 0); if (rank == 0) { int n; double** A; double* x; if (!read_parameters(n, A, x)) { cerr << "Invalid input!" << endl; MPI_Abort(MPI_COMM_WORLD, 1); } double* y = new double[n]; gemv_master(n, A, x, y, nofslaves); for (int i = 0; i < n; ++i) { cout << " " << y[i] << endl; } } else { gemv_slave(); } MPI_Finalize(); }