configuration.c 4.72 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <getopt.h>
#include <math.h>
#include <mpi.h>
#include <stdlib.h>
#include <stdio.h>

#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);

17
18
int log_enabled(const conf_t *c, int lvl);

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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
36
   c->halo_width = 1;
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
   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'},
52
      {"halo-width", required_argument, NULL, 'w'},
53

54
55
56
57
58
59
60
61
62
63
64
      {"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;
65
   while((option = getopt_long(argc, argv, "v:g:n:N:e:w:i:", long_options, NULL)) >= 0) {
66
67
68
69
70
71
      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;
72
         case 'w': c->halo_width = atoi(optarg); break;
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
         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));
95
   fprintf(f, " * Halo width:              %d cell%s\n", c->halo_width, c->halo_width == 1 ? "" : "s");
96
   fprintf(f, " * Halo transfer mode:      %s\n", transfer_mode_strs[c->transfer_mode]);
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
   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;
}