Skip to content

Commit

Permalink
[feat] allow mcxlab and pmcx to use cfg.flog to control log printing
Browse files Browse the repository at this point in the history
  • Loading branch information
fangq committed Aug 22, 2024
1 parent 17e347c commit 82fb8f1
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 11 deletions.
6 changes: 6 additions & 0 deletions mcxlab/mcxlab.m
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,12 @@
% 'M': return photon trajectory data as the 5th output
% 'P': show progress bar
% 'T': save photon trajectory data only, as the 1st output, disable flux/detp/seeds outputs
% cfg.flog: [2] log printing control; if set to a string, it defines a file path
% at which location the log will be printed in append mode; on Linux and Mac OS,
% one can use special paths such as /dev/null; if set to an integer,
% 2 (default): stderr
% 1: stdout
% 0: stdout but suppress printing MCX banner
% cfg.istrajstokes [0]: if set to 1, traj.iquv output contains the Stokes IQUV vector along trajectories
% cfg.maxjumpdebug: [10000000|int] when trajectory is requested in the output,
% use this parameter to set the maximum position stored. By default,
Expand Down
14 changes: 8 additions & 6 deletions src/mcx_core.cu
Original file line number Diff line number Diff line change
Expand Up @@ -2573,14 +2573,14 @@ int mcx_list_gpu(Config* cfg, GPUInfo** info) {
}

if (deviceCount == 0) {
MCX_FPRINTF(stderr, S_RED "ERROR: No CUDA-capable GPU device found\n" S_RESET);
MCX_FPRINTF(cfg->flog, S_RED "ERROR: No CUDA-capable GPU device found\n" S_RESET);
return 0;
}

*info = (GPUInfo*)calloc(deviceCount, sizeof(GPUInfo));

if (cfg->gpuid && cfg->gpuid > deviceCount) {
MCX_FPRINTF(stderr, S_RED "ERROR: Specified GPU ID is out of range\n" S_RESET);
MCX_FPRINTF(cfg->flog, S_RED "ERROR: Specified GPU ID is out of range\n" S_RESET);
return 0;
}

