Merge branch 'dev' into doc

This commit is contained in:
Max Lübke 2021-02-02 14:00:13 +01:00
commit 12f7820f91
15 changed files with 500 additions and 432 deletions

View File

@ -1,4 +1,4 @@

<!--
Time-stamp: "Last modified 2020-02-01 18:14:13 delucia"
-->
@ -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)

View File

@ -1,10 +1,10 @@
#include "DHT.h"
#include <inttypes.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include <unistd.h>
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
}

View File

@ -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.

View File

@ -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 &params, 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?

View File

@ -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 &params, 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
*/

View File

@ -10,7 +10,6 @@
// BSD-licenced #include "dht_wrapper.h" #include "global_buffer.h"
#include <ChemSim.h>
#include <Grid.h>
#include <Parser.h>
#include <RRuntime.h>
#include <SimParams.h>
#include <TransportSim.h>
@ -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<std::vector<int>>(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<std::vector<int>>(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<std::vector<string>>(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<std::vector<string>>(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(&params, 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(&params, R, grid, dht_comm);
ChemWorker worker(parser, R, grid, dht_comm);
// worker.prepareSimulation(dht_comm);
worker.loop();
}

View File

@ -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 &params, 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,

View File

@ -7,12 +7,13 @@
using namespace Rcpp;
using namespace poet;
ChemSim::ChemSim(t_simparams *params, RRuntime &R_, Grid &grid_)
ChemSim::ChemSim(SimParams &params, 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() {

View File

@ -23,7 +23,7 @@
namespace poet {
class ChemSim {
public:
ChemSim(t_simparams *params, RRuntime &R_, Grid &grid_);
ChemSim(SimParams &params, 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 &params, 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 &params, 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<bool> dht_flags;
t_simparams *params;
double *mpi_buffer_results;

View File

@ -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 &params, 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");

View File

@ -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)

View File

@ -1,148 +0,0 @@
#include "Parser.h"
#include <Rcpp.h>
#include <iostream>
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<std::string> 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<std::string> Parser::validateOptions() {
/* store all unknown parameters here */
std::list<std::string> 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 &param : cmdl.params()) {
if (!(paramlist.find(param.first) != paramlist.end()))
retList.push_back(param.first);
}
return retList;
}

View File

@ -1,146 +0,0 @@
#ifndef PARSER_H
#define PARSER_H
#include <RRuntime.h>
#include <string>
#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<std::string> List with all unknown parameters. Might be
* empty.
*/
std::list<std::string> validateOptions();
/**
* @brief Contains all valid program flags.
*
*/
const std::set<std::string> flaglist{"ignore-result", "dht", "dht-nolog"};
/**
* @brief Contains all valid program parameters.
*
*/
const std::set<std::string> 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

240
src/util/SimParams.cpp Normal file
View File

@ -0,0 +1,240 @@
#include "SimParams.h"
#include <Rcpp.h>
#include <iostream>
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<std::string> 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<std::vector<int>>(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<std::vector<string>>(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<int> SimParams::getDHTSignifVector() {
return this->dht_signif_vector;
}
std::vector<std::string> 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<std::string> SimParams::validateOptions(argh::parser cmdl) {
/* store all unknown parameters here */
std::list<std::string> 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 &param : cmdl.params()) {
if (!(paramlist.find(param.first) != paramlist.end()))
retList.push_back(param.first);
}
return retList;
}

View File

@ -1,8 +1,22 @@
#ifndef SIMPARAMS_H
#define SIMPARAMS_H
#ifndef PARSER_H
#define PARSER_H
#include <string>
#include <vector>
#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<int> getDHTSignifVector();
std::vector<std::string> 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<std::string> List with all unknown parameters. Might be
* empty.
*/
std::list<std::string> validateOptions(argh::parser cmdl);
/**
* @brief Contains all valid program flags.
*
*/
std::set<std::string> flaglist{"ignore-result", "dht", "dht-nolog"};
/**
* @brief Contains all valid program parameters.
*
*/
std::set<std::string> 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<int> dht_signif_vector;
std::vector<std::string> 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