#include "Configuration.hpp" #include #include #include #include #include #include "MpiEnvironment.hpp" #include #include // BEGIN helper functions to parse Communication Mode cmd args using namespace std::string_literals; std::array, 2> StringToCommunicationMode{ std::make_pair("Collective"s, CommunicationMode::Collective), // std::make_pair("P2P"s, CommunicationMode::P2P) // }; std::istream& operator>>(std::istream& in, CommunicationMode& comm) { std::string buf; in >> buf; auto r = std::find_if(std::begin(StringToCommunicationMode), std::end(StringToCommunicationMode), [&](auto& t) { return t.first == buf; }); if (r == std::end(StringToCommunicationMode)) throw boost::program_options::validation_error( boost::program_options::validation_error::invalid_option_value); comm = r->second; return in; } // END helper functions auto Configuration::parseArgs(int argc, char* argv[], const MpiEnvironment& env) -> Configuration { namespace po = boost::program_options; Configuration cfg; po::options_description desc{"Allowed options"}; desc.add_options()("help,h", "produce help message") // ("nprocs-x,x", po::value(&cfg.Procs.Cols), "number of processes in x-direction") // ("nprocs-y,y", po::value(&cfg.Procs.Rows), "number of processes in y-direction") // ("generations,g", po::value(&cfg.Generations), "number of generations simulated") // ("commmode,m", po::value(&cfg.CommMode), "Communication Mode. Collective or P2P") // ("inputfile,f", po::value(&cfg.InputFilePath)->required(), "path to wireworld file") // ("outputfile,o", po::value(&cfg.OutputFilePath), "path to output file"); // po::positional_options_description poDesc; poDesc.add("inputfile", 1); po::variables_map vm; try { po::store(po::command_line_parser(argc, argv) .options(desc) // .positional(poDesc) // .run(), vm); if (vm.count("help") > 0 && env.isMaster()) { std::cout << desc << "\n"; } po::notify(vm); } catch (const po::error& err) { MpiReportErrorAbort(err.what()); } // if no dimensions given, use MPI_Dims_create if (cfg.Procs.Cols < 1 || cfg.Procs.Rows < 1) { std::array dims{static_cast(cfg.Procs.Cols), static_cast(cfg.Procs.Rows)}; MPI_Dims_create(env.worldSize(), // nnodes 2, // ndims dims.data()); // dims cfg.Procs.Cols = dims[0]; cfg.Procs.Rows = dims[1]; } // validate const auto& totalCellCount = cfg.Procs.Cols * cfg.Procs.Rows; const auto& worldSize = env.worldSize(); if (totalCellCount != static_cast(worldSize)) { MpiReportErrorAbort(boost::str( boost::format("Total number of cells (%d) does not match " "the MPI World size (%d)") % totalCellCount % worldSize)); } return cfg; }