void LTSor::consumeInput() { // create a tuple synch lock tuple *synchLock = make_tuple("s", SYNCH_LOCK); put_tuple(synchLock, &ctx); // Initialise. note that as these can run in processes, the // solution vector must live in tuple space to be communicated // between the workers. Setting the solution variable is LOCAL ONLY Matrix matrix = (Matrix) inputs[0]; Vector target = (Vector) inputs[1]; Vector solution = (Vector) outputs[0]; for (index_t r = 0; r < SOR_N; ++r) { VECTOR(solution, r) = 1.0; } // put a tuple for the solution vector into tuple space tuple *solutionTuple = make_tuple("ss", SOLUTION_VECTOR); solutionTuple->elements[1].data.s.len = sizeof(solution); solutionTuple->elements[1].data.s.ptr = (char*) solution; // loop until we get the desired tolerance real maxDiff = (real)(2 * SOR_TOLERANCE); for (index_t t = 0; (t < SOR_MAX_ITERS) && (maxDiff >= SOR_TOLERANCE); t++) { maxDiff = 0.0; for (index_t r = 0; r < SOR_N; ++r) { // compute sum real sum = solutionSum(r); // calculate new solution real oldSolution = VECTOR(solution, r); VECTOR(solution, r) = (real)( (1.0 - SOR_OMEGA) * oldSolution + SOR_OMEGA * (VECTOR(target, r) - sum) / MATRIX_SQUARE_N(matrix, r, r, SOR_N) ); // refresh the solution vector in tuple-space tuple *solutionBlank = make_tuple("s?", SOLUTION_VECTOR); get_tuple(solutionBlank, &ctx); put_tuple(solutionTuple, &ctx); destroy_tuple(solutionBlank); // compute difference real diff = (real) fabs((double)(oldSolution - VECTOR(solution, r))); if (diff > maxDiff) { maxDiff = diff; } } } // flag the output producer. put_tuple(make_tuple("s", SOR_FLAG), &ctx); }
void LTRandmat::setup() { IntVector state = NEW_VECTOR_SZ(INT_TYPE, RANDMAT_NR); // generate first column values VECTOR(state, 0) = RAND_SEED % RAND_M; for (index_t row = 1; row < RANDMAT_NR; ++row) { VECTOR(state, row) = next(VECTOR(state, row - 1)); } // generate the A and C values for the next(k) method. aPrime = RANDMAT_A; cPrime = 1; for (index_t i = 1; i < RANDMAT_NR; ++i) { cPrime = (cPrime + aPrime) % RAND_M; aPrime = (aPrime * RANDMAT_A) % RAND_M; } cPrime = (cPrime * RANDMAT_C) % RAND_M; // emit the state vector to the tuple space. tuple *init = make_tuple("ss", "randmat state", ""); init->elements[1].data.s.len = sizeof(INT_TYPE) * RANDMAT_NR; init->elements[1].data.s.ptr = (char*) state; put_tuple(init, &ctx); destroy_tuple(init); }
void LTMandel::consumeInput() { // send off a mandelbrot request for each grid row. for (size_t y = 0; y < MANDEL_NR; ++y) { tuple *send = make_tuple("si", "mandel request"); send->elements[1].data.i = y; put_tuple(send, &ctx); destroy_tuple(send); } }
real LTSor::solutionSum(index_t row) { // tuple template. tuple *send = make_tuple("sii", "sor request"); // create an "rows reporting" tuple, so that we // know when the computation should end. tuple *rowsReporting = make_tuple("si", ROWS_DONE, 0); put_tuple(rowsReporting, &ctx); // create a sum tuple tuple *sumTuple = make_tuple("sd", SOLUTION_SUM, 0.0); put_tuple(sumTuple, &ctx); // split points, based on a cluster size of the square-root of the // number of elements in the solution vector. index_t skip = (size_t) sqrt((real) SOR_N); for (index_t pos = 0; pos < SOR_N; pos += skip) { send->elements[1].data.i = pos; send->elements[2].data.i = std::min(pos + skip, SOR_N); put_tuple(send, &ctx); } // wait for all the rows to be consumed rowsReporting->elements[1].data.i = SOR_N; get_tuple(rowsReporting, &ctx); // get the sum of the tuple-space op destroy_tuple(sumTuple); sumTuple = make_tuple("s?", SOLUTION_SUM); get_tuple(sumTuple, &ctx); // return the result return sumTuple->elements[1].data.d; }
void LTRandmat::work() { tuple *recv = make_tuple("s?", REQUEST); tuple *tmpInit = make_tuple("s?", "randmat state"); tuple *init = NULL; IntVector initVector = NULL; // satisfy randmat requests. while (1) { // block until we receive a tuple. tuple* gotten = get_tuple(recv, &ctx); // grab a copy of the initializer, tuple if we haven't already if (!init) { init = read_tuple(tmpInit, &ctx); initVector = (IntVector) init->elements[1].data.s.ptr; } // copy over row co-ordinate of the computation; create // a buffer for the results of the computation. size_t row = gotten->elements[1].data.i; tuple *send = make_tuple("sis", "randmat done", row, ""); IntVector buffer = (IntVector) NEW_VECTOR_SZ(INT_TYPE, RANDMAT_NC); send->elements[2].data.s.len = sizeof(INT_TYPE) * RANDMAT_NC; send->elements[2].data.s.ptr = (char*) buffer; // perform the actual computation for this row. buffer[0] = VECTOR(initVector, row); for (int x = 1; x < RANDMAT_NC; ++x) { buffer[x] = (aPrime * buffer[x-1] + cPrime) % RAND_M; } // send off the new tuple and purge local memory of the one we got put_tuple(send, &ctx); destroy_tuple(gotten); destroy_tuple(send); delete[] buffer; } // TODO destroy the template tuples; must send tuples for this // destroy_tuple(recv); }
void LTRandmat::consumeInput() { // create the first, seed column setup(); // tuple template tuple *send = make_tuple("si", REQUEST, 0); // send off a request for each grid row. for (size_t y = 0; y < RANDMAT_NR; ++y) { send->elements[1].data.i = y; put_tuple(send, &ctx); } // destroy the template tuple destroy_tuple(send); }
void LTMandel::work() { tuple *recv = make_tuple("s?", "mandel request"); // 2D delta between calculated points real dX = MANDEL_DX / (MANDEL_NC - 1); real dY = MANDEL_DY / (MANDEL_NR - 1); // satisfy mandelbrot requests. while (1) { // block until we receive a tuple. tuple* gotten = get_tuple(recv, &ctx); // copy over row co-ordinate of the computation; create // a buffer for the results of the computation. tuple *send = make_tuple("sis", "mandel done", gotten->elements[1].data.i, ""); int* buffer = (int*) malloc(sizeof(int) * MANDEL_NC); send->elements[2].data.s.len = sizeof(int) * MANDEL_NC; send->elements[2].data.s.ptr = (char*) buffer; // perform the actual computation for this row. double rY = MANDEL_Y0 + dY * send->elements[1].data.i; double rX = MANDEL_X0; for (int x = 0; x < MANDEL_NC; ++x, rX += dX) { buffer[x] = mandelCalc(rX, rY); } // send off the new tuple and purge local memory of the one we gotten put_tuple(send, &ctx); destroy_tuple(gotten); destroy_tuple(send); } // TODO destroy the template tuples; must send tuples for this // destroy_tuple(send); // destroy_tuple(recv); }
/** * Put out requests to have FFT operations done, and measure how * long it takes to get the results back. */ int main(int argc, char *argv[]) { struct tuple *s, *t, *u; int i, j, iters = 0; int r1[PARALLEL], r2[PARALLEL], r3[PARALLEL]; double x[N], y[N], mult; struct timeval T0, T1; int rndsock; struct context ctx; if (get_server_portnumber(&ctx)) { if (argc < 3) { /* help message */ fprintf(stderr, "Usage: %s <server> <portnumber>\n", argv[0]); exit(1); } strcpy(ctx.peername, argv[1]); ctx.portnumber = atoi(argv[2]); } rndsock = open("/dev/urandom", O_RDONLY); mult = 1.0 / pow(2.0, 31); for (i = 0; i < N; i++) { x[i] = mult * random_int(); y[i] = mult * random_int(); } s = make_tuple("siiis#s#", "fft", 0, 0, 0, x, N * sizeof(double), y, N * sizeof(double)); t = make_tuple("siii??", "fft done", 0, 0, 0); gettimeofday(&T0, NULL); while (1) { for (j = 0; j < PARALLEL; j++) { r1[j] = random_int(); r2[j] = random_int(); r3[j] = random_int(); s->elements[1].data.i = r1[j]; s->elements[2].data.i = r2[j]; s->elements[3].data.i = r3[j]; if (put_tuple(s, &ctx)) { perror("put_tuple failed"); exit(1); } } for (j = 0; j < PARALLEL; j++) { t->elements[1].data.i = r1[j]; t->elements[2].data.i = r2[j]; t->elements[3].data.i = r3[j]; u = get_tuple(t, &ctx); if (u == NULL) { perror("get_tuple failed"); exit(1); } } gettimeofday(&T1, NULL); iters += PARALLEL; printf("%f\n", TIMEVAL_DIFF(T0, T1) / iters); } close(rndsock); destroy_tuple(s); destroy_tuple(t); destroy_tuple(u); return 0; }
void LTSor::work() { // tuple templates tuple *synchLock = make_tuple("s", SYNCH_LOCK); tuple *recv = make_tuple("s??", "sor request"); // grab pointers locally. Matrix matrix = (Matrix) inputs[0]; while (1) { // block until we receieve a tuple. tuple* gotten = get_tuple(recv, &ctx); index_t row = gotten->elements[1].data.i; index_t start = gotten->elements[2].data.i; index_t stop = gotten->elements[3].data.i; // grab the solution tuple tuple *templateSolutionTuple = make_tuple("s?", SOLUTION_VECTOR); tuple *solutionTuple = read_tuple(templateSolutionTuple, &ctx); destroy_tuple(templateSolutionTuple); Vector solution = (Vector) solutionTuple->elements[1].data.s.ptr; // sum part of the matrix row with the corresponding elements // in the solution vector. real sum = 0.0; for (index_t col = start; col < stop; ++col) { if (col != row) { sum += MATRIX_SQUARE_N(matrix, row, col, SOR_N) * VECTOR(solution, col); } } // purge local memory of the tuple we received destroy_tuple(gotten); // Now, we combine the results from these elements with the "world". // enter the critical section get_tuple(synchLock, &ctx); // combine results with master copy (sum) tuple *tmpSum = make_tuple("s?", SOLUTION_SUM); tuple *tupleSum = get_tuple(tmpSum, &ctx); tmpSum->elements[1].data.d = sum + tupleSum->elements[1].data.d; put_tuple(tmpSum, &ctx); destroy_tuple(tmpSum); destroy_tuple(tupleSum); // record the number of rows reporting tuple *templateRowsReporting = make_tuple("s?", ROWS_DONE); tuple *rowsReporting = get_tuple(templateRowsReporting, &ctx); rowsReporting->elements[1].data.i += (stop - start); put_tuple(rowsReporting, &ctx); destroy_tuple(templateRowsReporting); destroy_tuple(rowsReporting); // leave the critical section put_tuple(synchLock, &ctx); } }