int main(int argc, char *argv[]) { int code = 0, i, j, n, initialruns, scheduledjobs,eig=0; powerbag **ppbag = NULL, *pbag; double *matcopy = NULL, *scratch = NULL; double scale = 1.0; int quantity = 1, numworkers = 1, theworker; char gotone; pthread_t *pthethread1; pthread_mutex_t output; pthread_mutex_t *psynchro_array; //new variables int read_n; double* read_matrix; if(argc < 2){ printf(" usage: rpower filename [-s scale] [-q quantity] [-w workers] [-e eigenvalues]\n"); code = 1; goto BACK; } sigset(SIGINT, &handlesigint); for(j = 2; j < argc; j++){ if (0 == strcmp(argv[j],"-s")){ j += 1; scale = atof(argv[j]); } else if (0 == strcmp(argv[j],"-q")){ j += 1; quantity = atoi(argv[j]); } else if (0 == strcmp(argv[j],"-w")){ j += 1; numworkers = atoi(argv[j]); } else if (0 == strcmp(argv[j],"-e")){ j += 1; eig = atoi(argv[j]); } else{ printf("bad option %s\n", argv[j]); code = 1; goto BACK; } } printf("will use scale %g and quantity %d: %d workers\n", scale, quantity, numworkers); if( numworkers > quantity ){ numworkers = quantity; printf(" --> reset workers to %d\n", numworkers); } deadstatus = (char *) calloc(numworkers, sizeof(char)); pthread_mutex_init(&output, NULL); /** common to everybody **/ psynchro_array = (pthread_mutex_t *)calloc(numworkers, sizeof(pthread_mutex_t)); if(!psynchro_array){ printf("could not create mutex array\n"); code = NOMEMORY; goto BACK; } for(j = 0; j < numworkers; j++) pthread_mutex_init(&psynchro_array[j], NULL); ppbag = (powerbag **)calloc(numworkers, sizeof(powerbag *)); if(!ppbag){ printf("could not create bag array\n"); code = NOMEMORY; goto BACK; } numworkersproxy = numworkers; ppbagproxy = ppbag; pthethread1 = (pthread_t *)calloc(numworkers, sizeof(pthread_t)); if(!pthethread1){ printf("could not create thread array\n"); code = NOMEMORY; goto BACK; } //read code once if(code=PWRread(argv[1],&read_n,&read_matrix)) goto BACK; for(j = 0; j < numworkers; j++){ //if((code = PWRreadnload_new(argv[1], 0, ppbag + j))) // goto BACK; /** inefficient: we should read the data once, and then copy **/ PWRallocateNload(read_n,j,read_matrix, ppbag + j,eig); pbag = ppbag[j]; pbag->psynchro = &psynchro_array[j]; pbag->poutputmutex = &output; pbag->command = STANDBY; pbag->status = PREANYTHING; //pbag->ID = j; n = pbag->n; /** now, allocate an extra matrix and a vector to use in perturbation**/ /** should really do it in the power code since we are putting them in the bag **/ /*pbag->matcopy = (double *)calloc(n*n, sizeof(double)); pbag->scratch = (double *)calloc(n, sizeof(double)); if((!pbag->matcopy) || (!pbag->scratch)){ printf("no memory for matrices at %d\n", j); code = NOMEMORY; goto BACK; }*/ /** and copy matrix **/ for(i = 0; i < n*n; i++) pbag->matcopy[i] = pbag->matrix[i]; printf("about to launch thread for worker %d\n", j); pthread_create(&pthethread1[j], NULL, &PWR_wrapper, (void *) pbag); } initialruns = numworkers; if (initialruns > quantity) initialruns = quantity; for(theworker = 0; theworker < initialruns; theworker++){ pbag = ppbag[theworker]; /* if((code = cheap_rank1perturb(n, pbag->scratch, pbag->matcopy, pbag->matrix, scale))) goto BACK;*/ pthread_mutex_lock(&output); printf("*****master: worker %d will run experiment %d\n", theworker, j); pthread_mutex_unlock(&output); /** tell the worker to work **/ pthread_mutex_lock(&psynchro_array[theworker]); pbag->command = WORK; pbag->status = WORKING; pbag->jobnumber = theworker; pbag->itercount = 0; pthread_mutex_unlock(&psynchro_array[theworker]); } scheduledjobs = activeworkers = initialruns; while(activeworkers > 0){ /** check the workers' status **/ gotone = 0; for(theworker = 0; theworker < numworkers; theworker++){ pthread_mutex_lock(&psynchro_array[theworker]); pbag = ppbag[theworker]; if(pbag->status == DONEWITHWORK){ pthread_mutex_lock(&output); printf("master: worker %d is done with job %d\n", pbag->ID, pbag->jobnumber); printf(" top eigenvalue estimate: %.12e\n", pbag->topeigvalue); pthread_mutex_unlock(&output); if(scheduledjobs >= quantity){ /** tell worker to quit **/ pthread_mutex_lock(&output); printf("master: telling worker %d to quit\n", pbag->ID); pthread_mutex_unlock(&output); pbag->command = QUIT; pbag->status = QUIT; --activeworkers; } else { gotone = 1; } } else if(pbag->status == PREANYTHING){ pthread_mutex_lock(&output); printf("master: worker %d is available\n", theworker); pthread_mutex_unlock(&output); gotone = 1; } else if( (pbag->status == WORKING) && (pbag->itercount > 100000)){ pbag->command = INTERRUPT; pthread_mutex_lock(&output); printf("master: telling worker %d to interrupt\n", pbag->ID); pthread_mutex_unlock(&output); } else if(deadstatus[theworker]){ pthread_mutex_lock(&output); printf("master: telling worker %d to quit\n", pbag->ID); pthread_mutex_unlock(&output); pbag->command = QUIT; pbag->status = QUIT; --activeworkers; /** and let's make sure we don't do it again **/ deadstatus[theworker] = 0; } pthread_mutex_unlock(&psynchro_array[theworker]); if(gotone) break; usleep(10000); } /** at this point we have run through all workers **/ if(gotone){ /** if we are here, "theworker" can work **/ pbag = ppbag[theworker]; if((code = cheap_rank1perturb(n, pbag->scratch, pbag->matcopy, pbag->matrix, scale))) goto BACK; pthread_mutex_lock(&output); printf("master: worker %d will run experiment %d\n", theworker, scheduledjobs); pthread_mutex_unlock(&output); /** tell the worker to work **/ pthread_mutex_lock(&psynchro_array[theworker]); pbag->command = WORK; pbag->status = WORKING; pbag->itercount = 0; pbag->jobnumber = scheduledjobs; pthread_mutex_unlock(&psynchro_array[theworker]); ++scheduledjobs; } } /* pthread_mutex_lock(&psynchro_array[theworker]); pbag->command = QUIT; pthread_mutex_unlock(&psynchro_array[theworker]);*/ pthread_mutex_lock(&output); printf("master: done with loop\n"); pthread_mutex_unlock(&output); /** actually this is bad -- should wait for the threads to be done -- but how **/ for(j = 0; j < numworkers; j++){ pthread_join(pthethread1[j], NULL); pthread_mutex_lock(&output); printf("master: joined with thread %d\n", j); pthread_mutex_unlock(&output); pbag = ppbag[j]; PWRfreespace(&pbag); } free(ppbag); BACK: if(matcopy) free(matcopy); if(scratch) free(scratch); return code; }
void PWRpoweralg_new(powerbag *pbag) { int n, ID; double *vector, *newvector, *matrix; int k, waitcount, retcode; double error, tolerance,tempsum; char letsgo = 0, interrupting, forcedquit = 0; ID = pbag->ID; n = pbag->n; pthread_mutex_lock(pbag->poutputmutex); printf("ID %d starts\n", pbag->ID); pthread_mutex_unlock(pbag->poutputmutex); vector = pbag->vector; newvector = pbag->newvector; matrix = pbag->matrix; tolerance = 1e-20; /** excessive **/ /* if (tolerance < 1e-7) tolerance = 1e-7;*/ for(;;){ pthread_mutex_lock(pbag->poutputmutex); printf(" ID %d in big loop\n", pbag->ID); pthread_mutex_unlock(pbag->poutputmutex); letsgo = 0; waitcount = 0; while(letsgo == 0){ /** wait until WORK signal **/ usleep(10000); pthread_mutex_lock(pbag->psynchro); if(pbag->command == WORK){ letsgo = 1; } else if(pbag->command == QUIT) letsgo = 2; pthread_mutex_unlock(pbag->psynchro); if (letsgo == 2) goto DONE; if(0 == waitcount%20){ pthread_mutex_lock(pbag->poutputmutex); printf("ID %d bag %p: wait %d for signal; right now have %d\n", pbag->ID, (void *) pbag, waitcount, pbag->command); pthread_mutex_unlock(pbag->poutputmutex); } ++waitcount; } pthread_mutex_lock(pbag->poutputmutex); printf("ID %d: got signal to start working\n", pbag->ID); pthread_mutex_unlock(pbag->poutputmutex); /** let's do the perturbation here **/ if((retcode = cheap_rank1perturb(n, pbag->scratch, pbag->matcopy, pbag->matrix, 10.0))) goto DONE; /** initialize vector to random**/ for(k = 0; k < n; k++) pbag->W0[k] = rand()/((double) RAND_MAX); for(k = 0; k < n*n; k++) pbag->Qprime[k] = pbag->matrix[k]; //for each eigenvalue for(int i=0;i<pbag->eigvaluecount;i++){ tempsum=0; //assign vector to W0 for(int cnter = 0; cnter < n; cnter++) pbag->vector[cnter] = pbag->W0[cnter]; for(k = 0; ; k++){ /* PWRshowvector(n, vector);*/ PWRpoweriteration(ID, k, n, vector, newvector, matrix, &pbag->topeigvalue, &error, pbag->poutputmutex); if(error < tolerance){ pthread_mutex_lock(pbag->poutputmutex); printf(" ID %d converged to tolerance %g! on job %d at iteration %d\n", ID, tolerance, pbag->jobnumber, k); printf(" ID %d top eigenvalue %g!\n", ID, pbag->topeigvalue); pthread_mutex_unlock(pbag->poutputmutex); break; } pbag->itercount = k; /** well, in this case we don't really need k **/ if(0 == k%1000){ pthread_mutex_lock(pbag->psynchro); interrupting = 0; if(pbag->command == INTERRUPT || pbag->command == QUIT){ pthread_mutex_lock(pbag->poutputmutex); printf(" ID %d interrupting after %d iterations\n", pbag->ID, k); pthread_mutex_unlock(pbag->poutputmutex); interrupting = 1; } pthread_mutex_unlock(pbag->psynchro); if(interrupting) break; /** takes you outside of for loop **/ } } //end of for(k = 0; ; k++) for(int cnt1 = 0; cnt1 < n; cnt1++) for(int cnt2 = 0; cnt2 < n; cnt2++){ //Qprime creation pbag->matrix[cnt1*n + cnt2]+= - pbag->topeigvalue * pbag->vector[cnt1]*pbag->vector[cnt2]; } //w^T * W0 for(int cnt2 = 0; cnt2 < n; cnt2++) tempsum+=pbag->vector[cnt2] * pbag->W0[cnt2]; for(int cnt2 = 0; cnt2 < n; cnt2++) pbag->W0[cnt2] -= tempsum * pbag->vector[cnt2]; pbag->vectortopeigvalue[i] = pbag->topeigvalue; }//end of //for each eigenvalue /** first, let's check if we have been told to quit **/ pthread_mutex_lock(pbag->psynchro); if(pbag->command == QUIT) forcedquit = 1; pthread_mutex_unlock(pbag->psynchro); if(forcedquit) break; pthread_mutex_lock(pbag->psynchro); pbag->status = DONEWITHWORK; pbag->command = STANDBY; pthread_mutex_unlock(pbag->psynchro); } DONE: pthread_mutex_lock(pbag->poutputmutex); printf(" ID %d quitting\n", pbag->ID); pthread_mutex_unlock(pbag->poutputmutex); }
int main(int argc, char *argv[]) { int code = 0, i, j, n; powerbag *pbag = NULL; double *matcopy = NULL, *scratch = NULL; double scale = 1.0; int quantity = 1; pthread_t thethread1; if(argc < 2){ printf(" usage: rpower filename [-s scale] [-q quantity]\n"); code = 1; goto BACK; } for(j = 2; j < argc; j++){ if (0 == strcmp(argv[j],"-s")){ j += 1; scale = atof(argv[j]); } else if (0 == strcmp(argv[j],"-q")){ j += 1; quantity = atoi(argv[j]); } else{ printf("bad option %s\n", argv[j]); code = 1; goto BACK; } } printf("will use scale %g and quantity %d\n", scale, quantity); /* if((code = PWRreadnload(argv[1], &n, &vector, &newvector, &matrix))) goto BACK; */ if((code = PWRreadnload_new(argv[1], 0, &pbag))) goto BACK; n = pbag->n; /** now, allocate an extra matrix and a vector to use in perturbation **/ matcopy = (double *)calloc(n*n, sizeof(double)); scratch = (double *)calloc(n, sizeof(double)); if((!matcopy) || (!scratch)){ printf("no memory\n"); code = NOMEMORY; goto BACK; } /** and copy matrix **/ for(i = 0; i < n*n; i++) matcopy[i] = pbag->matrix[i]; printf("about to launch thread\n"); pbag->status = WORKING; /** is this right??? **/ if((code = cheap_rank1perturb(n, scratch, matcopy, pbag->matrix, scale))) goto BACK; pthread_create(&thethread1, NULL, &PWR_wrapper, (void *) pbag); /* PWR_wrapper((void *) pbag);*/ /* for(j = 0; j < quantity; j++){ printf("\n************Experiment %d\n", j); PWR_wrapper((void *) pbag); printf("top eigenvalue estimate: %.12e\n", pbag->topeigvalue); } */ for(;;){ if(pbag->status == WAITING){ printf("master: worker is done\n"); break; } } PWRfreespace(&pbag); BACK: if(matcopy) free(matcopy); if(scratch) free(scratch); return code; }