MAM_Configuration.c 14.4 KB
Newer Older
Iker Martín Álvarez's avatar
Iker Martín Álvarez committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
#include "MAM_Configuration.h"
#include "MAM_Init_Configuration.h"
#include "MAM_DataStructures.h"
#include <limits.h>

typedef struct {
    unsigned int *value, default_value;
    int config_max_length;
    union {
      int (*set_config_simple)(unsigned int, unsigned int *);
      int (*set_config_complex)(unsigned int);
    };
    char *env_name;
} mam_config_setting_t;

int MAM_I_set_method(unsigned int new_method, unsigned int *method);
int MAM_I_set_spawn_strat(unsigned int strategy, unsigned int *strategies);
int MAM_I_set_red_strat(unsigned int strategy, unsigned int *strategies);
int MAM_I_set_target_number(unsigned int new_numC);

int MAM_I_configuration_get_defaults();

int MAM_I_contains_strat(unsigned int comm_strategies, unsigned int strategy);
int MAM_I_add_strat(unsigned int *comm_strategies, unsigned int strategy);
int MAM_I_remove_strat(unsigned int *comm_strategies, unsigned int strategy);

mam_config_setting_t configSettings[] = { 
    {NULL, MAM_SPAWN_MERGE, MAM_METHODS_SPAWN_LEN, {.set_config_simple = MAM_I_set_method }, MAM_SPAWN_METHOD_ENV},
    {NULL, MAM_STRAT_SPAWN_CLEAR, MAM_STRATS_SPAWN_LEN, {.set_config_simple = MAM_I_set_spawn_strat }, MAM_SPAWN_STRATS_ENV},
    {NULL, MAM_PHY_DIST_COMPACT, MAM_METHODS_PHYSICAL_DISTRIBUTION_LEN, {.set_config_simple = MAM_I_set_method }, MAM_PHYSICAL_DISTRIBUTION_METHOD_ENV},
    {NULL, MAM_RED_BASELINE, MAM_METHODS_RED_LEN, {.set_config_simple = MAM_I_set_method }, MAM_RED_METHOD_ENV},
    {NULL, MAM_STRAT_RED_CLEAR, MAM_STRATS_RED_LEN, {.set_config_simple = MAM_I_set_red_strat }, MAM_RED_STRATS_ENV},

    {NULL, 1, INT_MAX, {.set_config_complex = MAM_I_set_target_number }, MAM_NUM_TARGETS_ENV}
};

unsigned int masks_spawn[] = {MAM_STRAT_CLEAR_VALUE, MAM_MASK_PTHREAD, MAM_MASK_SPAWN_SINGLE, MAM_MASK_SPAWN_INTERCOMM, MAM_MASK_SPAWN_MULTIPLE, MAM_MASK_SPAWN_PARALLEL};
unsigned int masks_red[] = {MAM_STRAT_CLEAR_VALUE, MAM_MASK_PTHREAD, MAM_MASK_RED_WAIT_SOURCES, MAM_MASK_RED_WAIT_TARGETS};

/**
 * @brief Set configuration parameters for MAM.
 *
 * This function allows setting various configuration parameters for MAM
 * such as spawn method, spawn strategies, spawn physical distribution, 
 * redistribution method, and red strategies.
 *
 * @param spawn_method The spawn method reconfiguration.
 * @param spawn_strategies The spawn strategies reconfiguration.
 * @param spawn_dist The spawn physical distribution method reconfiguration.
 * @param red_method The redistribution method reconfiguration.
 * @param red_strategies The redesitribution strategy for reconfiguration.
 */
void MAM_Set_configuration(int spawn_method, int spawn_strategies, int spawn_dist, int red_method, int red_strategies) {
  int i, aux;
  int aux_array[] = {spawn_method, spawn_strategies, spawn_dist, red_method, red_strategies};
  if(state > MAM_I_NOT_STARTED) return;

  mam_config_setting_t *config = NULL;
  for (i = 0; i < MAM_KEY_COUNT-1; i++) { //FIXME Numero magico para no cambiar num_targets
    aux = aux_array[i];
    config = &configSettings[i];
    if (0 <= aux && aux < config->config_max_length) {
      if(i == MAM_NUM_TARGETS) {
        config->set_config_complex(aux);
      } else {
        config->set_config_simple(aux, config->value);
      }
    } 
  }
}

