read_ini.c 11 KB
Newer Older
1
2
3
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
iker_martin's avatar
iker_martin committed
4
#include <mpi.h>
5
#include "read_ini.h"
iker_martin's avatar
iker_martin committed
6
#include "../malleability/ProcessDist.h"
7
8
#include "ini.h"

iker_martin's avatar
iker_martin committed
9

10
void malloc_config_arrays(configuration *user_config, int resizes);
iker_martin's avatar
iker_martin committed
11
12
13
void def_struct_config_file(configuration *config_file, MPI_Datatype *config_type);
void def_struct_config_file_array(configuration *config_file, MPI_Datatype *config_type);

14
15
16
17
18
19
20
/*
 * Funcion utilizada para leer el fichero de configuracion
 * y guardarlo en una estructura para utilizarlo en el futuro.
 *
 * Primero lee la seccion "general" y a continuacion cada una
 * de las secciones "resize%d".
 */
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
static int handler(void* user, const char* section, const char* name,
                   const char* value) {
    configuration* pconfig = (configuration*)user;

    char *resize_name = malloc(10 * sizeof(char));
    int act_resize = pconfig->actual_resize;
    snprintf(resize_name, 10, "resize%d", act_resize);

    #define MATCH(s, n) strcmp(section, s) == 0 && strcmp(name, n) == 0
    if (MATCH("general", "resizes")) {
        pconfig->resizes = atoi(value) + 1;
        malloc_config_arrays(pconfig, pconfig->resizes);

    } else if (MATCH("general", "matrix_tam")) {
        pconfig->matrix_tam = atoi(value);
36
37
    } else if (MATCH("general", "comm_tam")) {
        pconfig->comm_tam = atoi(value);
38
39
40
41
    } else if (MATCH("general", "SDR")) {
        pconfig->sdr = atoi(value);
    } else if (MATCH("general", "ADR")) {
        pconfig->adr = atoi(value);
42
    } else if (MATCH("general", "AIB")) { //TODO Refactor cambiar nombre
43
        pconfig->aib = atoi(value);
44
45
46
47
    } else if (MATCH("general", "CST")) {
        pconfig->cst = atoi(value);
    } else if (MATCH("general", "CSS")) {
        pconfig->css = atoi(value);
48
49
50
51
52
53
54
55
56
57
58
59
60
61
    } else if (MATCH("general", "time")) {
        pconfig->general_time = atof(value);

    // Resize	
    } else if (MATCH(resize_name, "iters")) {
        pconfig->iters[act_resize] = atoi(value);
    } else if (MATCH(resize_name, "procs")) {
        pconfig->procs[act_resize] = atoi(value);
    } else if (MATCH(resize_name, "factor")) {
        pconfig->factors[act_resize] = atof(value);
    } else if (MATCH(resize_name, "physical_dist")) {

	char *aux = strdup(value);
        if (strcmp(aux, "node") == 0) {
iker_martin's avatar
iker_martin committed
62
          pconfig->phy_dist[act_resize] = COMM_PHY_NODES;
63
	} else {
iker_martin's avatar
iker_martin committed
64
          pconfig->phy_dist[act_resize] = COMM_PHY_CPU;
65
	}
66

67
68
69
70
71
72
73
74
75
76
77
	free(aux);
        pconfig->actual_resize = pconfig->actual_resize+1; // Ultimo elemento del grupo

    } else {
        return 0;  /* unknown section or name, error */
    }
 
    free(resize_name);
    return 1;
}

78
79
80
81
82
83
84
/*
 * Crea y devuelve una estructura de configuracion a traves
 * de un nombre de fichero dado.
 *
 * La memoria de la estructura se reserva en la funcion y es conveniente
 * liberarla con la funcion "free_config()"
 */
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
configuration *read_ini_file(char *file_name) {
    configuration *config = NULL;

    config = malloc(sizeof(configuration) * 1);
    if(config == NULL) {
        printf("Error when reserving configuration structure\n");
	return NULL;
    }
    config->actual_resize=0;

    if(ini_parse(file_name, handler, config) < 0) { // Obtener configuracion
        printf("Can't load '%s'\n", file_name);
        return NULL;
    }
    return config;
}

/*
 * Reserva de memoria para los vectores de la estructura de configuracion
 *
105
106
107
108
109
110
111
 * Si se llama desde fuera de este fichero, la memoria de la estructura
 * tiene que reservarse con la siguiente linea:
 * "configuration *config = malloc(sizeof(configuration));"
 *
 * Sin embargo se puede obtener a traves de las funciones
 *  - read_ini_file
 *  - recv_config_file
112
113
114
115
116
 */
void malloc_config_arrays(configuration *user_config, int resizes) {
    if(user_config != NULL) {
      user_config->iters = malloc(sizeof(int) * resizes);
      user_config->procs = malloc(sizeof(int) * resizes);
iker_martin's avatar
iker_martin committed
117
      user_config->factors = malloc(sizeof(float) * resizes);
118
119
120
121
      user_config->phy_dist = malloc(sizeof(int) * resizes);
    }
}

