#include #include #include #include #include #include "configuration.h" #include "box.h" // --------------------------------------------- Helper function declarations long parse_long(const char *str); void set_ncells_per_proc(conf_t *c, double ncells_per_proc); void set_ncells_total(conf_t *c, double ncells_total); void set_global_domain(conf_t *c, int cube_edge_length); int log_enabled(const conf_t *c, int lvl); const char *verbosity_levels[] = {"OFF", "INFO", "DEBUG", "TRACE"}; // ========================================================================== void conf_init(conf_t *c) { // Default number of cells (mesh elements) per proces: 1 * 2^14 = 16k double ncells_per_proc_avg = 0x1p14; c->verbosity_level = INFO; c->debug_rank = -1; #if MPI_VERSION >= 3 c->transfer_mode = SPARSE_COLLECTIVE; #else #pragma message("MPI_VERSION < 3 => Default transfer mode for halo exchange will be collective.") c->transfer_mode = COLLECTIVE; #endif c->halo_width = 1; c->n_iterations = 100; // Default values: set_ncells_per_proc(c, ncells_per_proc_avg); } const char* conf_set_from_args(conf_t *c, int argc, char* argv[]) { struct option long_options[] = { {"verbose", required_argument, NULL, 'v'}, {"debug-rank", required_argument, NULL, 'g'}, {"ncells-per-proc", required_argument, NULL, 'n'}, {"ncells", required_argument, NULL, 'N'}, {"edge-length", required_argument, NULL, 'e'}, {"halo-width", required_argument, NULL, 'w'}, {"graph", no_argument, &c->transfer_mode, SPARSE_COLLECTIVE}, {"collective", no_argument, &c->transfer_mode, COLLECTIVE}, {"p2p", no_argument, &c->transfer_mode, P2P_DEFAULT}, {"p2p-sync", no_argument, &c->transfer_mode, P2P_SYNCHRONOUS}, {"p2p-ready", no_argument, &c->transfer_mode, P2P_READY}, {"iterations", required_argument, NULL, 'i'}, {NULL, 0, NULL, 0} }; int option; while((option = getopt_long(argc, argv, "v:g:n:N:e:w:i:", long_options, NULL)) >= 0) { switch(option) { case 'v': c->verbosity_level = atoi(optarg); break; case 'g': c->debug_rank = atoi(optarg); break; case 'n': set_ncells_per_proc(c, parse_long(optarg)); break; case 'N': set_ncells_total(c, parse_long(optarg)); break; case 'e': set_global_domain(c, atoi(optarg)); break; case 'w': c->halo_width = atoi(optarg); break; case 'i': c->n_iterations = parse_long(optarg); break; } } return NULL; } void conf_print(const conf_t *c, FILE *f) { char *transfer_mode_strs[] = { "Sparse collective - MPI_Neighbor_alltoallw", "Collective - MPI_Alltoallw", "Point-to-point - MPI_Isend / MPI_Irecv", "Point-to-point; synchronous mode - MPI_Issend / MPI_Irecv", "Point-to-point; ready mode - MPI_Irsend / MPI_Irecv" }; char buf[128]; int i = c->verbosity_level; if(i < 0) i = 0; else if(i > 3) i = 3; fprintf(f, "Configuration:\n"); fprintf(f, " * Verbosity level: %s (%d)\n", verbosity_levels[i], c->verbosity_level); fprintf(f, " * Mesh domain (cube): %s\n", box_to_string(&c->global_domain, buf, 128)); fprintf(f, " * Halo width: %d cell%s\n", c->halo_width, c->halo_width == 1 ? "" : "s"); fprintf(f, " * Halo transfer mode: %s\n", transfer_mode_strs[c->transfer_mode]); fprintf(f, " * Number of iterations: %d\n", c->n_iterations); fprintf(f, "\n"); } int log_enabled(const conf_t *c, int lvl) { static int rank = -1; if(rank < 0) { MPI_Comm_rank(MPI_COMM_WORLD, &rank); } return c->verbosity_level >= lvl && (rank == 0 || rank == c->debug_rank); } int info_enabled(const conf_t *c) { return log_enabled(c, INFO); } int debug_enabled(const conf_t *c) { return log_enabled(c, DEBUG); } int trace_enabled(const conf_t *c) { return log_enabled(c, TRACE); } // --------------------------------------------------------- Helper functions void set_ncells_per_proc(conf_t *c, double ncells_per_proc) { int nprocs; MPI_Comm_size(MPI_COMM_WORLD, &nprocs); set_ncells_total(c, ncells_per_proc * nprocs); } void set_ncells_total(conf_t *c, double ncells_total) { double edge_length_exact = cbrt(ncells_total); set_global_domain(c, (int)round(edge_length_exact)); } void set_global_domain(conf_t *c, int cube_edge_length) { box_t *cube = &c->global_domain; int i; for(i = 0; i < N_DIMS; i++) { cube->coords[i] = 0; cube->extents[i] = cube_edge_length; } box_set_volume(cube); } long parse_long(const char *str) { char* p; long result = strtol(str, &p, 10); if(*p == 'k') { result <<= 10; } else if(*p == 'M') { result <<= 20; } return result; }