i've been trying make program in c multicore last few months, yet keep getting strange problem. maybe of can me out little?
the problem i'm having program gives proper results when let calculate using 1 thread. however, when choose more threads, values start changing, though calculations performed should same (aside of random number generator, shouldn't issue each core have own unique seeder , generator known work openmp multicore processing).
anyway, program kind of confidential, cannot give entire code (it's way large convenient use anyway) i'll try best give parts of code, may further explain problem.
first libraries included:
#include <stdio.h> #include <stdlib.h> #include <math.h> #include <string.h> #include <omp.h> /* openmp header */ #include <limits.h> #include <float.h> #include <gsl/gsl_rng.h> /*rng header*/ #include <gsl/gsl_randist.h> /*rng header*/
then define structures etc, know these work program work in single core mode. have main function, in openmp parallel loop looks this:
//perform multicore calculations (loop on photons) #pragma omp parallel default(none) \ num_threads(thread_cnt) \ private(icount,thread_id,i) \ shared(calc,imstr,sum_irefl,leaks) \ copyin(scat,cap,pcap_ini,profile,absmu,ctvar,lib) for(icount=0; icount <= cap.ndet; icount++){ thread_id = omp_get_thread_num(); printf("\nthread %d scat:\n",thread_id); for(i=0;i<ndim;i++) printf("%f\t",scat[i]); do{ do{ start(ctvar, absmu, profile, &pcap_ini, &cap, &icount, &imstr, &lib, calc, &thread_id); capil(ctvar, absmu, profile, &pcap_ini, &cap, &icount, &imstr, &lib, leaks, scat, calc, &thread_id); while (calc[thread_id].iesc == 0); /* perform capil until iesc not equal 0 anymore */ } while(calc[thread_id].iesc == -2); /* count etc if iesc!=-2, else redo start */ count(absmu, ctvar, &cap, &icount, profile, leaks, &imstr,calc, &thread_id); } while(calc[thread_id].iesc == -3); sum_irefl[thread_id] = sum_irefl[thread_id] + calc[thread_id].i_refl; if(icount%1000 == 0 && thread_id == 0) printf("%d\t%ld\t%f\n",icount,calc[0].i_refl, calc[0].rh[2]); }
in these subfunctions ( start, capil, count
) variables written new values, case calc,imstr,sum_irefl
, leaks
. set them shared, each thread can access them. however, don't believe there's chance memory race instance calc
split in array, each thread has own variables (accessed through unique thread_id
) , other shared variables may raced they're not read @ point. perhaps i'm misunderstanding dangers of memory races, don't think poses problem here...
the copyin
variables made threadsafe before (not shown here, compiler not complain, assume it's not problem) , they're read during parallel loop, again don't see problem be. furthermore, checked each variable @ start of parallel loop has values should have. it's somewhere during parallel section values obtained different when run program 1 or more cores.
i know not lot go on, hope of have idea nevertheless. if need more information, feel free ask me, might able supply more.
so things wonder: possible have harmful memory race after all? see else going wrong? know of (relatively) easy-to-use programs use check multicore program?
to expand on comment, code this. while thread dependent values still used in loop, don't have reinitialized every single pass through, @ least save overhead. i'm still not sure i'm seeing problem example though. of shared variables referenced thread_id? mention not read, how updated, perhaps summing or otherwise accumulating values in them?
#pragma omp parallel default(none) \ num_threads(thread_cnt) \ shared(calc,imstr,sum_irefl,leaks) \ copyin(scat,cap,pcap_ini,profile,absmu,ctvar,lib) { int icount, thread_id, i; //note, private definition in region thread_id = omp_get_thread_num(); printf("\nthread %d scat:\n",thread_id); //perform multicore calculations (loop on photons) #pragma omp for(icount=0; icount <= cap.ndet; icount++){ for(i=0;i<ndim;i++) printf("%f\t",scat[i]); do{ do{ start(ctvar, absmu, profile, &pcap_ini, &cap, &icount, &imstr, &lib, calc, &thread_id); capil(ctvar, absmu, profile, &pcap_ini, &cap, &icount, &imstr, &lib, leaks, scat, calc, &thread_id); while (calc[thread_id].iesc == 0); /* perform capil until iesc not equal 0 anymore */ } while(calc[thread_id].iesc == -2); /* count etc if iesc!=-2, else redo start */ count(absmu, ctvar, &cap, &icount, profile, leaks, &imstr,calc, &thread_id); } while(calc[thread_id].iesc == -3); sum_irefl[thread_id] = sum_irefl[thread_id] + calc[thread_id].i_refl; if(icount%1000 == 0 && thread_id == 0) printf("%d\t%ld\t%f\n",icount,calc[0].i_refl, calc[0].rh[2]); } }
Comments
Post a Comment