122
123
124
/*
 * Libera toda la memoria de una estructura de configuracion
 */
125
126
void free_config(configuration *user_config) {
    if(user_config != NULL) {
127
128
129
130
      free(user_config->iters);
      free(user_config->procs);
      free(user_config->factors);
      free(user_config->phy_dist);
131

132
      free(user_config);
133
134
135
    }
}

136
/*
137
138
139
 * Imprime por salida estandar toda la informacion que contiene
 * la configuracion pasada como argumento
 */
140
void print_config(configuration *user_config, int grp) {
141
142
  if(user_config != NULL) {
    int i;
143
144
    printf("Config loaded: resizes=%d, matrix=%d, comm_tam=%d, sdr=%d, adr=%d, aib=%d, css=%d, cst=%d, time=%f || grp=%d\n",
        user_config->resizes, user_config->matrix_tam, user_config->comm_tam, user_config->sdr, user_config->adr, user_config->aib, user_config->css, user_config->cst, user_config->general_time, grp);
145
146
147
148
149
150
    for(i=0; i<user_config->resizes; i++) {
      printf("Resize %d: Iters=%d, Procs=%d, Factors=%f, Phy=%d\n",
        i, user_config->iters[i], user_config->procs[i], user_config->factors[i], user_config->phy_dist[i]);
    }
  }
}
iker_martin's avatar
iker_martin committed
151
152


153
154
155
156
/*
 * Imprime por salida estandar la informacion relacionada con un
 * solo grupo de procesos en su configuracion.
 */
157
158
159
160
161
162
163
164
165
166
167
void print_config_group(configuration *user_config, int grp) {
  if(user_config != NULL) {
    int parents, sons;
    parents = sons = 0;
    if(grp > 0) {
      parents = user_config->procs[grp-1];
    }
    if(grp < user_config->resizes - 1) {
      sons = user_config->procs[grp+1];
    }

168
169
    printf("Config: matrix=%d, comm_tam=%d, sdr=%d, adr=%d, aib=%d, css=%d, cst=%d, time=%f\n",
        user_config->matrix_tam, user_config->comm_tam, user_config->sdr, user_config->adr, user_config->aib, user_config->css, user_config->cst, user_config->general_time);
170
171
172
173
174
    printf("Config Group: iters=%d, factor=%f, phy=%d, procs=%d, parents=%d, sons=%d\n",
        user_config->iters[grp], user_config->factors[grp], user_config->phy_dist[grp], user_config->procs[grp], parents, sons);
  }
}

175
//||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ||
176
177
178
//||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ||
//| FUNCIONES DE INTERCOMUNICACION DE ESTRUCTURA DE CONFIGURACION ||
//||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ||
179
//||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| |/
iker_martin's avatar
iker_martin committed
180

181
182
183
184
185
186
187
188
/*
 * Envia una estructura de configuracion al grupo de procesos al que se 
 * enlaza este grupo a traves del intercomunicador pasado como argumento.
 *
 * Esta funcion tiene que ser llamada por todos los procesos del mismo grupo
 * e indicar cual es el proceso raiz que se encargara de enviar la
 * configuracion al otro grupo.
 */
iker_martin's avatar
iker_martin committed
189
190
191
192
void send_config_file(configuration *config_file, int root, MPI_Comm intercomm) {

  MPI_Datatype config_type, config_type_array;

193
194
  // Obtener un tipo derivado para enviar todos los
  // datos escalares con una sola comunicacion
iker_martin's avatar
iker_martin committed
195
196
  def_struct_config_file(config_file, &config_type);

197
198
199

  // Obtener un tipo derivado para enviar los tres vectores
  // de enteros con una sola comunicacion
iker_martin's avatar
iker_martin committed
200
  def_struct_config_file_array(config_file, &config_type_array);
201
202

  MPI_Bcast(config_file, 1, config_type, root, intercomm);
iker_martin's avatar
iker_martin committed
203
204
205
  MPI_Bcast(config_file, 1, config_type_array, root, intercomm);
  MPI_Bcast(config_file->factors, config_file->resizes, MPI_FLOAT, root, intercomm);

206
  //Liberar tipos derivados
iker_martin's avatar
iker_martin committed
207
208
209
210
  MPI_Type_free(&config_type);
  MPI_Type_free(&config_type_array);
}

211
212
213
214
215
216
217
218
219
220
221
/*
 * Recibe una estructura de configuracion desde otro grupo de procesos
 * y la devuelve. La memoria de la estructura se reserva en esta funcion.
 *
 * Esta funcion tiene que ser llamada por todos los procesos del mismo grupo
 * e indicar cual es el proceso raiz del otro grupo que se encarga de enviar
 * la configuracion a este grupo.
 *
 * La memoria de la configuracion devuelta tiene que ser liberada con
 * la funcion "free_config".
 */
