Function cimba_run
Defined in File cimba.h
Function Documentation
-
uint64_t cimba_run(void *your_experiment_array, uint64_t num_trials, size_t trial_struct_size, cimba_trial_func *your_trial_func)
The main simulation function, executing a user-defined experiment consisting of several trials in parallel.
The experiment is an array of your trial structs, containing any combination of parameter variations and replications that you need. The trial struct stores the parameters going into each trial and the results coming from it.
The run will call your trial function once for each member of your array, executing in parallel on as many CPU cores as the computer has available. It also needs to know the number of trials in your experiment and the size of your trial struct to do the necessary pointer calculations.
Your trial function is responsible for setting up the simulation from parameters given in the trial struct, starting it (typically by calling
cmb_event_queue_execute(), collecting the results, and storing them back to the trial struct. Note that no end time is given as an argument here. You need to determine the appropriate closing time and schedule an event for that inside your simulation. Seetest/test_cimba.cfor an example.Your trial function is also responsible for managing the seeds used by any pseudo-random number generators. The generators should be initialized with a seed at the start of each trial. If you just want independent trials with no need for reproducibility, call
cmb_random_hwseed()to get one based on hardware entropy. It will provide each trial with a unique, truly random seed.If you need both randomness and reproducibility, call
cmb_random_hwseed()once in your main program to get a master seed, usecmb_random_splitmix64()with that master seed and a running trial counter to get a unique and reproducible seed for each trial, store this trial seed in your trial struct, and then let the trial function use this pre-calculated and stored seed to initialize the PRNG’s for that trial.The recommended seed generation approach is along these lines:
and then, in your trial function, given the pointeruint64_t master_seed = cmb_random_hwseed(); struct trial *experiment = calloc(num_trials, sizeof(*experiment)); for (unsigned trl_idx = 0u; trl_idx < num_trials; trl_idx++) { experiment[trl_idx].seed = cmb_random_fmix64(master_seed, trl_idx); }
trlto one specificstruct trialto run in your experiment array:Seecmb_random_initialize(trl->seed);
test/test_cimba.cfor one example of this, combined with optional command line arguments for an externally provided master seed.When
cimba_run_experiment()returns, the results fields of the trial structs that constitute your experiment array will be filled in.In some cases, different trial functions may be needed for individual trials of the experiment. To run multiple trial functions in parallel, set the
your_trial_funcargument toNULLand store the trial function to use as the first member of each trial struct in the experiment. That way, you can run different simulations for each trial in your experiment if required.It is also possible to (ab)use
cimba_run_experiment()to parallelize other functions than Cimba simulations. The trial function can be any function that matches the patternvoid func(void *arg), effectively usingcimba_run_experiment()as a user-friendly pthreads wrapper to parallelize any CPU-bound function with limited input and output requirements.- Parameters:
your_experiment_array – Your user-defined array of trials to be run.
num_trials – The number of trials in the array.
trial_struct_size – The size of your trial struct in bytes.
your_trial_func – Pointer to the trial function to be executed. If NULL, the first member of each trial struct will be assumed to be a pointer to the trial function to be executed for that particular trial.
- Returns:
Number of failed trials terminated by cmb_logger_error, if any. Return value zero indicates success, no trials failed.