Expand Down Expand Up @@ -2614,7 +2614,7 @@ int mcx_list_gpu(Config* cfg, GPUInfo** info) {
(*info)[dev].autoblock = MAX((*info)[dev].maxmpthread / mcx_smxblock(dp.major, dp.minor), 64);

if ((*info)[dev].autoblock == 0) {
MCX_FPRINTF(stderr, S_RED "WARNING: maxThreadsPerMultiProcessor can not be detected\n" S_RESET);
MCX_FPRINTF(cfg->flog, S_RED "WARNING: maxThreadsPerMultiProcessor can not be detected\n" S_RESET);
(*info)[dev].autoblock = 64;
}

Expand Down Expand Up @@ -2944,7 +2944,7 @@ void mcx_run_simulation(Config* cfg, GPUInfo* gpu) {

/** Here we determine if the GPU memory of the current device can store all time gates, if not, disabling normalization */
if (totalgates > gpu[gpuid].maxgate && cfg->isnormalized) {
MCX_FPRINTF(stderr, S_RED "WARNING: GPU memory can not hold all time gates, disabling normalization to allow multiple runs\n" S_RESET);
MCX_FPRINTF(cfg->flog, S_RED "WARNING: GPU memory can not hold all time gates, disabling normalization to allow multiple runs\n" S_RESET);
cfg->isnormalized = 0;
}

Expand Down Expand Up @@ -3135,7 +3135,7 @@ void mcx_run_simulation(Config* cfg, GPUInfo* gpu) {
* Saving detected photon is enabled by default, but in case if a user disabled this feature, a warning is printed
*/
if (cfg->issavedet) {
MCX_FPRINTF(stderr, S_RED "WARNING: this MCX binary can not save partial path, please recompile mcx and make sure -D SAVE_DETECTORS is used by nvcc\n" S_RESET);
MCX_FPRINTF(cfg->flog, S_RED "WARNING: this MCX binary can not save partial path, please recompile mcx and make sure -D SAVE_DETECTORS is used by nvcc\n" S_RESET);
cfg->issavedet = 0;
}

Expand Down Expand Up @@ -3177,7 +3177,8 @@ void mcx_run_simulation(Config* cfg, GPUInfo* gpu) {
*/
tic = StartTimer();
#pragma omp master
{

if (cfg->printnum >= 0) {
mcx_printheader(cfg);

#ifdef MCX_TARGET_NAME
Expand All @@ -3190,6 +3191,7 @@ void mcx_run_simulation(Config* cfg, GPUInfo* gpu) {
MCX_FPRINTF(cfg->flog, "- compiled with: RNG [%s] with Seed Length [%d]\n", MCX_RNG_NAME, (int)((sizeof(RandType)*RAND_BUF_LEN) >> 2));
fflush(cfg->flog);
}

#pragma omp barrier

/**
Expand Down
4 changes: 3 additions & 1 deletion src/mcx_utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -5393,7 +5393,8 @@ int mcx_run_from_json(char* jsonstr) {
*/

void mcx_printheader(Config* cfg) {
MCX_FPRINTF(cfg->flog, S_MAGENTA"\
if (cfg->printnum >= 0 ) {
MCX_FPRINTF(cfg->flog, S_MAGENTA"\
###############################################################################\n\
# Monte Carlo eXtreme (MCX) -- CUDA #\n\
# Copyright (c) 2009-2024 Qianqian Fang <q.fang at neu.edu> #\n\
Expand All @@ -5412,6 +5413,7 @@ void mcx_printheader(Config* cfg) {
###############################################################################\n\
$Rev:: $" S_GREEN MCX_VERSION S_MAGENTA " $Date:: $ by $Author:: $\n\
###############################################################################\n" S_RESET);
}
}

/**
Expand Down
6 changes: 3 additions & 3 deletions src/mcx_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ typedef struct MCXConfig {

unsigned int maxgate; /**<simultaneous recording gates*/
int respin; /**<number of repeatitions (if positive), or number of divisions (if negative)*/
unsigned int printnum; /**<number of printed threads (for debugging)*/
int printnum; /**<number of printed threads (for debugging)*/
int gpuid; /**<the ID of the GPU to use, starting from 1, 0 for auto*/

unsigned int* vol; /**<pointer to the volume*/
Expand Down Expand Up @@ -347,9 +347,9 @@ void mcx_python_flush(void);

#if defined(MCX_CONTAINER) && (defined(MATLAB_MEX_FILE) || defined(OCTAVE_API_VERSION_NUMBER))
#ifdef _OPENMP
#define MCX_FPRINTF(fp,...) {if(omp_get_thread_num()==0) mexPrintf(__VA_ARGS__);} /**< macro to print messages, calls mexPrint if inside MATLAB */
#define MCX_FPRINTF(fp,...) {if(omp_get_thread_num()==0) {(fp==stderr) ? mexPrintf(__VA_ARGS__) : fprintf(fp,__VA_ARGS__);}} /**< macro to print messages, calls mexPrint if inside MATLAB */
#else
#define MCX_FPRINTF(fp,...) mexPrintf(__VA_ARGS__) /**< macro to print messages, calls mexPrint in MATLAB */
#define MCX_FPRINTF(fp,...) {(fp==stderr) ? mexPrintf(__VA_ARGS__) : fprintf(fp,__VA_ARGS__);} /**< macro to print messages, calls mexPrint in MATLAB */
#endif
#else
#define MCX_FPRINTF(fp,...) fprintf(fp,__VA_ARGS__) /**< macro to print messages, calls fprintf in command line mode */
Expand Down
24 changes: 24 additions & 0 deletions src/mcxlab.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1286,6 +1286,30 @@ void mcx_set_field(const mxArray* root, const mxArray* item, int idx, Config* cf
}

printf("mcx.workload=<<%ld>>;\n", arraydim[0]*arraydim[1]);
} else if (strcmp(name, "flog") == 0) {
int len = mxGetNumberOfElements(item);
char logfile[MAX_SESSION_LENGTH] = {'\0'};

if (mxIsChar(item)) {
if (len > 0) {
mxGetString(item, logfile, MAX_SESSION_LENGTH);
cfg->flog = fopen(logfile, "a+");

if (cfg->flog == NULL) {
mexErrMsgTxt("Log output file can not be written");
}
} else {
cfg->flog = stdout;
}
} else {
double* val = mxGetPr(item);

if (len > 0 && val[0] <= 2) {
cfg->flog = ((int)val[0] == 2 ? stderr : ((int)val[0] == 1 ? stdout : (cfg->printnum = -1, stdout)));
}
}

printf("mcx.flog=%d;\n", cfg->flog);
} else {
printf(S_RED "WARNING: redundant field '%s'\n" S_RESET, name);
}
Expand Down
23 changes: 22 additions & 1 deletion src/pmcx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,7 @@ void parseVolume(const py::dict& user_cfg, Config& mcx_config) {
void parse_config(const py::dict& user_cfg, Config& mcx_config) {
mcx_initcfg(&mcx_config);

mcx_config.flog = stdout;
mcx_config.flog = stderr;
GET_SCALAR_FIELD(user_cfg, mcx_config, nphoton, py::int_);
GET_SCALAR_FIELD(user_cfg, mcx_config, nblocksize, py::int_);
GET_SCALAR_FIELD(user_cfg, mcx_config, nthread, py::int_);
Expand Down Expand Up @@ -1003,6 +1003,27 @@ void parse_config(const py::dict& user_cfg, Config& mcx_config) {
}
}

if (user_cfg.contains("flog")) {
auto logfile_id_value = user_cfg["flog"];

if (py::int_::check_(logfile_id_value)) {
auto logid = py::int_(logfile_id_value);
mcx_config.flog = (logid >= 2 ? stderr : (logid == 1 ? stdout : (mcx_config.printnum = -1, stdout)));
} else if (py::str::check_(logfile_id_value)) {
std::string logfile_id_string_value = py::str(logfile_id_value);

if (logfile_id_string_value.empty()) {
throw py::value_error("the 'flog' field must be an integer or non-empty string");
}

mcx_config.flog = fopen(logfile_id_string_value.c_str(), "a+");

if (mcx_config.flog == NULL) {
throw py::value_error("Log output file can not be written");
}
}
}

// Output arguments parsing
GET_SCALAR_FIELD(user_cfg, mcx_config, issave2pt, py::bool_);
GET_SCALAR_FIELD(user_cfg, mcx_config, issavedet, py::bool_);
Expand Down

0 comments on commit 82fb8f1

Please sign in to comment.