/*
 * @brief Set the configuration value for a specific key in MAM.
 *
 * Modifies the configuration value associated with the given key
 * to the specified "required" value. The final value set is returned in the
 * "provided" parameter.
 *
 * @param key       The key for which the configuration value is to be modified.
 * @param required  The required value to set for the specified key.
 * @param provided  Pointer to an integer where the final value set will be stored.
 *                  This parameter is updated with the actual value after modification.
 *                  For strategy keys the value is "MAM_STRATS_ADDED" if "required" has 
 *                  been added, or "MAM_STRATS_MODIFIED" if multiple strategies of the
 *                  key have been modified.
 */
void MAM_Set_key_configuration(int key, int required, int *provided) {
  int i, aux;

  if(provided == NULL) provided = &aux;
  *provided = MAM_DENIED;
  if(required < 0 || state > MAM_I_NOT_STARTED) return;

  mam_config_setting_t *config = NULL;
  for (i = 0; i < MAM_KEY_COUNT; i++) { //FIXME A for is not needed -- Check if key < MAM_KEY_COUNT and then just use key as index
    if (key == i) {
      config = &configSettings[i];
      break;
    }
  }

  if (config != NULL) {
    if (required < config->config_max_length) {
      if(i == MAM_NUM_TARGETS) {
        *provided = config->set_config_complex(required);
      } else {
        *provided = config->set_config_simple(required, config->value);
      }
    } else {*provided = *(config->value); }
  } else { printf("MAM: Key %d does not exist\n", key); }
}

/*
 * Retorna si una estrategia aparece o no
 */
int MAM_Contains_strat(int key, unsigned int strategy, int *result) {
  int strategies, aux = MAM_OK;
  unsigned int len = 0, mask;

  switch(key) {
    case MAM_SPAWN_STRATEGIES:
      strategies = mall_conf->spawn_strategies;
      mask = masks_spawn[strategy];
      len = MAM_STRATS_SPAWN_LEN;
      break;
    case MAM_RED_STRATEGIES:
      strategies = mall_conf->red_strategies;
      mask = masks_red[strategy];
      len = MAM_STRATS_RED_LEN;
      break;
    default:
      aux = MAM_DENIED;
      break;
  }

  if(aux == MAM_OK && strategy < len) {
    aux = MAM_I_contains_strat(strategies, mask);
  } else {
    aux = 0;
  }

  if(result != NULL) *result = aux;
  return aux;
}

/*
 * //TODO
 * Tiene que ser llamado despues de setear la config
 */
int MAM_Set_target_number(unsigned int numC){
  return MAM_I_set_target_number(numC);
}


/*
 * //TODO
 * Tiene que ser llamado fuera de reconfig
 */
void MAM_Use_valgrind(int flag) {
  if(state > MAM_I_NOT_STARTED) return;

  mall_conf->external_usage = flag ? MAM_USE_VALGRIND: 0;
  #if MAM_DEBUG
    if(mall->myId == mall->root && flag) DEBUG_FUNC("Settled Valgrind Wrapper", mall->myId, mall->numP); fflush(stdout);
  #endif
}

/*
 * //TODO
 * Tiene que ser llamado fuera de reconfig
 */
void MAM_Use_extrae(int flag) {
  if(state > MAM_I_NOT_STARTED) return;

  mall_conf->external_usage = flag ? MAM_USE_EXTRAE: 0;
  #if MAM_DEBUG
    if(mall->myId == mall->root && flag) DEBUG_FUNC("Settled Extrae Wrapper", mall->myId, mall->numP); fflush(stdout);
  #endif
}

//======================================================||
//===============MAM_INIT FUNCTIONS=====================||
//======================================================||
//======================================================||

void MAM_Init_configuration() {
  if(mall == NULL || mall_conf == NULL) {
    printf("MAM FATAL ERROR: Setting initial config without previous mallocs\n");
    fflush(stdout);
    MPI_Abort(MPI_COMM_WORLD, -50);
  }

  mall_conf->spawn_method = MAM_STRAT_CLEAR_VALUE;
  mall_conf->spawn_strategies = MAM_STRAT_CLEAR_VALUE;
  mall_conf->red_method = MAM_STRAT_CLEAR_VALUE;
  mall_conf->red_strategies = MAM_STRAT_CLEAR_VALUE;
  mall_conf->external_usage = 0;

  configSettings[MAM_SPAWN_METHOD].value = &mall_conf->spawn_method;
  configSettings[MAM_SPAWN_STRATEGIES].value = &mall_conf->spawn_strategies;
  configSettings[MAM_PHYSICAL_DISTRIBUTION].value = &mall_conf->spawn_dist;
  configSettings[MAM_RED_METHOD].value = &mall_conf->red_method;
  configSettings[MAM_RED_STRATEGIES].value = &mall_conf->red_strategies;
}

