int main (int argc, char *argv[]) { /*! structure to store all simulation parameters */ Config mcxconfig; /** mcxconfig: structure to store all simulation parameters */ GPUInfo *gpuinfo=NULL; /** gpuinfo: structure to store GPU information */ unsigned int activedev=0; /** activedev: count of total active GPUs to be used */ /** To start an MCX simulation, we first create a simulation configuration and set all elements to its default settings. */ mcx_initcfg(&mcxconfig); /** Then, we parse the full command line parameters and set user specified settings */ mcx_parsecmd(argc,argv,&mcxconfig); /** The next step, we identify gpu number and query all GPU info */ if(!(activedev=mcx_list_gpu(&mcxconfig,&gpuinfo))){ mcx_error(-1,"No GPU device found\n",__FILE__,__LINE__); } #ifdef _OPENMP /** Now we are ready to launch one thread for each involked GPU to run the simulation */ omp_set_num_threads(activedev); #pragma omp parallel { #endif /** This line runs the main MCX simulation for each GPU inside each thread */ mcx_run_simulation(&mcxconfig,gpuinfo); #ifdef _OPENMP } #endif /** Once simulation is complete, we clean up the allocated memory in config and gpuinfo, and exit */ mcx_cleargpuinfo(&gpuinfo); mcx_clearcfg(&mcxconfig); return 0; }
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]){ Config cfg; GPUInfo *gpuinfo=NULL; mxArray *tmp; int ifield, jstruct; int ncfg, nfields; int fielddim[4]; int activedev=0; int errorflag=0; int threadid=0; const char *outputtag[]={"data"}; const char *datastruct[]={"data","stat"}; const char *statstruct[]={"runtime","nphoton","energytot","energyabs","normalizer","workload"}; const char *gpuinfotag[]={"name","id","devcount","major","minor","globalmem", "constmem","sharedmem","regcount","clock","sm","core", "autoblock","autothread","maxgate"}; if (nrhs==0){ mcxlab_usage(); return; } if(nrhs==1 && mxIsChar(prhs[0])){ char shortcmd[MAX_SESSION_LENGTH]; mxGetString(prhs[0], shortcmd, MAX_SESSION_LENGTH); shortcmd[MAX_SESSION_LENGTH-1]='\0'; if(strcmp(shortcmd,"gpuinfo")==0){ mcx_initcfg(&cfg); cfg.isgpuinfo=3; if(!(activedev=mcx_list_gpu(&cfg,&gpuinfo))){ mexWarnMsgTxt("no active GPU device found"); } plhs[0] = mxCreateStructMatrix(gpuinfo[0].devcount,1,15,gpuinfotag); for(int i=0;i<gpuinfo[0].devcount;i++){ mxSetField(plhs[0],i,"name",mxCreateString(gpuinfo[i].name)); SET_GPU_INFO(plhs[0],i,id); SET_GPU_INFO(plhs[0],i,devcount); SET_GPU_INFO(plhs[0],i,major); SET_GPU_INFO(plhs[0],i,minor); SET_GPU_INFO(plhs[0],i,globalmem); SET_GPU_INFO(plhs[0],i,constmem); SET_GPU_INFO(plhs[0],i,sharedmem); SET_GPU_INFO(plhs[0],i,regcount); SET_GPU_INFO(plhs[0],i,clock); SET_GPU_INFO(plhs[0],i,sm); SET_GPU_INFO(plhs[0],i,core); SET_GPU_INFO(plhs[0],i,autoblock); SET_GPU_INFO(plhs[0],i,autothread); SET_GPU_INFO(plhs[0],i,maxgate); } mcx_cleargpuinfo(&gpuinfo); mcx_clearcfg(&cfg); } return; } printf("Launching MCXLAB - Monte Carlo eXtreme for MATLAB & GNU Octave ...\n"); if (!mxIsStruct(prhs[0])) mexErrMsgTxt("Input must be a structure."); nfields = mxGetNumberOfFields(prhs[0]); ncfg = mxGetNumberOfElements(prhs[0]); if(nlhs>=1) plhs[0] = mxCreateStructMatrix(ncfg,1,2,datastruct); if(nlhs>=2) plhs[1] = mxCreateStructMatrix(ncfg,1,1,outputtag); if(nlhs>=3) plhs[2] = mxCreateStructMatrix(ncfg,1,1,outputtag); if(nlhs>=4) plhs[3] = mxCreateStructMatrix(ncfg,1,1,outputtag); if(nlhs>=5) plhs[4] = mxCreateStructMatrix(ncfg,1,1,outputtag); for (jstruct = 0; jstruct < ncfg; jstruct++) { /* how many configs */ try{ printf("Running simulations for configuration #%d ...\n", jstruct+1); mcx_initcfg(&cfg); for (ifield = 0; ifield < nfields; ifield++) { /* how many input struct fields */ tmp = mxGetFieldByNumber(prhs[0], jstruct, ifield); if (tmp == NULL) { continue; } mcx_set_field(prhs[0],tmp,ifield,&cfg); } #ifndef MATLAB_MEX_FILE mexEvalString("fflush(stdout);"); #else mexEvalString("drawnow;"); #endif cfg.issave2pt=(nlhs>=1); cfg.issavedet=(nlhs>=2); cfg.issaveseed=(nlhs>=4); #if defined(USE_MT_RAND) cfg.issaveseed=0; #endif if(cfg.vol==NULL || cfg.medianum==0){ mexErrMsgTxt("You must define 'vol' and 'prop' field."); } if(!(activedev=mcx_list_gpu(&cfg,&gpuinfo))){ mexErrMsgTxt("No active GPU device found"); } if(nlhs>=1){ int fieldlen=cfg.dim.x*cfg.dim.y*cfg.dim.z*(int)((cfg.tend-cfg.tstart)/cfg.tstep+0.5); cfg.exportfield = (float*)calloc(fieldlen,sizeof(float)); } if(nlhs>=2){ cfg.exportdetected=(float*)malloc((cfg.medianum+1)*cfg.maxdetphoton*sizeof(float)); } if(nlhs>=4){ cfg.seeddata=malloc(cfg.maxdetphoton*sizeof(float)*RAND_BUF_LEN); } if(nlhs>=5){ cfg.exportdebugdata=(float*)malloc(cfg.maxjumpdebug*sizeof(float)*MCX_DEBUG_REC_LEN); } mcx_validate_config(&cfg); #ifdef _OPENMP omp_set_num_threads(activedev); #pragma omp parallel shared(errorflag) { threadid=omp_get_thread_num(); #endif try{ mcx_run_simulation(&cfg,gpuinfo); }catch(const char *err){ mexPrintf("Error from thread (%d): %s\n",threadid,err); errorflag++; }catch(const std::exception &err){ mexPrintf("C++ Error from thread (%d): %s\n",threadid,err.what()); errorflag++; }catch(...){ mexPrintf("Unknown Exception from thread (%d)",threadid); errorflag++; } #ifdef _OPENMP } #endif if(errorflag) mexErrMsgTxt("MCXLAB Terminated due to an exception!"); if(nlhs>=5){ fielddim[0]=MCX_DEBUG_REC_LEN; fielddim[1]=cfg.debugdatalen; // his.savedphoton is for one repetition, should correct fielddim[2]=0; fielddim[3]=0; mxSetFieldByNumber(plhs[4],jstruct,0, mxCreateNumericArray(2,fielddim,mxSINGLE_CLASS,mxREAL)); if(cfg.debuglevel & MCX_DEBUG_MOVE) memcpy((float*)mxGetPr(mxGetFieldByNumber(plhs[4],jstruct,0)),cfg.exportdebugdata,fielddim[0]*fielddim[1]*sizeof(float)); if(cfg.exportdebugdata) free(cfg.exportdebugdata); cfg.exportdebugdata=NULL; } if(nlhs>=4){ fielddim[0]=(cfg.issaveseed>0)*RAND_BUF_LEN*sizeof(float); fielddim[1]=cfg.detectedcount; // his.savedphoton is for one repetition, should correct fielddim[2]=0; fielddim[3]=0; mxSetFieldByNumber(plhs[3],jstruct,0, mxCreateNumericArray(2,fielddim,mxUINT8_CLASS,mxREAL)); memcpy((unsigned char*)mxGetPr(mxGetFieldByNumber(plhs[3],jstruct,0)),cfg.seeddata,fielddim[0]*fielddim[1]); free(cfg.seeddata); cfg.seeddata=NULL; } if(nlhs>=3){ fielddim[0]=cfg.dim.x; fielddim[1]=cfg.dim.y; fielddim[2]=cfg.dim.z; fielddim[3]=0; if(cfg.vol){ mxSetFieldByNumber(plhs[2],jstruct,0, mxCreateNumericArray(3,fielddim,mxUINT8_CLASS,mxREAL)); memcpy((unsigned char*)mxGetPr(mxGetFieldByNumber(plhs[2],jstruct,0)),cfg.vol, fielddim[0]*fielddim[1]*fielddim[2]*sizeof(unsigned char)); } } if(nlhs>=2){ fielddim[0]=(cfg.medianum+1); fielddim[1]=cfg.detectedcount; fielddim[2]=0; fielddim[3]=0; if(cfg.detectedcount>0){ mxSetFieldByNumber(plhs[1],jstruct,0, mxCreateNumericArray(2,fielddim,mxSINGLE_CLASS,mxREAL)); memcpy((float*)mxGetPr(mxGetFieldByNumber(plhs[1],jstruct,0)),cfg.exportdetected, fielddim[0]*fielddim[1]*sizeof(float)); } free(cfg.exportdetected); cfg.exportdetected=NULL; } if(nlhs>=1){ fielddim[0]=cfg.dim.x; fielddim[1]=cfg.dim.y; fielddim[2]=cfg.dim.z; fielddim[3]=(int)((cfg.tend-cfg.tstart)/cfg.tstep+0.5); mxSetFieldByNumber(plhs[0],jstruct,0, mxCreateNumericArray(4,fielddim,mxSINGLE_CLASS,mxREAL)); memcpy((float*)mxGetPr(mxGetFieldByNumber(plhs[0],jstruct,0)),cfg.exportfield, fielddim[0]*fielddim[1]*fielddim[2]*fielddim[3]*sizeof(float)); free(cfg.exportfield); cfg.exportfield=NULL; mxArray *stat=mxCreateStructMatrix(1,1,6,statstruct); mxArray *val = mxCreateDoubleMatrix(1,1,mxREAL); *mxGetPr(val) = cfg.runtime; mxSetFieldByNumber(stat,0,0, val); val = mxCreateDoubleMatrix(1,1,mxREAL); *mxGetPr(val) = cfg.nphoton; mxSetFieldByNumber(stat,0,1, val); val = mxCreateDoubleMatrix(1,1,mxREAL); *mxGetPr(val) = cfg.energytot; mxSetFieldByNumber(stat,0,2, val); val = mxCreateDoubleMatrix(1,1,mxREAL); *mxGetPr(val) = cfg.energyabs; mxSetFieldByNumber(stat,0,3, val); val = mxCreateDoubleMatrix(1,1,mxREAL); *mxGetPr(val) = cfg.normalizer; mxSetFieldByNumber(stat,0,4, val); val = mxCreateDoubleMatrix(1,activedev,mxREAL); for(int i=0;i<activedev;i++) *(mxGetPr(val)+i) = cfg.workload[i]; mxSetFieldByNumber(stat,0,5, val); mxSetFieldByNumber(plhs[0],jstruct,1, stat); } }catch(const char *err){ mexPrintf("Error: %s\n",err); }catch(const std::exception &err){ mexPrintf("C++ Error: %s\n",err.what()); }catch(...){ mexPrintf("Unknown Exception"); } if(detps) free(detps); mcx_cleargpuinfo(&gpuinfo); mcx_clearcfg(&cfg); } return; }