/* Get and declare the arguments with macros too */ #define ARGS(TYPEI) \ int xreg, int yreg, TYPEI *avi, int starti, int jumpi /* -- Procedures --------------------------------------------------------- */ void array_random_u_2d_f(ARGS(float), double p0, double p1) { DECLARE_LOOPVARS (float) double range = p1 - p0; LOOP_2D *aifst = range * erand48(seed) + p0; } void array_random_ui_2d_f(ARGS(float), double p0, double p1) { DECLARE_LOOPVARS (float) double range = p1 - p0; LOOP_2D *aifst = floor(range * erand48(seed) + p0); } float gaussdev (void) /* Returns a normally distributed deviate using the code from Numerical Recipes in C (Press et al.) */ { static int iset = 0;
int main( int argc, char** argv ) { int pnum, pid; double elapsed_time; float *A, *B, *C, *Cans; float diff; int n = 2048; int i, j, k; unsigned short seed[3]; if( argc != 1 ){ if( argc == 2 ){ n = atoi(argv[1]); } else{ printf("mmul [n]\n"); exit(0); } } MPI_Init(&argc, &argv); MPI_Comm_size(MPI_COMM_WORLD, &pnum); MPI_Comm_rank(MPI_COMM_WORLD, &pid); //printf("Processor %d out of %d says hi!\n", pid, pnum); if( pid == 0 ){ //printf("Intializing matrix size : %d x %d x %d\n", n, n, n); A = (float*)malloc( sizeof(float) * n * n ); B = (float*)malloc( sizeof(float) * n * n ); C = (float*)malloc( sizeof(float) * n * n ); seed[0] = 0; seed[1] = 1; seed[2] = 2; for (i=0; i<n; i++) { for (k=0; k<n; k++) { A(i,k) = (float)erand48(seed); } } for (k=0; k<n; k++) { for (j=0; j<n; j++) { B(k,j) = (float)erand48(seed); } } } MPI_Barrier(MPI_COMM_WORLD); elapsed_time = -1*MPI_Wtime(); //Please modify the content of this function mmul(A, B, C, n); MPI_Barrier(MPI_COMM_WORLD); elapsed_time += MPI_Wtime(); if( pid == 0 ){ printf("Elapsed Time : %f secs\n", elapsed_time); Cans = (float*)malloc( sizeof(float) * n * n ); mmul1(A, B, Cans, n); diff = compute_diff(C, Cans, n); printf("Performance : %.2f GFlops\n", 2.0*n*n*n/elapsed_time/1000000000 ); printf("Result Diff : %.3f\%\n", diff*100 ); free(A); free(B); free(C); free(Cans); }
double drand48(void) { return erand48(__rand48_seed); }
int beginSlavery(int fd) { uint16_t randContext[3]; for(int i = 0; i < 3; i++) { randContext[i] = time(NULL) ^ getpid(); } int returnCode = -1; json_t* params = NULL; json_t* nextCommand = NULL; char** values = NULL; struct workerTask* tasks = NULL; uint32_t connPoolSize = 128; uint32_t connPoolCount = 0; void** connPool = __xmalloc(sizeof(void*) * connPoolSize); memset(connPool, 0, sizeof(void*) * connPoolSize); //recieve initial parameters params = readCommand(fd, 5000); if(!params) { fprintf(stderr, "No initialization packet\n"); goto exit; } //make sure the initial packet has all of the required info uint64_t slaveID; const char* command; const char* address; const char* username; const char* password; const char* tableName; int port; int errorChecking; int valueLength; int result = json_unpack(params, "{s:s, s:s, s:i, s:I, s:s, s:s, s:s, s:b, s:i}", "command", &command, "address", &address, "port", &port, "slave-id", &slaveID, "username", &username, "password", &password, "table", &tableName, "error-checking", &errorChecking, "value-length", &valueLength); if(result != 0 || strcmp(command, "init") || port <= 0 || port > 65535) { fprintf(stderr, "Invalid initialization packet recieved\n"); goto exit; } uint64_t numKeys = 0; //loop and execute commands from the master while(1) { nextCommand = readCommand(fd, 15000); if(!nextCommand) { fprintf(stderr, "Invalid next command\n"); goto exit; } const char* command; int result = json_unpack(nextCommand, "{s:s}", "command", &command); if(result == -1) { fprintf(stderr, "Packet missing command field\n"); goto exit; } //parse commands and modify keyRange array if needed struct workerTask task; if(!strcmp(command, "add")) { uint64_t numKeysToAdd; int result = json_unpack(nextCommand, "{s:I}", "amount", &numKeysToAdd); if(result == -1) { goto exit; } if(errorChecking) { values = __xrealloc(values, sizeof(char*) * (numKeys + numKeysToAdd)); for(uint64_t i = 0; i < numKeysToAdd; i++) { values[numKeys + i] = __xmalloc(valueLength + 1); for(int j = 0; j < valueLength; j++) { values[numKeys + i][j] = (erand48(randContext) * 26) + 'A'; } values[numKeys + i][valueLength] = '\0'; } } task.startingKey = slaveID + numKeys; task.numKeys = numKeysToAdd; task.type = kClientAddKeys; task.values = values; numKeys += task.numKeys; } else if(!strcmp(command, "remove")) { uint64_t numKeysToRemove; int result = json_unpack(nextCommand, "{s:I}", "amount", &numKeysToRemove); if(result == -1) { goto exit; } if(errorChecking) { uint64_t position = numKeys - numKeysToRemove; for(uint64_t i = 0; i < numKeysToRemove; i++) { free(values[position + i]); } values = __xrealloc(&values, sizeof(char*) * (numKeys - numKeysToRemove)); } if(numKeysToRemove > numKeys) { goto exit; } task.startingKey = slaveID + numKeys - numKeysToRemove; task.numKeys = numKeysToRemove; task.type = kClientRemoveKeys; task.values = NULL; numKeys -= numKeysToRemove; } else if(!strcmp(command, "test")) { json_t* array = json_object_get(nextCommand, "workload"); //right now we only need 1 workload type if(!(json_is_array(array) && json_array_size(array) == kWorkloadTypes)) { goto exit; } for(int i = 0; i < kWorkloadTypes; i++) { task.workloadComposition[i] = json_number_value(json_array_get(array, i)); } int result = json_unpack(nextCommand, "{s:I}", "amount", &task.count); if(result == -1) { goto exit; } task.startingKey = slaveID; task.numKeys = numKeys; task.values = values; task.type = kClientRunWorkload; } else if(!strcmp(command, "quit")) { returnCode = 0; goto exit; } else { fprintf(stderr, "unknown command from client: %s\n", command); goto exit; } int numClients; result = json_unpack(nextCommand, "{s:i, s:F}", "num-clients", &numClients, "throughput", &task.throughput); if(result == -1) { fprintf(stderr, "Packet missing number of clients or throughput value\n"); goto exit; } task.connOpenDelay = 0; //fill out the generic task information task.table = tableName; task.valueSize = valueLength; task.workerID = slaveID; task.hostname = address; task.username = username; task.password = password; task.port = port; //split the request between the clients while(numClients >= connPoolSize) { size_t oldSize = connPoolSize; connPoolSize *= 8; connPool = __xrealloc(connPool, connPoolSize * sizeof(void*)); memset(&connPool[oldSize], 0, sizeof(void*) * oldSize * 7); } if(numClients < connPoolCount) { for(int i = connPoolCount - 1; i >= numClients; i--) { storage_disconnect(connPool[i]); connPool[i] = NULL; } } tasks = __xmalloc(sizeof(struct workerTask) * numClients); splitTasks(&task, tasks, numClients, connPool); //perform the request json_t* requestResponse; performRequest(tasks, numClients, &requestResponse); //save the connections for next time for(int i = 0; i < numClients; i++) { connPool[i] = tasks[i].conn; } connPoolCount = numClients; //send the result back to the master char* serialResponse = json_dumps(requestResponse, JSON_COMPACT); json_decref(requestResponse); size_t len = strlen(serialResponse); if(len > 1048576) { fprintf(stderr, "Response too large (%zd)\n", len); free(serialResponse); goto exit; } char sizeBuf[9]; sprintf(sizeBuf, "%08d", (int)len); sendAll(fd, sizeBuf, 8); if(sendAll(fd, serialResponse, strlen(serialResponse)) == -1) { free(serialResponse); goto exit; } free(serialResponse); free(tasks); tasks = NULL; //free the parsed command json_decref(nextCommand); nextCommand = NULL; } exit: for(uint32_t i = 0; i < connPoolCount; i++) { storage_disconnect(connPool[i]); } free(connPool); free(tasks); json_decref(nextCommand); json_decref(params); if(values) { for(uint64_t i = 0; i < numKeys; i++) { free(values[i]); } free(values); } return returnCode; }
const char* testClient(void* parameters) { struct workerTask* worker = (struct workerTask*)parameters; uint16_t randContext[3]; for(int i = 0; i < 3; i++) { randContext[i] = time(NULL) ^ worker->workerID; } if(!worker->conn) { //spread the load from new connections so the server won't be overloaded usleep(erand48(randContext) * 1000 + 1000*worker->connOpenDelay); worker->conn = storage_connect(worker->hostname, worker->port); if(!worker->conn) { printf("storage_connect failed\n"); return ece297strerror(errno); } int result = storage_auth(worker->username, worker->password, worker->conn); if(result == -1) { printf("storage_auth failed\n"); storage_disconnect(worker->conn); worker->conn = NULL; return ece297strerror(errno); } } uint64_t loopCount = worker->numKeys; if(worker->type == kClientRunWorkload) { loopCount = worker->count; } uint64_t period = 0; //0 throughput = no limit if(worker->throughput) { period = (1/worker->throughput) * 1000000; //start at a random time usleep(erand48(randContext) * period); } struct timeval next; gettimeofday(&next, NULL); for(uint64_t i = 0; i < loopCount; i++) { if(worker->throughput) { int64_t timeRemaining = -uSElapsed(&next); if(timeRemaining > 0) { usleep((uint32_t)timeRemaining); } uint64_t newTime = next.tv_usec + period; next.tv_sec += newTime / 1000000; next.tv_usec = newTime % 1000000; } switch (worker->type) { case kClientAddKeys: { char keyBuf[20]; //as per ECE297 spec stringGen(worker->startingKey + i, worker->keySecret, keyBuf, sizeof(keyBuf)); struct storage_record record; memset(&record.metadata, 0, sizeof(record.metadata)); stringGen(worker->startingKey + i, worker->valueSecret, record.value, sizeof(record.value)); struct timeval start; gettimeofday(&start, NULL); if(storage_set(worker->table, keyBuf, &record, worker->conn) == -1) { printf("storage_set failed\n"); return ece297strerror(errno); } recordLatency(timeElapsed(&start), worker->latencyResults); break; } case kClientRunWorkload: { //WATCH the floating point promotion - it must be cast to a uint64_t BEFORE adding worker->startingKey uint64_t keyIndex = ((uint64_t)(erand48(randContext) * worker->numKeys)) + worker->startingKey; char keyBuf[20]; //as per ECE297 spec stringGen(keyIndex, worker->keySecret, keyBuf, sizeof(keyBuf)); char expectedValue[1024]; stringGen(keyIndex, worker->valueSecret, expectedValue, sizeof(expectedValue)); struct timeval start; gettimeofday(&start, NULL); struct storage_record rec; if(storage_get(worker->table, keyBuf, &rec, worker->conn) == -1) { printf("storage_get failed (key index = %u)\n", keyIndex); return ece297strerror(errno); } if(strcmp(rec.value, expectedValue)) { return "Server returned incorrect key"; } recordLatency(timeElapsed(&start), worker->latencyResults); } } } return NULL; }
/* Utility Function: init_cell * Initializes atoms in a cell */ void init_cell(Cell* this_cell, int xi, int yi, int zi, const SimParams* params) { // Set some cell values this_cell->x = xi; this_cell->y = yi; this_cell->z = zi; const double pdx = params->max_x - params->min_x; const double pdy = params->max_y - params->min_y; const double pdz = params->max_z - params->min_z; this_cell->min_x = params->min_x + (pdx * xi) / params->cell_dim_x; this_cell->max_x = params->min_x + (pdx * (xi+1)) / params->cell_dim_x; this_cell->min_y = params->min_y + (pdy * yi) / params->cell_dim_y; this_cell->max_y = params->min_y + (pdy * (yi+1)) / params->cell_dim_y; this_cell->min_z = params->min_z + (pdz * zi) / params->cell_dim_z; this_cell->max_z = params->min_z + (pdz * (zi+1)) / params->cell_dim_z; // Build up the list of atoms, using a uniform random distribution // Since we are doing each cell separately, we don't know exactly // how many atoms to put in it. Therefore, we will allocate a // random number such that the total number of atoms on average // would come out right. We'll do this by pretending to assign // all the atoms, but only actually assigning a 1/# of cells fraction // of them. double* x = new double[params->n_atoms]; double* y = new double[params->n_atoms]; double* z = new double[params->n_atoms]; int atom_count = 0; const double prob = 1.0 / (params->cell_dim_x * params->cell_dim_y * params->cell_dim_z); const double cdx = this_cell->max_x - this_cell->min_x; const double cdy = this_cell->max_y - this_cell->min_y; const double cdz = this_cell->max_z - this_cell->min_z; // Give some seed that is unique to this cell unsigned short int seed[3]; seed[0] = (unsigned short)xi; seed[1] = (unsigned short)yi; seed[2] = (unsigned short)zi; int i; for(i=0; i < params->n_atoms; i++) { if (erand48(seed) < prob) { x[atom_count] = this_cell->min_x + (cdx * erand48(seed)); y[atom_count] = this_cell->min_y + (cdy * erand48(seed)); z[atom_count] = this_cell->min_z + (cdz * erand48(seed)); atom_count++; } } if(atom_count > 40) atom_count = 40 ; // Allocate the atom array for the cell this_cell->atoms = new Atom[atom_count]; this_cell->n_atoms = atom_count; // Store the positions into the cells. Also randomly determine // a mass and charge, and zero out the velocity and force for(i=0;i<atom_count;i++) { Atom* this_atom = &(this_cell->atoms[i]); this_atom->m = 10.0 * erand48(seed); this_atom->q = 5.0 * erand48(seed) - 2.5; this_atom->x = x[i]; this_atom->y = y[i]; this_atom->z = z[i]; this_atom->vx = this_atom->vy = this_atom->vz = 0; this_atom->vhx = this_atom->vhy = this_atom->vhz = 0; this_atom->fx = this_atom->fy = this_atom->fz = 0; //CmiPrintf("m:%f, q:%f, x:%f y:%f z:%f\n", this_atom->m, this_atom->q, this_atom->x, this_atom->y, this_atom->z); } delete [] x; delete [] y; delete [] z; }
/* * fetch a source random number from the pseudo random number generator: * erand48() */ static double rand_src_rand48(unsigned short *xi) { return (erand48(xi)); }
int main (void) { unsigned short int xs[3] = { 0x0001, 0x0012, 0x0123 }; unsigned short int lxs[7]; unsigned short int *xsp; int result = 0; long int l; double d; double e; /* Test srand48. */ srand48 (0x98765432); /* Get the values of the internal Xi array. */ xsp = seed48 (xs); if (xsp[0] != 0x330e || xsp[1] != 0x5432 || xsp[2] != 0x9876) { puts ("srand48(0x98765432) didn't set correct value"); printf (" expected: { %04hx, %04hx, %04hx }\n", 0x330e, 0x5432, 0x9876); printf (" seen: { %04hx, %04hx, %04hx }\n", xsp[0], xsp[1], xsp[2]); result = 1; } /* Put the values back. */ memcpy (xs, xsp, sizeof (xs)); (void) seed48 (xs); /* See whether the correct values are installed. */ l = lrand48 (); if (l != 0x2fed1413l) { printf ("lrand48() in line %d failed: expected %lx, seen %lx\n", __LINE__ - 4, 0x2fed1413l, l); result = 1; } l = mrand48 (); if (l != 0xa28c1003l) { printf ("mrand48() in line %d failed: expected %lx, seen %lx\n", __LINE__ - 4, 0xa28c1003l, l); result = 1; } l = lrand48 (); if (l != 0x585fcfb7l) { printf ("lrand48() in line %d failed: expected %lx, seen %lx\n", __LINE__ - 4, 0x585fcfb7l, l); result = 1; } l = mrand48 (); if (l != 0x9e88f474l) { printf ("mrand48() in line %d failed: expected %lx, seen %lx\n", __LINE__ - 4, 0x9e88f474l, l); result = 1; } /* Test seed48. The previous call should have install the values in the initialization of `xs' above. */ xs[0] = 0x1234; xs[1] = 0x5678; xs[2] = 0x9012; xsp = seed48 (xs); if (xsp[0] != 0x62f2 || xsp[1] != 0xf474 || xsp[2] != 0x9e88) { puts ("seed48() did not install the values correctly"); printf (" expected: { %04hx, %04hx, %04hx }\n", 0x62f2, 0xf474, 0x9e88); printf (" seen: { %04hx, %04hx, %04hx }\n", xsp[0], xsp[1], xsp[2]); result = 1; } /* Test lrand48 and mrand48. We continue from the seed established above. */ l = lrand48 (); if (l != 0x017e48b5l) { printf ("lrand48() in line %d failed: expected %lx, seen %lx\n", __LINE__ - 4, 0x017e48b5l, l); result = 1; } l = mrand48 (); if (l != 0xeb7a1fa3l) { printf ("mrand48() in line %d failed: expected %lx, seen %lx\n", __LINE__ - 4, 0xeb7a1fa3l, l); result = 1; } l = lrand48 (); if (l != 0x6b6a3f95l) { printf ("lrand48() in line %d failed: expected %lx, seen %lx\n", __LINE__ - 4, 0x6b6a3f95l, l); result = 1; } l = mrand48 (); if (l != 0x175c0d6fl) { printf ("mrand48() in line %d failed: expected %lx, seen %lx\n", __LINE__ - 4, 0x175c0d6fl, l); result = 1; } /* Test lcong48. */ lxs[0] = 0x4567; lxs[1] = 0x6789; lxs[2] = 0x8901; lxs[3] = 0x0123; lxs[4] = 0x2345; lxs[5] = 0x1111; lxs[6] = 0x2222; lcong48 (lxs); /* See whether the correct values are installed. */ l = lrand48 (); if (l != 0x6df63d66l) { printf ("lrand48() in line %d failed: expected %lx, seen %lx\n", __LINE__ - 4, 0x6df63d66l, l); result = 1; } l = mrand48 (); if (l != 0x2f92c8e1l) { printf ("mrand48() in line %d failed: expected %lx, seen %lx\n", __LINE__ - 4, 0x2f92c8e1l, l); result = 1; } l = lrand48 (); if (l != 0x3b4869ffl) { printf ("lrand48() in line %d failed: expected %lx, seen %lx\n", __LINE__ - 4, 0x3b4869ffl, l); result = 1; } l = mrand48 (); if (l != 0x5cd4cc3el) { printf ("mrand48() in line %d failed: expected %lx, seen %lx\n", __LINE__ - 4, 0x5cd4cc3el, l); result = 1; } /* Check whether srand48() restores the A and C parameters. */ srand48 (0x98765432); /* See whether the correct values are installed. */ l = lrand48 (); if (l != 0x2fed1413l) { printf ("lrand48() in line %d failed: expected %lx, seen %lx\n", __LINE__ - 4, 0x2fed1413l, l); result = 1; } l = mrand48 (); if (l != 0xa28c1003l) { printf ("mrand48() in line %d failed: expected %lx, seen %lx\n", __LINE__ - 4, 0xa28c1003l, l); result = 1; } l = lrand48 (); if (l != 0x585fcfb7l) { printf ("lrand48() in line %d failed: expected %lx, seen %lx\n", __LINE__ - 4, 0x585fcfb7l, l); result = 1; } l = mrand48 (); if (l != 0x9e88f474l) { printf ("mrand48() in line %d failed: expected %lx, seen %lx\n", __LINE__ - 4, 0x9e88f474l, l); result = 1; } /* And again to see whether seed48() does the same. */ lcong48 (lxs); /* See whether lxs wasn't modified. */ l = lrand48 (); if (l != 0x6df63d66l) { printf ("lrand48() in line %d failed: expected %lx, seen %lx\n", __LINE__ - 4, 0x6df63d66l, l); result = 1; } /* Test seed48. The previous call should have install the values in the initialization of `xs' above. */ xs[0] = 0x1234; xs[1] = 0x5678; xs[2] = 0x9012; xsp = seed48 (xs); if (xsp[0] != 0x0637 || xsp[1] != 0x7acd || xsp[2] != 0xdbec) { puts ("seed48() did not install the values correctly"); printf (" expected: { %04hx, %04hx, %04hx }\n", 0x0637, 0x7acd, 0xdbec); printf (" seen: { %04hx, %04hx, %04hx }\n", xsp[0], xsp[1], xsp[2]); result = 1; } /* Test lrand48 and mrand48. We continue from the seed established above. */ l = lrand48 (); if (l != 0x017e48b5l) { printf ("lrand48() in line %d failed: expected %lx, seen %lx\n", __LINE__ - 4, 0x017e48b5l, l); result = 1; } l = mrand48 (); if (l != 0xeb7a1fa3l) { printf ("mrand48() in line %d failed: expected %lx, seen %lx\n", __LINE__ - 4, 0xeb7a1fa3l, l); result = 1; } l = lrand48 (); if (l != 0x6b6a3f95l) { printf ("lrand48() in line %d failed: expected %lx, seen %lx\n", __LINE__ - 4, 0x6b6a3f95l, l); result = 1; } l = mrand48 (); if (l != 0x175c0d6fl) { printf ("mrand48() in line %d failed: expected %lx, seen %lx\n", __LINE__ - 4, 0x175c0d6fl, l); result = 1; } /* Test drand48. */ d = drand48 (); if (d != 0.0908832261858485424) { printf ("drand48() in line %d failed: expected %.*g, seen %.*g\n", __LINE__ - 4, DECIMAL_DIG, 0.0908832261858485424, DECIMAL_DIG, d); result = 1; } d = drand48 (); if (d != 0.943149381730059133133) { printf ("drand48() in line %d failed: expected %.*g, seen %.*g\n", __LINE__ - 4, DECIMAL_DIG, 0.943149381730059133133, DECIMAL_DIG, d); result = 1; } /* Now the functions which get the Xis passed. */ xs[0] = 0x3849; xs[1] = 0x5061; xs[2] = 0x7283; l = nrand48 (xs); if (l != 0x1efe61a1l) { printf ("nrand48() in line %d failed: expected %lx, seen %lx\n", __LINE__ - 4, 0x1efe61a1l, l); result = 1; } l = jrand48 (xs); if (l != 0xf568c7a0l) { printf ("jrand48() in line %d failed: expected %lx, seen %lx\n", __LINE__ - 4, 0xf568c7a0l, l); result = 1; } l = nrand48 (xs); if (l != 0x2a5e57fel) { printf ("nrand48() in line %d failed: expected %lx, seen %lx\n", __LINE__ - 4, 0x2a5e57fel, l); result = 1; } l = jrand48 (xs); if (l != 0x71a779a8l) { printf ("jrand48() in line %d failed: expected %lx, seen %lx\n", __LINE__ - 4, 0x71a779a8l, l); result = 1; } /* Test whether the global A and C are used. */ lcong48 (lxs); l = nrand48 (xs); if (l != 0x32beee9fl) { printf ("nrand48() in line %d failed: expected %lx, seen %lx\n", __LINE__ - 4, 0x32beee9fl, l); result = 1; } l = jrand48 (xs); if (l != 0x7bddf3bal) { printf ("jrand48() in line %d failed: expected %lx, seen %lx\n", __LINE__ - 4, 0x7bddf3bal, l); result = 1; } l = nrand48 (xs); if (l != 0x85bdf28l) { printf ("nrand48() in line %d failed: expected %lx, seen %lx\n", __LINE__ - 4, 0x85bdf28l, l); result = 1; } l = jrand48 (xs); if (l != 0x7b433e47l) { printf ("jrand48() in line %d failed: expected %lx, seen %lx\n", __LINE__ - 4, 0x7b433e47l, l); result = 1; } /* Test erand48. Also compare with the drand48 results. */ (void) seed48 (xs); d = drand48 (); e = erand48 (xs); if (d != e) { printf ("\ drand48() and erand48 in lines %d and %d produce different results\n", __LINE__ - 6, __LINE__ - 5); printf (" drand48() = %g, erand48() = %g\n", d, e); result = 1; } else if (e != 0.640650904452755298735) { printf ("erand48() in line %d failed: expected %.*g, seen %.*g\n", __LINE__ - 4, DECIMAL_DIG, 0.640650904452755298735, DECIMAL_DIG, e); result = 1; } d = drand48 (); e = erand48 (xs); if (d != e) { printf ("\ drand48() and erand48 in lines %d and %d produce different results\n", __LINE__ - 6, __LINE__ - 5); printf (" drand48() = %g, erand48() = %g\n", d, e); result = 1; } else if (e != 0.115372323508150742555) { printf ("erand48() in line %d failed: expected %.*g, seen %.*g\n", __LINE__ - 4, DECIMAL_DIG, 0.0115372323508150742555, DECIMAL_DIG, e); result = 1; } return result; }
/* -- mlp_forback -------------------------------------------------------- */ int mlp_forback( float *stims, int *stimstarts, int ndim, int negs, int *stimoffs, int nin, int *nunits, int nlevels, int *tranfns, float *activs, float *biases, int ntunits, float *weights, int nweights, float *bschange, float *wtchange, float *etas, float *etbs, float alpha, float decay, float *targs, int *targstarts, int *targoffs, int nout, int niter, int nbatch, int ransel, float *err, float *errvar) /* Carries out niter learning cycles on the machine, selecting stimuli at random from the stims and targs arrays if RANSEL is non-zero, otherwise taking them in sequence. Other parameters are as in bprop, fprop and mlp_forward, with targs etc. instead of outs etc. If nbatch is 1, then does continuous learning with momentum governed by alpha. If nbatch is greater than 1, then does batch learning, averaging errors over nbatch examples before updating. In this case, alpha is ignored. - one special case - if niter is 0, just do a single backward pass, assuming that the forward pass has already been carried out. On return activs is set to the latest error signals, and an explicit call of fprop is needed to get activations. Err returns the mean error, errvar its variance. Returns fail code. */ { float anegs = negs, cerr, errsum = 0.0, errsumsqu = 0.0; int iter, eg = -1, dofwd = niter > 0, batching = nbatch > 1, si, so; /* check inputs to avoid having to do so on each iteration */ int ifail = checkns(nunits,nlevels,nin,nout,ntunits,nweights); if (ifail) return ifail; if (nbatch <= 0) return 10; /* When batching, niter is given as number of batches - change to no of egs and ensure weight change arrays are zeroed */ if (batching) { niter *= nbatch; mlp_fillvec(0.0, wtchange, nweights); mlp_fillvec(0.0, bschange, ntunits); } if (niter == 0) niter = 1; /* Always do a backward pass */ /* Iterate */ for (iter = 1; iter <= niter; iter++) { if (ndim) { /* stimstarts is n-D array giving limits */ si = mlp_getsample(ndim, stimstarts, ransel); so = mlp_getoutsample(ndim, stimstarts, targstarts); } else { /* stimstarts 1-D array of starting points */ if (ransel) eg = (int)(erand48(seed) * anegs); else eg = (eg+1) % negs; si = *(stimstarts+eg); so = *(targstarts+eg); } if (dofwd) fprop(stims+si, stimoffs,nin,nunits,nlevels,tranfns,activs, biases,ntunits,weights,nweights); if (batching) { cerr = bprop_batch(stims+si, stimoffs, nin, nunits, nlevels, tranfns, activs, ntunits, weights, nweights, wtchange, bschange, targs+so, targoffs, nout); if (iter % nbatch == 0) bwtupd_batch(biases, ntunits, weights, nweights, wtchange, bschange, etas, etbs, decay, nbatch); } else cerr = bprop(stims+si, stimoffs, nin, nunits, nlevels, tranfns, activs, biases, ntunits, weights, nweights, wtchange, bschange, etas, etbs, alpha, decay, targs+so, targoffs, nout); errsum += cerr; errsumsqu += cerr * cerr; } /* Calculate the error and its variance over this set of trials. It's divided by 2 because bprop returns a sum of squares, but actually uses the derivative with respect to half the sum of squares. */ *err = errsum/(2*niter); *errvar = errsumsqu/(4*niter) - *err * *err; return 0; }
void mlp_randomvec(float *arr, int n, float x0, float x1) { float *arrend = arr+n, x1mx0 = x1-x0; while (arr < arrend) *arr++ = x0 + x1mx0 * erand48(seed); }