void MAM_Set_initial_configuration() {
  int not_filled = 1;
  
  not_filled = MAM_I_configuration_get_defaults();
  if(not_filled) {
    if(mall->myId == mall->root) printf("MAM WARNING: Starting configuration not set\n");
    fflush(stdout);
    MPI_Abort(mall->comm, -50);
  }

  #if MAM_DEBUG >= 2
    if(mall->myId == mall->root) {
      DEBUG_FUNC("Initial configuration settled", mall->myId, mall->numP); 
      fflush(stdout); 
    }
  #endif
}

void MAM_Check_configuration() {
  int global_internodes;
  if(mall->numC == mall->numP) { // Migrate
    MAM_Set_key_configuration(MAM_SPAWN_METHOD, MAM_SPAWN_BASELINE, NULL);
  }

  MPI_Allreduce(&mall->internode_group, &global_internodes, 1, MPI_INT, MPI_MAX, mall->comm);
  if((MAM_Contains_strat(MAM_SPAWN_STRATEGIES, MAM_STRAT_SPAWN_MULTIPLE, NULL)
  || MAM_Contains_strat(MAM_SPAWN_STRATEGIES, MAM_STRAT_SPAWN_PARALLEL, NULL) )
  && global_internodes) { // Remove internode MPI_COMM_WORLDs
    MAM_Set_key_configuration(MAM_SPAWN_METHOD, MAM_SPAWN_BASELINE, NULL);
  }

  if(mall_conf->spawn_method == MAM_SPAWN_MERGE) {
    if(MAM_I_contains_strat(mall_conf->spawn_strategies, MAM_MASK_SPAWN_INTERCOMM)) {
      MAM_I_remove_strat(&mall_conf->spawn_strategies, MAM_MASK_SPAWN_INTERCOMM);
    }
    // FIXME This should not be required to be removed for that case...
    if(mall->numP > mall->numC && MAM_I_contains_strat(mall_conf->spawn_strategies, MAM_MASK_SPAWN_SINGLE)) {
      MAM_I_remove_strat(&mall_conf->spawn_strategies, MAM_MASK_SPAWN_SINGLE);
    }
  }
  if(mall_conf->red_method == MAM_RED_RMA_LOCK || mall_conf->red_method == MAM_RED_RMA_LOCKALL) {
    if(MAM_I_contains_strat(mall_conf->spawn_strategies, MAM_MASK_SPAWN_INTERCOMM)) {
      MAM_I_remove_strat(&mall_conf->spawn_strategies, MAM_MASK_SPAWN_INTERCOMM);
    }
    if(!MAM_I_contains_strat(mall_conf->red_strategies, MAM_MASK_RED_WAIT_TARGETS) &&
       !MAM_I_contains_strat(mall_conf->red_strategies, MAM_MASK_PTHREAD)) {
      MAM_I_set_red_strat(MAM_STRAT_RED_WAIT_TARGETS, &mall_conf->red_strategies);
    }
  }

  #if MAM_DEBUG >= 2
    if(mall->myId == mall->root) {
      DEBUG_FUNC("MaM configuration", mall->myId, mall->numP); 
      printf("Spawn M=%d S=%d D=%d Redist M=%d S=%d\n", 
            mall_conf->spawn_method, mall_conf->spawn_strategies, mall_conf->spawn_dist, mall_conf->red_method, mall_conf->red_strategies);
      fflush(stdout);
    }
  #endif
}

//======================================================||
//================PRIVATE FUNCTIONS=====================||
//======================================================||
//======================================================||


int MAM_I_configuration_get_defaults() {
  size_t i;
  int set_value;
  char *tmp = NULL;
  
  mam_config_setting_t *config = NULL;
  for (i = 0; i < MAM_KEY_COUNT; i++) {
    config = &configSettings[i];
    tmp = getenv(config->env_name);

    if(tmp != NULL) {
      set_value = atoi(tmp);
    } else {
      set_value = config->default_value;
    }

    if (0 <= set_value && set_value < config->config_max_length) {
      if(i == MAM_NUM_TARGETS) {
        config->set_config_complex(set_value);
      } else {
        config->set_config_simple(set_value, config->value);
      }
    }
    tmp = NULL;
  }
  return 0;
}


int MAM_I_set_method(unsigned int new_method, unsigned int *method) {
  *method = new_method;
  return *method;
}

