diff --git a/README.md b/README.md index 28763df54..189cc2bf3 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ - + @@ -23,7 +23,7 @@ DHT: --dht ... enable dht (default is off) ---dht-log ... enable logarithm application before rounding (default is off) +--dht-nolog ... enable logarithm application before rounding (default is off) --dht-signif=<1-n> ... set rounding to number of significant digits (default 5) (only used if no vector is given in setup file) diff --git a/src/DHT/DHT.c b/src/DHT/DHT.c index 165953540..74f8b6220 100644 --- a/src/DHT/DHT.c +++ b/src/DHT/DHT.c @@ -1,10 +1,10 @@ #include "DHT.h" +#include #include #include #include #include -#include #include static void determine_dest(uint64_t hash, int comm_size, @@ -79,7 +79,7 @@ DHT *DHT_create(MPI_Comm comm, uint64_t size, unsigned int data_size, object->recv_entry = malloc(1 + data_size + key_size); object->send_entry = malloc(1 + data_size + key_size); object->index_count = 9 - (index_bytes / 8); - object->index = (uint64_t*)malloc((object->index_count) * sizeof(uint64_t)); + object->index = (uint64_t *)malloc((object->index_count) * sizeof(uint64_t)); object->mem_alloc = mem_alloc; // if set, initialize dht_stats @@ -375,8 +375,8 @@ int DHT_free(DHT *table, int *eviction_counter, int *readerror_counter) { return DHT_SUCCESS; } -#ifdef DHT_STATISTICS int DHT_print_statistics(DHT *table) { +#ifdef DHT_STATISTICS int *written_buckets; int *read_misses, sum_read_misses; int *evictions, sum_evictions; @@ -476,5 +476,5 @@ int DHT_print_statistics(DHT *table) { MPI_Barrier(table->communicator); return DHT_SUCCESS; +#endif } -#endif \ No newline at end of file diff --git a/src/DHT/DHT.h b/src/DHT/DHT.h index 4eff08179..6fed3a79b 100644 --- a/src/DHT/DHT.h +++ b/src/DHT/DHT.h @@ -250,9 +250,7 @@ extern int DHT_free(DHT* table, int* eviction_counter, int* readerror_counter); * @return int Returns DHT_SUCCESS on success or DHT_MPI_ERROR on internal MPI * error. */ -#ifdef DHT_STATISTICS extern int DHT_print_statistics(DHT* table); -#endif /** * @brief Determine destination rank and index. diff --git a/src/DHT/DHT_Wrapper.cpp b/src/DHT/DHT_Wrapper.cpp index 468d913d4..e71caa679 100644 --- a/src/DHT/DHT_Wrapper.cpp +++ b/src/DHT/DHT_Wrapper.cpp @@ -26,20 +26,22 @@ uint64_t poet::get_md5(int key_size, void *key) { return retval; } -DHT_Wrapper::DHT_Wrapper(t_simparams *params, MPI_Comm dht_comm, +DHT_Wrapper::DHT_Wrapper(SimParams ¶ms, MPI_Comm dht_comm, int buckets_per_process, int data_size, int key_size) { // initialize DHT object dht_object = - DHT_create(dht_comm, buckets_per_process, data_size, key_size, &poet::get_md5); - + DHT_create(dht_comm, buckets_per_process, data_size, key_size, &get_md5); // allocate memory for fuzzing buffer fuzzing_buffer = (double *)malloc(key_size); // extract needed values from sim_param struct - this->dt_differ = params->dt_differ; - this->dht_log = params->dht_log; - this->dht_signif_vector = params->dht_signif_vector; - this->dht_prop_type_vector = params->dht_prop_type_vector; + t_simparams tmp = params.getNumParams(); + + this->dt_differ = tmp.dt_differ; + this->dht_log = tmp.dht_log; + + this->dht_signif_vector = params.getDHTSignifVector(); + this->dht_prop_type_vector = params.getDHTPropTypeVector(); } DHT_Wrapper::~DHT_Wrapper() { @@ -139,9 +141,7 @@ int DHT_Wrapper::fileToTable(const char *filename) { void DHT_Wrapper::printStatistics() { int res; -#ifdef DHT_STATISTICS res = DHT_print_statistics(dht_object); -#endif if (res != DHT_SUCCESS) { // MPI ERROR ... WHAT TO DO NOW? @@ -209,4 +209,4 @@ void DHT_Wrapper::fuzzForDHT(int var_count, void *key, double dt) { // if timestep differs over iterations set current current time step at the // end of fuzzing buffer if (dt_differ) fuzzing_buffer[var_count] = dt; -} \ No newline at end of file +} diff --git a/src/DHT/DHT_Wrapper.h b/src/DHT/DHT_Wrapper.h index c1d0edd88..2612e8e3c 100644 --- a/src/DHT/DHT_Wrapper.h +++ b/src/DHT/DHT_Wrapper.h @@ -51,14 +51,14 @@ class DHT_Wrapper { * calling DHT_create with all given parameters. Also the fuzzing buffer will * be allocated and all needed parameters extracted from simparams struct. * - * @param params Simulation parameter struct returned at initialization + * @param params Simulation parameter object * @param dht_comm Communicator which addresses all participating DHT * processes * @param buckets_per_process Count of buckets to allocate for each process * @param data_size Size of data in bytes * @param key_size Size of key in bytes */ - DHT_Wrapper(t_simparams *params, MPI_Comm dht_comm, int buckets_per_process, + DHT_Wrapper(SimParams ¶ms, MPI_Comm dht_comm, int buckets_per_process, int data_size, int key_size); /** * @brief Destroy the dht wrapper object @@ -82,7 +82,8 @@ class DHT_Wrapper { * marked with false ('not to be simulated'). * * @param length Count of grid cells inside work package - * @param[out] out_result_index Indexing work packages which should be simulated + * @param[out] out_result_index Indexing work packages which should be + * simulated * @param[in,out] work_package Pointer to current work package * @param dt Current timestep of simulation */ diff --git a/src/kin.cpp b/src/kin.cpp index 91ca04bfd..367b01f60 100644 --- a/src/kin.cpp +++ b/src/kin.cpp @@ -10,7 +10,6 @@ // BSD-licenced #include "dht_wrapper.h" #include "global_buffer.h" #include #include -#include #include #include #include @@ -85,11 +84,10 @@ int main(int argc, char *argv[]) { double cummul_chemistry = 0.f; double cummul_master_seq = 0.f; - argh::parser cmdl(argv); - int dht_significant_digits; + // argh::parser cmdl(argv); + // int dht_significant_digits; // cout << "CPP: Start Init (MPI)" << endl; - t_simparams params; int world_size, world_rank; MPI_Init(&argc, &argv); @@ -190,8 +188,8 @@ int main(int argc, char *argv[]) { "source('parallel_r_library.R');"; R.parseEvalQ(r_load_dependencies); - Parser parser(argv, world_rank, world_size); - int pret = parser.parseCmdl(); + SimParams parser(world_rank, world_size); + int pret = parser.parseFromCmdl(argv, R); if (pret == PARSER_ERROR) { MPI_Finalize(); @@ -201,8 +199,8 @@ int main(int argc, char *argv[]) { return EXIT_SUCCESS; } - parser.parseR(R); - params = parser.getParams(); + // parser.parseR(R); + // params = parser.getParams(); // if (params.world_rank == 0) { // cout << "CPP: Complete results storage is " << (params.store_result ? @@ -233,6 +231,7 @@ int main(int argc, char *argv[]) { // "source(filesim)"); // eval the init string, ignoring any returns // only rank 0 initializes goes through the whole initialization + bool dt_differ; if (world_rank == 0) { // cmdl(2) >> params.out_dir; // <- second positional argument // R["fileout"] = @@ -248,13 +247,17 @@ int main(int argc, char *argv[]) { std::string master_init_code = "mysetup <- master_init(setup=setup)"; R.parseEval(master_init_code); - params.dt_differ = R.parseEval("mysetup$dt_differ"); - MPI_Bcast(&(params.dt_differ), 1, MPI_C_BOOL, 0, MPI_COMM_WORLD); + dt_differ = R.parseEval("mysetup$dt_differ"); + MPI_Bcast(&dt_differ, 1, MPI_C_BOOL, 0, MPI_COMM_WORLD); } else { // workers will only read the setup DataFrame defined by input file R.parseEval("mysetup <- setup"); - MPI_Bcast(&(params.dt_differ), 1, MPI_C_BOOL, 0, MPI_COMM_WORLD); + MPI_Bcast(&dt_differ, 1, MPI_C_BOOL, 0, MPI_COMM_WORLD); } + parser.setDtDiffer(dt_differ); + + t_simparams params = parser.getNumParams(); + if (world_rank == 0) { cout << "CPP: R init done on process with rank " << params.world_rank << endl; @@ -267,6 +270,8 @@ int main(int argc, char *argv[]) { Grid grid(R); // params.grid = &grid; grid.init(); + + parser.initVectorParams(R, grid.getCols()); /* Retrieve state_C from R context for MPI buffer generation */ // Rcpp::DataFrame state_C = R.parseEval("mysetup$state_C"); @@ -296,78 +301,79 @@ int main(int argc, char *argv[]) { // params.R = &R; - if (params.dht_enabled) { - // cout << "\nCreating DHT\n"; - // determine size of dht entries - // int dht_data_size = grid.getCols() * sizeof(double); - // int dht_key_size = - // grid.getCols() * sizeof(double) + (params.dt_differ * - // sizeof(double)); + // if (params.dht_enabled) { + // // cout << "\nCreating DHT\n"; + // // determine size of dht entries + // // int dht_data_size = grid.getCols() * sizeof(double); + // // int dht_key_size = + // // grid.getCols() * sizeof(double) + (params.dt_differ * + // // sizeof(double)); - // // // determine bucket count for preset memory usage - // // // bucket size is key + value + 1 byte for status - // int dht_buckets_per_process = - // params.dht_size_per_process / (1 + dht_data_size + dht_key_size); + // // // // determine bucket count for preset memory usage + // // // // bucket size is key + value + 1 byte for status + // // int dht_buckets_per_process = + // // params.dht_size_per_process / (1 + dht_data_size + dht_key_size); - // MDL : following code moved here from worker.cpp - /*Load significance vector from R setup file (or set default)*/ - bool signif_vector_exists = R.parseEval("exists('signif_vector')"); - if (signif_vector_exists) { - params.dht_signif_vector = as>(R["signif_vector"]); - } else { - params.dht_signif_vector.assign(grid.getCols(), dht_significant_digits); - } + // // MDL : following code moved here from worker.cpp + // /*Load significance vector from R setup file (or set default)*/ + // bool signif_vector_exists = R.parseEval("exists('signif_vector')"); + // if (signif_vector_exists) { + // params.dht_signif_vector = as>(R["signif_vector"]); + // } else { + // params.dht_signif_vector.assign(grid.getCols(), + // params.dht_significant_digits); + // } - /*Load property type vector from R setup file (or set default)*/ - bool prop_type_vector_exists = R.parseEval("exists('prop_type')"); - if (prop_type_vector_exists) { - params.dht_prop_type_vector = as>(R["prop_type"]); - } else { - params.dht_prop_type_vector.assign(grid.getCols(), "act"); - } + // /*Load property type vector from R setup file (or set default)*/ + // bool prop_type_vector_exists = R.parseEval("exists('prop_type')"); + // if (prop_type_vector_exists) { + // params.dht_prop_type_vector = as>(R["prop_type"]); + // } else { + // params.dht_prop_type_vector.assign(grid.getCols(), "act"); + // } - if (params.world_rank == 0) { - // // print only on master, values are equal on all workes - // cout << "CPP: dht_data_size: " << dht_data_size << "\n"; - // cout << "CPP: dht_key_size: " << dht_key_size << "\n"; - // cout << "CPP: dht_buckets_per_process: " << dht_buckets_per_process - // << endl; + // if (params.world_rank == 0) { + // // // print only on master, values are equal on all workes + // // cout << "CPP: dht_data_size: " << dht_data_size << "\n"; + // // cout << "CPP: dht_key_size: " << dht_key_size << "\n"; + // // cout << "CPP: dht_buckets_per_process: " << dht_buckets_per_process + // // << endl; - // MDL: new output on signif_vector and prop_type - if (signif_vector_exists) { - cout << "CPP: using problem-specific rounding digits: " << endl; - R.parseEval( - "print(data.frame(prop=prop, type=prop_type, " - "digits=signif_vector))"); - } else { - cout << "CPP: using DHT default rounding digits = " - << dht_significant_digits << endl; - } + // // MDL: new output on signif_vector and prop_type + // if (signif_vector_exists) { + // cout << "CPP: using problem-specific rounding digits: " << endl; + // R.parseEval( + // "print(data.frame(prop=prop, type=prop_type, " + // "digits=signif_vector))"); + // } else { + // cout << "CPP: using DHT default rounding digits = " + // << params.dht_significant_digits << endl; + // } - // MDL: pass to R the DHT stuff. These variables exist - // only if dht_enabled is true - R["dht_final_signif"] = params.dht_signif_vector; - R["dht_final_proptype"] = params.dht_prop_type_vector; - } + // // MDL: pass to R the DHT stuff. These variables exist + // // only if dht_enabled is true + // R["dht_final_signif"] = params.dht_signif_vector; + // R["dht_final_proptype"] = params.dht_prop_type_vector; + // } - // if (params.dht_strategy == 0) { - // if (params.world_rank != 0) { - // dht_object = DHT_create(dht_comm, dht_buckets_per_process, - // dht_data_size, dht_key_size, get_md5); + // // if (params.dht_strategy == 0) { + // // if (params.world_rank != 0) { + // // dht_object = DHT_create(dht_comm, dht_buckets_per_process, + // // dht_data_size, dht_key_size, get_md5); - // // storing for access from worker and callback functions - // fuzzing_buffer = (double *)malloc(dht_key_size); - // } - // } else { - // dht_object = DHT_create(MPI_COMM_WORLD, dht_buckets_per_process, - // dht_data_size, dht_key_size, get_md5); - // } + // // // storing for access from worker and callback functions + // // fuzzing_buffer = (double *)malloc(dht_key_size); + // // } + // // } else { + // // dht_object = DHT_create(MPI_COMM_WORLD, dht_buckets_per_process, + // // dht_data_size, dht_key_size, get_md5); + // // } - // if (params.world_rank == 0) { - // cout << "CPP: DHT successfully created!" << endl; - // } - } + // // if (params.world_rank == 0) { + // // cout << "CPP: DHT successfully created!" << endl; + // // } + // } // MDL: store all parameters if (params.world_rank == 0) { cout << "CPP: Calling R Function to store calling parameters" << endl; @@ -377,7 +383,7 @@ int main(int argc, char *argv[]) { MPI_Barrier(MPI_COMM_WORLD); if (params.world_rank == 0) { /* This is executed by the master */ - ChemMaster master(¶ms, R, grid); + ChemMaster master(parser, R, grid); TransportSim trans(R); Rcpp::NumericVector master_send; @@ -572,14 +578,14 @@ int main(int argc, char *argv[]) { R.parseEval(r_vis_code); cout << "CPP: Done! Results are stored as R objects into <" - << params.out_dir << "/timings.rds>" << endl; + << parser.getOutDir() << "/timings.rds>" << endl; /*exporting results and profiling data*/ // std::string r_vis_code; // r_vis_code = "saveRDS(profiling, file=paste0(fileout,'/timings.rds'));"; // R.parseEval(r_vis_code); } else { /*This is executed by the workers*/ - ChemWorker worker(¶ms, R, grid, dht_comm); + ChemWorker worker(parser, R, grid, dht_comm); // worker.prepareSimulation(dht_comm); worker.loop(); } diff --git a/src/model/ChemMaster.cpp b/src/model/ChemMaster.cpp index f662572a0..64f1305c3 100644 --- a/src/model/ChemMaster.cpp +++ b/src/model/ChemMaster.cpp @@ -8,13 +8,14 @@ using namespace poet; using namespace std; using namespace Rcpp; -#define TAG_WORK 42 - -ChemMaster::ChemMaster(t_simparams *params, RRuntime &R_, Grid &grid_) +ChemMaster::ChemMaster(SimParams ¶ms, RRuntime &R_, Grid &grid_) : ChemSim(params, R_, grid_) { - this->wp_size = params->wp_size; - this->out_dir = params->out_dir; - this->dht_enabled = params->dht_enabled; + t_simparams tmp = params.getNumParams(); + + this->wp_size = tmp.wp_size; + this->dht_enabled = tmp.dht_enabled; + + this->out_dir = params.getOutDir(); workerlist = (worker_struct *)calloc(world_size - 1, sizeof(worker_struct)); send_buffer = (double *)calloc((wp_size * (grid.getCols())) + BUFFER_OFFSET, diff --git a/src/model/ChemSim.cpp b/src/model/ChemSim.cpp index d6459512c..7be1a7406 100644 --- a/src/model/ChemSim.cpp +++ b/src/model/ChemSim.cpp @@ -7,12 +7,13 @@ using namespace Rcpp; using namespace poet; -ChemSim::ChemSim(t_simparams *params, RRuntime &R_, Grid &grid_) +ChemSim::ChemSim(SimParams ¶ms, RRuntime &R_, Grid &grid_) : R(R_), grid(grid_) { - this->world_rank = params->world_rank; - this->world_size = params->world_size; - this->wp_size = params->wp_size; - this->out_dir = params->out_dir; + t_simparams tmp = params.getNumParams(); + this->world_rank = tmp.world_rank; + this->world_size = tmp.world_size; + this->wp_size = tmp.wp_size; + this->out_dir = params.getOutDir(); } void ChemSim::run() { diff --git a/src/model/ChemSim.h b/src/model/ChemSim.h index 3765c3bc2..130de9950 100644 --- a/src/model/ChemSim.h +++ b/src/model/ChemSim.h @@ -23,7 +23,7 @@ namespace poet { class ChemSim { public: - ChemSim(t_simparams *params, RRuntime &R_, Grid &grid_); + ChemSim(SimParams ¶ms, RRuntime &R_, Grid &grid_); virtual void run(); virtual void end(); @@ -59,7 +59,7 @@ class ChemSim { class ChemMaster : public ChemSim { public: - ChemMaster(t_simparams *params, RRuntime &R_, Grid &grid_); + ChemMaster(SimParams ¶ms, RRuntime &R_, Grid &grid_); ~ChemMaster(); void run() override; @@ -91,8 +91,7 @@ class ChemMaster : public ChemSim { class ChemWorker : public ChemSim { public: - ChemWorker(t_simparams *params_, RRuntime &R_, Grid &grid_, - MPI_Comm dht_comm); + ChemWorker(SimParams ¶ms, RRuntime &R_, Grid &grid_, MPI_Comm dht_comm); ~ChemWorker(); void loop(); @@ -110,7 +109,6 @@ class ChemWorker : public ChemSim { std::string dht_file; unsigned int dht_size_per_process; std::vector dht_flags; - t_simparams *params; double *mpi_buffer_results; diff --git a/src/model/ChemWorker.cpp b/src/model/ChemWorker.cpp index 1f62371a1..c81ea450f 100644 --- a/src/model/ChemWorker.cpp +++ b/src/model/ChemWorker.cpp @@ -9,14 +9,17 @@ using namespace poet; using namespace std; using namespace Rcpp; -ChemWorker::ChemWorker(t_simparams *params_, RRuntime &R_, Grid &grid_, +ChemWorker::ChemWorker(SimParams ¶ms, RRuntime &R_, Grid &grid_, MPI_Comm dht_comm) - : params(params_), ChemSim(params_, R_, grid_) { - this->dt_differ = params->dt_differ; - this->dht_enabled = params->dht_enabled; - this->dht_size_per_process = params->dht_size_per_process; - this->dht_file = params->dht_file; - this->dht_snaps = params->dht_snaps; + : ChemSim(params, R_, grid_) { + t_simparams tmp = params.getNumParams(); + + this->dt_differ = tmp.dt_differ; + this->dht_enabled = tmp.dht_enabled; + this->dht_size_per_process = tmp.dht_size_per_process; + this->dht_snaps = tmp.dht_snaps; + + this->dht_file = params.getDHTFile(); mpi_buffer = (double *)calloc((wp_size * (grid.getCols())) + BUFFER_OFFSET, sizeof(double)); @@ -49,9 +52,9 @@ ChemWorker::ChemWorker(t_simparams *params_, RRuntime &R_, Grid &grid_, if (!dht_file.empty()) readFile(); // set size - dht_flags.resize(params->wp_size, true); + dht_flags.resize(wp_size, true); // assign all elements to true (default) - dht_flags.assign(params->wp_size, true); + dht_flags.assign(wp_size, true); timing[0] = 0.0; timing[1] = 0.0; @@ -178,9 +181,9 @@ void ChemWorker::doWork(MPI_Status &probe_status) { // R.parseEvalQ("print(head(work_package_full))"); // R.parseEvalQ("print( c(length(dht_flags), nrow(work_package_full)) )"); - grid.importWP(mpi_buffer, params->wp_size); + grid.importWP(mpi_buffer, wp_size); - if (params->dht_enabled) { + if (dht_enabled) { R.parseEvalQ("work_package <- work_package_full[dht_flags,]"); } else { R.parseEvalQ("work_package <- work_package_full"); diff --git a/src/util/CMakeLists.txt b/src/util/CMakeLists.txt index 9c1446c2c..fb6b282f5 100644 --- a/src/util/CMakeLists.txt +++ b/src/util/CMakeLists.txt @@ -1,4 +1,4 @@ -add_library(POET_Util RRuntime.cpp Parser.cpp) +add_library(POET_Util RRuntime.cpp SimParams.cpp) target_include_directories(POET_Util PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${R_INCLUDE_DIRS}) target_link_libraries(POET_Util ${R_LIBRARIES}) target_compile_definitions(POET_Util PUBLIC STRICT_R_HEADERS) \ No newline at end of file diff --git a/src/util/Parser.cpp b/src/util/Parser.cpp deleted file mode 100644 index 8fd3e0dce..000000000 --- a/src/util/Parser.cpp +++ /dev/null @@ -1,148 +0,0 @@ -#include "Parser.h" - -#include - -#include - -using namespace poet; -using namespace std; -using namespace Rcpp; - -Parser::Parser(char *argv[], int world_rank_, int world_size_) - : cmdl(argv), world_rank(world_rank_), world_size(world_size_) { - this->simparams.world_rank = world_rank_; - this->simparams.world_size = world_size; -} - -int Parser::parseCmdl() { - // if user asked for help - if (cmdl[{"help", "h"}]) { - if (world_rank == 0) { - cout << "Todo" << endl - << "See README.md for further information." << endl; - } - return PARSER_HELP; - } - // if positional arguments are missing - else if (!cmdl(2)) { - if (world_rank == 0) { - cerr << "ERROR. Kin needs 2 positional arguments: " << endl - << "1) the R script defining your simulation and" << endl - << "2) the directory prefix where to save results and profiling" - << endl; - } - return PARSER_ERROR; - } - - // collect all parameters which are not known, print them to stderr and return - // with PARSER_ERROR - std::list unknownOptions = validateOptions(); - if (!unknownOptions.empty()) { - if (world_rank == 0) { - cerr << "Unrecognized option(s):\n" << endl; - for (auto option : unknownOptions) { - cerr << option << endl; - } - cerr << "\nMake sure to use available options. Exiting!" << endl; - } - return PARSER_ERROR; - } - - /*Parse DHT arguments*/ - simparams.dht_enabled = cmdl["dht"]; - // cout << "CPP: DHT is " << ( dht_enabled ? "ON" : "OFF" ) << '\n'; - - if (simparams.dht_enabled) { - cmdl("dht-strategy", 0) >> simparams.dht_strategy; - // cout << "CPP: DHT strategy is " << dht_strategy << endl; - - cmdl("dht-signif", 5) >> dht_significant_digits; - // cout << "CPP: DHT significant digits = " << dht_significant_digits << - // endl; - - simparams.dht_log = !(cmdl["dht-nolog"]); - // cout << "CPP: DHT logarithm before rounding: " << ( dht_logarithm ? "ON" - // : "OFF" ) << endl; - - cmdl("dht-size", DHT_SIZE_PER_PROCESS) >> simparams.dht_size_per_process; - // cout << "CPP: DHT size per process (Byte) = " << dht_size_per_process << - // endl; - - cmdl("dht-snaps", 0) >> simparams.dht_snaps; - - cmdl("dht-file") >> simparams.dht_file; - } - /*Parse work package size*/ - cmdl("work-package-size", WORK_PACKAGE_SIZE_DEFAULT) >> simparams.wp_size; - - /*Parse output options*/ - simparams.store_result = !cmdl["ignore-result"]; - - /* rank 0 will summarize all extracted values to stdout */ - if (world_rank == 0) { - cout << "CPP: Complete results storage is " - << (simparams.store_result ? "ON" : "OFF") << endl; - cout << "CPP: Work Package Size: " << simparams.wp_size << endl; - cout << "CPP: DHT is " << (simparams.dht_enabled ? "ON" : "OFF") << '\n'; - - if (simparams.dht_enabled) { - cout << "CPP: DHT strategy is " << simparams.dht_strategy << endl; - cout << "CPP: DHT key default digits (ignored if 'signif_vector' is " - "defined) = " - << dht_significant_digits << endl; - cout << "CPP: DHT logarithm before rounding: " - << (simparams.dht_log ? "ON" : "OFF") << endl; - cout << "CPP: DHT size per process (Byte) = " - << simparams.dht_size_per_process << endl; - cout << "CPP: DHT save snapshots is " << simparams.dht_snaps << endl; - cout << "CPP: DHT load file is " << simparams.dht_file << endl; - } - } - - cmdl(1) >> simparams.filesim; - cmdl(2) >> simparams.out_dir; - - return PARSER_OK; -} - -void Parser::parseR(RRuntime &R) { - // if local_rank == 0 then master else worker - R["local_rank"] = simparams.world_rank; - // assign a char* (string) to 'filesim' - R["filesim"] = wrap(simparams.filesim); - // assign a char* (string) to 'fileout' - R["fileout"] = wrap(simparams.out_dir); - // pass the boolean "store_result" to the R process - R["store_result"] = simparams.store_result; - // worker count - R["n_procs"] = simparams.world_size - 1; - // work package size - R["work_package_size"] = simparams.wp_size; - // dht enabled? - R["dht_enabled"] = simparams.dht_enabled; - // log before rounding? - R["dht_log"] = simparams.dht_log; - - // eval the init string, ignoring any returns - R.parseEvalQ("source(filesim)"); -} - -t_simparams Parser::getParams() { return this->simparams; } - -std::list Parser::validateOptions() { - /* store all unknown parameters here */ - std::list retList; - - /* loop over all flags and compare to given flaglist*/ - for (auto &flag : cmdl.flags()) { - if (!(flaglist.find(flag) != flaglist.end())) retList.push_back(flag); - } - - /* and loop also over params and compare to given paramlist */ - for (auto ¶m : cmdl.params()) { - if (!(paramlist.find(param.first) != paramlist.end())) - retList.push_back(param.first); - } - - return retList; -} diff --git a/src/util/Parser.h b/src/util/Parser.h deleted file mode 100644 index 0dd8e7ce5..000000000 --- a/src/util/Parser.h +++ /dev/null @@ -1,146 +0,0 @@ -#ifndef PARSER_H -#define PARSER_H - -#include - -#include - -#include "SimParams.h" -#include "argh.h" - -/** Return value if no error occured */ -#define PARSER_OK 0 -/** Return value if error occured during parsing of program arguments */ -#define PARSER_ERROR -1 -/** Return value if user asked for help message with program parameter */ -#define PARSER_HELP -2 - -/** Standard DHT Size (Defaults to 1 GiB) */ -#define DHT_SIZE_PER_PROCESS 1073741824 -/** Standard work package size */ -#define WORK_PACKAGE_SIZE_DEFAULT 5 - -namespace poet { -/** - * @brief Reads information from program arguments and R runtime - * - * Providing functions to initialize parameters of the simulation using command - * line parameters and parameters from the R runtime. This class will also parse - * arguments from the commandline and decides if argument is known or unknown. - * - */ -class Parser { - public: - /** - * @brief Construct a new Parser object - * - * With all given parameters a new instance of this class will be created. - * - * @param argv Argument value of the program - * @param world_rank Rank of process inside MPI_COMM_WORLD - * @param world_size Size of communicator MPI_COMM_WORLD - */ - Parser(char *argv[], int world_rank, int world_size); - - /** - * @brief Parse program arguments - * - * This is done by the argh.h library. - * - * First, the function will check if there is a flag 'help' or 'h'. If this is - * the case a help message is printed and the function will return with - * PARSER_HELP. - * - * Second, if there are not 2 positional arguments an error will be printed to - * stderr and the function returns with PARSER_ERROR. - * - * Then all given program parameters and flags will be read and checked, if - * there are known by validateOptions. A list of all unknown options might be - * returned, printed out and the function will return with PARSER_ERROR. - * Oterhwise the function continuos. - * - * Now all program arguments will be stored inside t_simparams struct, printed - * out and the function returns with PARSER_OK. - * - * @return int Returns with 0 if no error occured, otherwise value less than 0 - * is returned. - */ - int parseCmdl(); - - /** - * @brief Distribute all known parameters to R runtime. - * - * All stored parameters are distributed to the R runtime. - * - * @todo This function might be redundant and can be put into parseCmdl. - * - * @param R Instance of RRuntime - */ - void parseR(RRuntime &R); - - /** - * @brief Get the Params object - * - * Return all parsed simulation parameters. Should be called after parseCmdl. - * - * @return t_simparams Struct of t_simparams - */ - t_simparams getParams(); - - private: - /** - * @brief Validate program parameters and flags - * - * Therefore this function iterates over the list of flags and parameters and - * compare them to the class member flagList and paramList. If a program - * argument is not included it is put to a list. This list will be returned. - * - * @return std::list List with all unknown parameters. Might be - * empty. - */ - std::list validateOptions(); - - /** - * @brief Contains all valid program flags. - * - */ - const std::set flaglist{"ignore-result", "dht", "dht-nolog"}; - - /** - * @brief Contains all valid program parameters. - * - */ - const std::set paramlist{"work-package-size", "dht-signif", - "dht-strategy", "dht-size", - "dht-snaps", "dht-file"}; - - /** - * @brief Instance of argh class - * - * This class will be instantiate inside constructor of this class object. - * - */ - argh::parser cmdl; - - /** - * @brief Struct containing all simulation parameters - * - */ - t_simparams simparams; - - /** - * @brief Rank of process inside MPI_COMM_WORLD - * - */ - int world_rank; - - /** - * @brief Size of MPI_COMM_WORLD - * - */ - int world_size; - - int dht_significant_digits; -}; -} // namespace poet -#endif // PARSER_H \ No newline at end of file diff --git a/src/util/SimParams.cpp b/src/util/SimParams.cpp new file mode 100644 index 000000000..fdf95e685 --- /dev/null +++ b/src/util/SimParams.cpp @@ -0,0 +1,240 @@ +#include "SimParams.h" + +#include + +#include + +using namespace poet; +using namespace std; +using namespace Rcpp; + +SimParams::SimParams(int world_rank_, int world_size_) { + this->simparams.world_rank = world_rank_; + this->simparams.world_size = world_size_; +} + +int SimParams::parseFromCmdl(char *argv[], RRuntime &R) { + // initialize argh object + argh::parser cmdl(argv); + + // if user asked for help + if (cmdl[{"help", "h"}]) { + if (simparams.world_rank == 0) { + cout << "Todo" << endl + << "See README.md for further information." << endl; + } + return PARSER_HELP; + } + // if positional arguments are missing + else if (!cmdl(2)) { + if (simparams.world_rank == 0) { + cerr << "ERROR. Kin needs 2 positional arguments: " << endl + << "1) the R script defining your simulation and" << endl + << "2) the directory prefix where to save results and profiling" + << endl; + } + return PARSER_ERROR; + } + + // collect all parameters which are not known, print them to stderr and return + // with PARSER_ERROR + std::list optionsError = validateOptions(cmdl); + if (!optionsError.empty()) { + if (simparams.world_rank == 0) { + cerr << "Unrecognized option(s):\n" << endl; + for (auto option : optionsError) { + cerr << option << endl; + } + cerr << "\nMake sure to use available options. Exiting!" << endl; + } + return PARSER_ERROR; + } + + /*Parse DHT arguments*/ + simparams.dht_enabled = cmdl["dht"]; + // cout << "CPP: DHT is " << ( dht_enabled ? "ON" : "OFF" ) << '\n'; + + if (simparams.dht_enabled) { + cmdl("dht-strategy", 0) >> simparams.dht_strategy; + // cout << "CPP: DHT strategy is " << dht_strategy << endl; + + cmdl("dht-signif", 5) >> simparams.dht_significant_digits; + // cout << "CPP: DHT significant digits = " << dht_significant_digits << + // endl; + + simparams.dht_log = !(cmdl["dht-nolog"]); + // cout << "CPP: DHT logarithm before rounding: " << ( dht_logarithm ? "ON" + // : "OFF" ) << endl; + + cmdl("dht-size", DHT_SIZE_PER_PROCESS) >> simparams.dht_size_per_process; + // cout << "CPP: DHT size per process (Byte) = " << dht_size_per_process << + // endl; + + cmdl("dht-snaps", 0) >> simparams.dht_snaps; + + cmdl("dht-file") >> dht_file; + } + /*Parse work package size*/ + cmdl("work-package-size", WORK_PACKAGE_SIZE_DEFAULT) >> simparams.wp_size; + + /*Parse output options*/ + simparams.store_result = !cmdl["ignore-result"]; + + if (simparams.world_rank == 0) { + cout << "CPP: Complete results storage is " + << (simparams.store_result ? "ON" : "OFF") << endl; + cout << "CPP: Work Package Size: " << simparams.wp_size << endl; + cout << "CPP: DHT is " << (simparams.dht_enabled ? "ON" : "OFF") << '\n'; + + if (simparams.dht_enabled) { + cout << "CPP: DHT strategy is " << simparams.dht_strategy << endl; + cout << "CPP: DHT key default digits (ignored if 'signif_vector' is " + "defined) = " + << simparams.dht_significant_digits << endl; + cout << "CPP: DHT logarithm before rounding: " + << (simparams.dht_log ? "ON" : "OFF") << endl; + cout << "CPP: DHT size per process (Byte) = " + << simparams.dht_size_per_process << endl; + cout << "CPP: DHT save snapshots is " << simparams.dht_snaps << endl; + cout << "CPP: DHT load file is " << dht_file << endl; + } + } + + cmdl(1) >> filesim; + cmdl(2) >> out_dir; + + /* distribute information to R runtime */ + // if local_rank == 0 then master else worker + R["local_rank"] = simparams.world_rank; + // assign a char* (string) to 'filesim' + R["filesim"] = wrap(filesim); + // assign a char* (string) to 'fileout' + R["fileout"] = wrap(out_dir); + // pass the boolean "store_result" to the R process + R["store_result"] = simparams.store_result; + // worker count + R["n_procs"] = simparams.world_size - 1; + // work package size + R["work_package_size"] = simparams.wp_size; + // dht enabled? + R["dht_enabled"] = simparams.dht_enabled; + // log before rounding? + R["dht_log"] = simparams.dht_log; + + // eval the init string, ignoring any returns + R.parseEvalQ("source(filesim)"); + + return PARSER_OK; +} + +void SimParams::initVectorParams(RRuntime &R, int col_count) { + if (simparams.dht_enabled) { + // cout << "\nCreating DHT\n"; + // determine size of dht entries + // int dht_data_size = grid.getCols() * sizeof(double); + // int dht_key_size = + // grid.getCols() * sizeof(double) + (params.dt_differ * + // sizeof(double)); + + // // // determine bucket count for preset memory usage + // // // bucket size is key + value + 1 byte for status + // int dht_buckets_per_process = + // params.dht_size_per_process / (1 + dht_data_size + dht_key_size); + + // MDL : following code moved here from worker.cpp + /*Load significance vector from R setup file (or set default)*/ + bool signif_vector_exists = R.parseEval("exists('signif_vector')"); + if (signif_vector_exists) { + dht_signif_vector = as>(R["signif_vector"]); + } else { + dht_signif_vector.assign(col_count, simparams.dht_significant_digits); + } + + /*Load property type vector from R setup file (or set default)*/ + bool prop_type_vector_exists = R.parseEval("exists('prop_type')"); + if (prop_type_vector_exists) { + dht_prop_type_vector = as>(R["prop_type"]); + } else { + dht_prop_type_vector.assign(col_count, "act"); + } + + if (simparams.world_rank == 0) { + // // print only on master, values are equal on all workes + // cout << "CPP: dht_data_size: " << dht_data_size << "\n"; + // cout << "CPP: dht_key_size: " << dht_key_size << "\n"; + // cout << "CPP: dht_buckets_per_process: " << dht_buckets_per_process + // << endl; + + // MDL: new output on signif_vector and prop_type + if (signif_vector_exists) { + cout << "CPP: using problem-specific rounding digits: " << endl; + R.parseEval( + "print(data.frame(prop=prop, type=prop_type, " + "digits=signif_vector))"); + } else { + cout << "CPP: using DHT default rounding digits = " + << simparams.dht_significant_digits << endl; + } + + // MDL: pass to R the DHT stuff. These variables exist + // only if dht_enabled is true + R["dht_final_signif"] = dht_signif_vector; + R["dht_final_proptype"] = dht_prop_type_vector; + } + } +} + +// void SimParams::parseR(RRuntime &R) { +// // if local_rank == 0 then master else worker +// R["local_rank"] = simparams.world_rank; +// // assign a char* (string) to 'filesim' +// R["filesim"] = wrap(simparams.filesim); +// // assign a char* (string) to 'fileout' +// R["fileout"] = wrap(simparams.out_dir); +// // pass the boolean "store_result" to the R process +// R["store_result"] = simparams.store_result; +// // worker count +// R["n_procs"] = simparams.world_size - 1; +// // work package size +// R["work_package_size"] = simparams.wp_size; +// // dht enabled? +// R["dht_enabled"] = simparams.dht_enabled; +// // log before rounding? +// R["dht_log"] = simparams.dht_log; + +// // eval the init string, ignoring any returns +// R.parseEvalQ("source(filesim)"); +// } + +void SimParams::setDtDiffer(bool dt_differ) { simparams.dt_differ = dt_differ; } + +t_simparams SimParams::getNumParams() { return this->simparams; } + +std::vector SimParams::getDHTSignifVector() { + return this->dht_signif_vector; +} +std::vector SimParams::getDHTPropTypeVector() { + return this->dht_prop_type_vector; +} +std::string SimParams::getDHTFile() { return this->dht_file; } + +std::string SimParams::getFilesim() { return this->filesim; } +std::string SimParams::getOutDir() { return this->out_dir; } + +std::list SimParams::validateOptions(argh::parser cmdl) { + /* store all unknown parameters here */ + std::list retList; + + /* loop over all flags and compare to given flaglist*/ + for (auto &flag : cmdl.flags()) { + if (!(flaglist.find(flag) != flaglist.end())) retList.push_back(flag); + } + + /* and loop also over params and compare to given paramlist */ + for (auto ¶m : cmdl.params()) { + if (!(paramlist.find(param.first) != paramlist.end())) + retList.push_back(param.first); + } + + return retList; +} diff --git a/src/util/SimParams.h b/src/util/SimParams.h index b4ad7ac8d..9cb70f0eb 100644 --- a/src/util/SimParams.h +++ b/src/util/SimParams.h @@ -1,8 +1,22 @@ -#ifndef SIMPARAMS_H -#define SIMPARAMS_H +#ifndef PARSER_H +#define PARSER_H #include -#include + +#include "RRuntime.h" +#include "argh.h" + +/** Return value if no error occured */ +#define PARSER_OK 0 +/** Return value if error occured during parsing of program arguments */ +#define PARSER_ERROR -1 +/** Return value if user asked for help message with program parameter */ +#define PARSER_HELP -2 + +/** Standard DHT Size (Defaults to 1 GiB) */ +#define DHT_SIZE_PER_PROCESS 1073741824 +/** Standard work package size */ +#define WORK_PACKAGE_SIZE_DEFAULT 5 typedef struct { int world_size; @@ -14,19 +28,119 @@ typedef struct { int dht_snaps; int dht_strategy; unsigned int dht_size_per_process; + int dht_significant_digits; + + unsigned int wp_size; + + bool store_result; +} t_simparams; + +namespace poet { +/** + * @brief Reads information from program arguments and R runtime + * + * Providing functions to initialize parameters of the simulation using command + * line parameters and parameters from the R runtime. This class will also parse + * arguments from the commandline and decides if argument is known or unknown. + * + * Stores and distribute current simulation parameters at any time. + * + */ +class SimParams { + public: + /** + * @brief Construct a new SimParams object + * + * With all given parameters a new instance of this class will be created. + * + * @param world_rank Rank of process inside MPI_COMM_WORLD + * @param world_size Size of communicator MPI_COMM_WORLD + */ + SimParams(int world_rank, int world_size); + + /** + * @brief Parse program arguments + * + * This is done by the argh.h library. + * + * First, the function will check if there is a flag 'help' or 'h'. If this is + * the case a help message is printed and the function will return with + * PARSER_HELP. + * + * Second, if there are not 2 positional arguments an error will be printed to + * stderr and the function returns with PARSER_ERROR. + * + * Then all given program parameters and flags will be read and checked, if + * there are known by validateOptions. A list of all unknown options might be + * returned, printed out and the function will return with PARSER_ERROR. + * Oterhwise the function continuos. + * + * Now all program arguments will be stored inside t_simparams struct, printed + * out and the function returns with PARSER_OK. + * + * Also, all parsed agruments are distributed to the R runtime. + * + * @param argv Argument value of the program + * @param R Instantiated R runtime + * @return int Returns with 0 if no error occured, otherwise value less than 0 + * is returned. + */ + int parseFromCmdl(char *argv[], RRuntime &R); + + void initVectorParams(RRuntime &R, int col_count); + + void setDtDiffer(bool dt_differ); + + t_simparams getNumParams(); + + std::vector getDHTSignifVector(); + std::vector getDHTPropTypeVector(); + std::string getDHTFile(); + + std::string getFilesim(); + std::string getOutDir(); + + private: + /** + * @brief Validate program parameters and flags + * + * Therefore this function iterates over the list of flags and parameters and + * compare them to the class member flagList and paramList. If a program + * argument is not included it is put to a list. This list will be returned. + * + * @return std::list List with all unknown parameters. Might be + * empty. + */ + std::list validateOptions(argh::parser cmdl); + + /** + * @brief Contains all valid program flags. + * + */ + std::set flaglist{"ignore-result", "dht", "dht-nolog"}; + + /** + * @brief Contains all valid program parameters. + * + */ + std::set paramlist{"work-package-size", "dht-signif", + "dht-strategy", "dht-size", + "dht-snaps", "dht-file"}; + + /** + * @brief Struct containing all simulation parameters + * + * Contains only those values which are standard arithmetic C types. + * + */ + t_simparams simparams; + std::vector dht_signif_vector; std::vector dht_prop_type_vector; std::string dht_file; - unsigned int wp_size; - std::string filesim; std::string out_dir; - - bool store_result; - - // void* R; - // void* grid; -} t_simparams; - -#endif // SIMPARAMS_H +}; +} // namespace poet +#endif // PARSER_H \ No newline at end of file