iker_martin's avatar
iker_martin committed
222
223
224
225
configuration *recv_config_file(int root, MPI_Comm intercomm) {

  MPI_Datatype config_type, config_type_array;

226

iker_martin's avatar
iker_martin committed
227
228
  configuration *config_file = malloc(sizeof(configuration) * 1);

229
230
231
  // Obtener un tipo derivado para recibir todos los
  // datos escalares con una sola comunicacion
  def_struct_config_file(config_file, &config_type);
iker_martin's avatar
iker_martin committed
232
233
  MPI_Bcast(config_file, 1, config_type, root, intercomm);

234
235
236
  // Obtener un tipo derivado para enviar los tres vectores
  // de enteros con una sola comunicacion
  malloc_config_arrays(config_file, config_file->resizes); // Reserva de memoria de los vectores
iker_martin's avatar
iker_martin committed
237
238
239
240
241
  def_struct_config_file_array(config_file, &config_type_array);

  MPI_Bcast(config_file, 1, config_type_array, root, intercomm);
  MPI_Bcast(config_file->factors, config_file->resizes, MPI_FLOAT, root, intercomm);

242
  //Liberar tipos derivados
iker_martin's avatar
iker_martin committed
243
244
245
246
247
248
  MPI_Type_free(&config_type);
  MPI_Type_free(&config_type_array);

  return config_file;
}

249
250
251
252
/*
 * Tipo derivado para enviar 6 elementos especificos
 * de la estructura de configuracion con una sola comunicacion.
 */
iker_martin's avatar
iker_martin committed
253
void def_struct_config_file(configuration *config_file, MPI_Datatype *config_type) {
254
255
  int i, counts = 11;
  int blocklengths[11] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
iker_martin's avatar
iker_martin committed
256
257
258
259
  MPI_Aint displs[counts], dir;
  MPI_Datatype types[counts];

  // Rellenar vector types
260
261
262
  types[0] = types[1] = types[2] = types[3] = types[4] = types[5] = types[6] = types[7] = types[8] = MPI_INT;
  types[9] = MPI_FLOAT;
  types[10] = MPI_DOUBLE;
iker_martin's avatar
iker_martin committed
263

264
  // Rellenar vector displs
iker_martin's avatar
iker_martin committed
265
266
267
268
269
  MPI_Get_address(config_file, &dir);

  MPI_Get_address(&(config_file->resizes), &displs[0]);
  MPI_Get_address(&(config_file->actual_resize), &displs[1]);
  MPI_Get_address(&(config_file->matrix_tam), &displs[2]);
270
271
272
273
  MPI_Get_address(&(config_file->comm_tam), &displs[3]);
  MPI_Get_address(&(config_file->sdr), &displs[4]);
  MPI_Get_address(&(config_file->adr), &displs[5]);
  MPI_Get_address(&(config_file->aib), &displs[6]);
274
275
276
277
  MPI_Get_address(&(config_file->css), &displs[7]);
  MPI_Get_address(&(config_file->cst), &displs[8]);
  MPI_Get_address(&(config_file->general_time), &displs[9]);
  MPI_Get_address(&(config_file->Top), &displs[10]);
iker_martin's avatar
iker_martin committed
278
279
280
281
282
283
284

  for(i=0;i<counts;i++) displs[i] -= dir;

  MPI_Type_create_struct(counts, blocklengths, displs, types, config_type);
  MPI_Type_commit(config_type);
}

285
286
287
288
/*
 * Tipo derivado para enviar tres vectores de enteros
 * de la estructura de configuracion con una sola comunicacion.
 */
iker_martin's avatar
iker_martin committed
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
void def_struct_config_file_array(configuration *config_file, MPI_Datatype *config_type) {
  int i, counts = 3;
  int blocklengths[3] = {1, 1, 1};
  MPI_Aint displs[counts], dir;
  MPI_Datatype aux, types[counts];

  // Rellenar vector types
  types[0] = types[1] = types[2] = MPI_INT;

  // Modificar blocklengths al valor adecuado
  blocklengths[0] = blocklengths[1] = blocklengths[2] = config_file->resizes;

  //Rellenar vector displs
  MPI_Get_address(config_file, &dir);

  MPI_Get_address(config_file->iters, &displs[0]);
  MPI_Get_address(config_file->procs, &displs[1]);
  MPI_Get_address(config_file->phy_dist, &displs[2]);

  for(i=0;i<counts;i++) displs[i] -= dir;

310
  // Tipo derivado para enviar un solo elemento de tres vectores
iker_martin's avatar
iker_martin committed
311
  MPI_Type_create_struct(counts, blocklengths, displs, types, &aux);
312
313
  // Tipo derivado para enviar N elementos de tres vectores(3N en total)
  MPI_Type_create_resized(aux, 0, 1*sizeof(int), config_type); 
iker_martin's avatar
iker_martin committed
314
315
  MPI_Type_commit(config_type);
}