//TODO Se podría hacer un par de arrays o dict para obtener la mascara sin un switch
int MAM_I_set_spawn_strat(unsigned int strategy, unsigned int *strategies) {
  int result = 0;
  int strat_removed = 0;

  switch(strategy) {
    case MAM_STRAT_SPAWN_CLEAR:
      *strategies = MAM_STRAT_CLEAR_VALUE;
      result = MAM_STRATS_MODIFIED;
      break;
    case MAM_STRAT_SPAWN_PTHREAD:
      result = MAM_I_add_strat(strategies, MAM_MASK_PTHREAD);
      break;
    case MAM_STRAT_SPAWN_SINGLE:
      result = MAM_I_add_strat(strategies, MAM_MASK_SPAWN_SINGLE);
      if(result == MAM_STRATS_ADDED) {
        strat_removed += MAM_I_remove_strat(strategies, MAM_MASK_SPAWN_PARALLEL);
      }
      break;
    case MAM_STRAT_SPAWN_INTERCOMM:
      result = MAM_I_add_strat(strategies, MAM_MASK_SPAWN_INTERCOMM);
      break;
    case MAM_STRAT_SPAWN_MULTIPLE:
      result = MAM_I_add_strat(strategies, MAM_MASK_SPAWN_MULTIPLE);
      if(result == MAM_STRATS_ADDED) {
        strat_removed += MAM_I_remove_strat(strategies, MAM_MASK_SPAWN_PARALLEL);
      }
      break;
    case MAM_STRAT_SPAWN_PARALLEL:
      result = MAM_I_add_strat(strategies, MAM_MASK_SPAWN_PARALLEL);
      if(result == MAM_STRATS_ADDED) {
        strat_removed += MAM_I_remove_strat(strategies, MAM_MASK_SPAWN_MULTIPLE);
        strat_removed += MAM_I_remove_strat(strategies, MAM_MASK_SPAWN_SINGLE);
      }
      break;
    default:
      //Unkown strategy
      result = MAM_DENIED;
      break;
  }

  if(strat_removed) {
    result = MAM_STRATS_MODIFIED;
  }
  return result;
}

int MAM_I_set_red_strat(unsigned int strategy, unsigned int *strategies) {
  int result = 0;
  int strat_removed = 0;

  switch(strategy) {
    case MAM_STRAT_RED_CLEAR:
      *strategies = MAM_STRAT_CLEAR_VALUE;
      result = MAM_STRATS_MODIFIED;
      break;
    case MAM_STRAT_RED_PTHREAD: //TODO - IMPROVEMENT - This could be done with a single operation instead of 3.
      result = MAM_I_add_strat(strategies, MAM_MASK_PTHREAD);
      if(result == MAM_STRATS_ADDED) {
        strat_removed += MAM_I_remove_strat(strategies, MAM_MASK_RED_WAIT_SOURCES);
        strat_removed += MAM_I_remove_strat(strategies, MAM_MASK_RED_WAIT_TARGETS);
      }
      break;
    case MAM_STRAT_RED_WAIT_SOURCES:
      result = MAM_I_add_strat(strategies, MAM_MASK_RED_WAIT_SOURCES);
      if(result == MAM_STRATS_ADDED) {
        strat_removed += MAM_I_remove_strat(strategies, MAM_MASK_RED_WAIT_TARGETS);
        strat_removed += MAM_I_remove_strat(strategies, MAM_MASK_PTHREAD);
      }
      break;
    case MAM_STRAT_RED_WAIT_TARGETS:
      result = MAM_I_add_strat(strategies, MAM_MASK_RED_WAIT_TARGETS);
      if(result == MAM_STRATS_ADDED) {
        strat_removed += MAM_I_remove_strat(strategies, MAM_MASK_RED_WAIT_SOURCES);
        strat_removed += MAM_I_remove_strat(strategies, MAM_MASK_PTHREAD);
      }
      break;
    default:
      //Unkown strategy
      result = MAM_DENIED;
      break;
  }

  if(strat_removed) {
    result = MAM_STRATS_MODIFIED;
  }
  return result;
}

int MAM_I_set_target_number(unsigned int new_numC) {
  if(state > MAM_I_NOT_STARTED || new_numC == 0) return MAM_DENIED;

  mall->numC = (int) new_numC;
  return new_numC;
}


/*
 * Returns 1 if strategy is applied, 0 otherwise
 */
int MAM_I_contains_strat(unsigned int comm_strategies, unsigned int strategy) {
  return comm_strategies & strategy;
}

int MAM_I_add_strat(unsigned int *comm_strategies, unsigned int strategy) {
  if(MAM_I_contains_strat(*comm_strategies, strategy)) return MAM_OK;
  *comm_strategies |= strategy;
  return MAM_STRATS_ADDED;
}

int MAM_I_remove_strat(unsigned int *comm_strategies, unsigned int strategy) {
  if(!MAM_I_contains_strat(*comm_strategies, strategy)) return MAM_OK;
  *comm_strategies &= ~strategy;
  return MAM_STRATS_MODIFIED;
}