malleabilityTypes.c 10.7 KB
Newer Older
1
2
3
#include "malleabilityTypes.h"


4
5
void init_malleability_data_struct(malleability_data_t *data_struct, size_t size);
void realloc_malleability_data_struct(malleability_data_t *data_struct, size_t qty_to_add);
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

void def_malleability_entries(malleability_data_t *data_struct_rep, malleability_data_t *data_struct_dist, MPI_Datatype *new_type);
void def_malleability_qty_type(malleability_data_t *data_struct_rep, malleability_data_t *data_struct_dist, MPI_Datatype *new_type);


//======================================================||
//======================================================||
//===================PUBLIC FUNCTIONS===================||
//======================================================||
//======================================================||

/*
 * Anyade en la estructura de datos a comunicar con los hijos
 * un nuevo set de datos de un total "total_qty" distribuido entre
 * todos los padres. La nueva serie "data" solo representa los datos
 * que tiene este padre.
 */
23
24
void add_data(void *data, size_t total_qty, int type, size_t request_qty, malleability_data_t *data_struct) {
  size_t i;
25
26
27
28
29
30
31
32
33
34
  
  if(data_struct->entries == 0) {
    init_malleability_data_struct(data_struct, MALLEABILITY_INIT_DATA_QTY);
  } else if(data_struct->entries == data_struct->max_entries) {
    realloc_malleability_data_struct(data_struct, MALLEABILITY_INIT_DATA_QTY);
  }
  
  data_struct->qty[data_struct->entries] = total_qty;
  data_struct->types[data_struct->entries] = type;
  data_struct->arrays[data_struct->entries] = data;
35
  data_struct->request_qty[data_struct->entries] = request_qty;
36

37
38
39
40
41
  if(request_qty) {
    data_struct->requests[data_struct->entries] = (MPI_Request *) malloc(request_qty * sizeof(MPI_Request));
    for(i=0; i < request_qty; i++) {
      data_struct->requests[data_struct->entries][i] = MPI_REQUEST_NULL;
    }
42
43
44
45
  }
  data_struct->entries+=1;
}

46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
/*
 * Modifica en la estructura de datos a comunicar con los hijos
 * un set de datos de un total "total_qty" distribuido entre
 * todos los padres. La nueva serie "data" solo representa los datos
 * que tiene este padre.
 */
void modify_data(void *data, size_t index, size_t total_qty, int type, size_t request_qty, malleability_data_t *data_struct) {
  size_t i;
  
  if(data_struct->entries < index) { // Index does not exist
    return;
  }
  if(data_struct->requests[index] != NULL) {
    //free(data_struct->requests[index]); TODO Error when trying to free
    data_struct->requests[index] = NULL;
  }

  data_struct->qty[index] = total_qty;
  data_struct->types[index] = type;
  data_struct->arrays[index] = data;
66
  data_struct->request_qty[index] = request_qty;
67
68
69
70
71
72
73
74

  if(request_qty) {
    data_struct->requests[index] = (MPI_Request *) malloc(request_qty * sizeof(MPI_Request));
    for(i=0; i < request_qty; i++) {
      data_struct->requests[index][i] = MPI_REQUEST_NULL;
    }
  }
}
75
76
77
78
79
80
81
82
83

/*
 * Comunicar desde los padres a los hijos las estructuras de datos sincronas o asincronas
 * No es necesario que las estructuras esten inicializadas para un buen funcionamiento.
 *
 * En el argumento "root" todos tienen que indicar quien es el proceso raiz de los padres
 * unicamente.
 */
void comm_data_info(malleability_data_t *data_struct_rep, malleability_data_t *data_struct_dist, int is_children_group, int myId, int root, MPI_Comm intercomm) {
84
  int is_intercomm, rootBcast = MPI_PROC_NULL;
85
  size_t i, j;
86
87
  MPI_Datatype entries_type, struct_type;

88
89
90
91

  MPI_Comm_test_inter(intercomm, &is_intercomm);
  if(is_intercomm && !is_children_group) {
    rootBcast = myId == root ? MPI_ROOT : MPI_PROC_NULL;
92
  } else {
93
    rootBcast = root;
94
95
96
97
  }

  // Mandar primero numero de entradas
  def_malleability_entries(data_struct_dist, data_struct_rep, &entries_type);
98
  MPI_Bcast(MPI_BOTTOM, 1, entries_type, rootBcast, intercomm);
99

100
101
102
  if(is_children_group && ( data_struct_rep->entries != 0 || data_struct_dist->entries != 0 )) {
    init_malleability_data_struct(data_struct_rep, data_struct_rep->entries);
    init_malleability_data_struct(data_struct_dist, data_struct_dist->entries);
103
104
105
  }

  def_malleability_qty_type(data_struct_dist, data_struct_rep, &struct_type);
106
  MPI_Bcast(MPI_BOTTOM, 1, struct_type, rootBcast, intercomm);
107
108
109
110

  if(is_children_group) {
    for(i=0; i < data_struct_rep->entries; i++) {
      data_struct_rep->arrays[i] = (void *) malloc(data_struct_rep->qty[i] * sizeof(int)); //TODO Tener en cuenta que no siempre es int
111
112
113
114
      data_struct_rep->requests[i] = (MPI_Request *) malloc(data_struct_rep->request_qty[i] * sizeof(MPI_Request));
      for(j=0; j < data_struct_rep->request_qty[i]; j++) {
        data_struct_rep->requests[i][j] = MPI_REQUEST_NULL;
      }
115
116
    }
    for(i=0; i < data_struct_dist->entries; i++) {
117
      data_struct_dist->arrays[i] = (void *) NULL;
118
119
120
121
      data_struct_dist->requests[i] = (MPI_Request *) malloc(data_struct_dist->request_qty[i] * sizeof(MPI_Request));
      for(j=0; j < data_struct_dist->request_qty[i]; j++) {
        data_struct_dist->requests[i][j] = MPI_REQUEST_NULL;
      }
122
123
    }
  }
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139

  MPI_Type_free(&entries_type);
  MPI_Type_free(&struct_type);
}

//======================================================||
//======================================================||
//=========INIT/REALLOC/FREE RESULTS FUNCTIONS==========||
//======================================================||
//======================================================||

/*
 * Inicializa la estructura que describe una serie de datos con las mismas
 * caracteristicas de localización y uso. Se inicializa para utilizar hasta
 * "size" elementos.
 */
140
void init_malleability_data_struct(malleability_data_t *data_struct, size_t size) {
141
142
  size_t i;

143
  data_struct->max_entries = size;
144
  data_struct->qty = (size_t *) malloc(size * sizeof(size_t));
145
  data_struct->types = (int *) malloc(size * sizeof(int));
146
  data_struct->request_qty = (size_t *) malloc(size * sizeof(size_t));
147
148
149
150
  data_struct->requests = (MPI_Request **) malloc(size * sizeof(MPI_Request *));
  data_struct->arrays = (void **) malloc(size * sizeof(void *));

  data_struct->request_ibarrier = MPI_REQUEST_NULL;
151
152
153
154
155

  for(i=0; i<size; i++) { //calloc and memset does not ensure a NULL value
    data_struct->requests[i] = NULL;
    data_struct->arrays[i] = NULL;
  }
156
157
158
159
160
161
162
}

/*
 * Realoja la estructura que describe una serie de datos con las mismas
 * caracteristicas de localización y uso. Se anyaden "size" entradas nuevas
 * a las ya existentes.
 */
163
void realloc_malleability_data_struct(malleability_data_t *data_struct, size_t qty_to_add) {
164
  size_t i, needed, *qty_aux, *request_qty_aux;
165
  int *types_aux;
166
167
168
169
  MPI_Request **requests_aux;
  void **arrays_aux;

  needed = data_struct->max_entries + qty_to_add;
170
  qty_aux = (size_t *) realloc(data_struct->qty, needed * sizeof(int));
171
  types_aux = (int *) realloc(data_struct->types, needed * sizeof(int));
172
  request_qty_aux = (size_t *) realloc(data_struct->request_qty, needed * sizeof(int));
173
174
175
  requests_aux = (MPI_Request **) realloc(data_struct->requests, needed * sizeof(MPI_Request *));
  arrays_aux = (void **) realloc(data_struct->arrays, needed * sizeof(void *));

176
  if(qty_aux == NULL || arrays_aux == NULL || requests_aux == NULL || types_aux == NULL || request_qty_aux == NULL) {
177
178
179
180
    fprintf(stderr, "Fatal error - No se ha podido realojar la memoria constante de datos a redistribuir/comunicar\n");
    MPI_Abort(MPI_COMM_WORLD, 1);
  }

181
182
183
184
185
  for(i=data_struct->max_entries; i<needed; i++) { //calloc and memset does not ensure a NULL value
    requests_aux[i] = NULL;
    arrays_aux[i] = NULL;
  }

186
187
  data_struct->qty = qty_aux;
  data_struct->types = types_aux;
188
  data_struct->request_qty = request_qty_aux;
189
190
191
192
193
194
  data_struct->requests = requests_aux;
  data_struct->arrays = arrays_aux;
  data_struct->max_entries = needed;
}

void free_malleability_data_struct(malleability_data_t *data_struct) {
195
  size_t i, j, max;
196
197
198
199

  max = data_struct->entries;
  if(max != 0) {
    for(i=0; i<max; i++) {
200
      //free(data_struct->arrays[i]); //FIXME Valores alojados con 1 elemento no se liberan?
201
202
    }

203
204
205
206
207
208
    if(data_struct->qty != NULL) {
      free(data_struct->qty);
    }
    if(data_struct->types != NULL) {
      free(data_struct->types);
    }
209
210
211
212
213
214
215
216
217
218
219
220
221
222
    if(data_struct->requests != NULL && data_struct->request_qty != NULL) {
      for(i=0; i<max; i++) {
        if(data_struct->requests[i] != NULL) {
	  for(j=0; j<data_struct->request_qty[i]; j++) {
	    if(data_struct->requests[i][j] != MPI_REQUEST_NULL) {
              MPI_Request_free(&(data_struct->requests[i][j]));
	      data_struct->requests[i][j] = MPI_REQUEST_NULL;
	    }
	  }
          free(data_struct->requests[i]);
	}
      }
      free(data_struct->request_qty);
      free(data_struct->requests);  
223
    }
224

225
226
227
    if(data_struct->arrays != NULL) {
      free(data_struct->arrays);
    }
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
  }
}

//======================================================||
//======================================================||
//================MPI DERIVED DATATYPES=================||
//======================================================||
//======================================================||

/*
 * Crea un tipo derivado para mandar el numero de entradas
 * en dos estructuras de descripcion de datos.
 */
void def_malleability_entries(malleability_data_t *data_struct_rep, malleability_data_t *data_struct_dist, MPI_Datatype *new_type) {
  int counts = 2;
243
244
245
246
247
  int blocklengths[counts];
  MPI_Aint displs[counts];
  MPI_Datatype types[counts];

  blocklengths[0] = blocklengths[1] = 1;
248
  types[0] = types[1] = MPI_UNSIGNED_LONG;
249
250

  // Obtener direccion base
251
252
  MPI_Get_address(&(data_struct_rep->entries), &displs[0]);
  MPI_Get_address(&(data_struct_dist->entries), &displs[1]);
253

254
  MPI_Type_create_struct(counts, blocklengths, displs, types, new_type);
255
256
257
258
259
260
261
262
  MPI_Type_commit(new_type);
}

/*
 * Crea un tipo derivado para mandar las cantidades y tipo
 * de datos de dos estructuras de descripcion de datos.
 * El vector de "requests" no es enviado ya que solo es necesario
 * en los padres.
263
 * TODO Refactor?
264
265
 */
void def_malleability_qty_type(malleability_data_t *data_struct_rep, malleability_data_t *data_struct_dist, MPI_Datatype *new_type) {
266
  int counts = 6;
267
  int blocklengths[counts];
268
  MPI_Aint displs[counts];
269
270
  MPI_Datatype types[counts];

271
272
273
274
  types[0] = types[1] = types[3] = types[4] = MPI_UNSIGNED_LONG;
  types[2] = types[5] = MPI_INT;
  blocklengths[0] = blocklengths[1] = blocklengths[2] = data_struct_rep->entries;
  blocklengths[3] = blocklengths[4] = blocklengths[5] = data_struct_dist->entries;
275

276
  MPI_Get_address((data_struct_rep->qty), &displs[0]);
277
278
279
280
281
  MPI_Get_address((data_struct_rep->request_qty), &displs[1]);
  MPI_Get_address((data_struct_rep->types), &displs[2]);
  MPI_Get_address((data_struct_dist->qty), &displs[3]);
  MPI_Get_address((data_struct_dist->request_qty), &displs[4]);
  MPI_Get_address((data_struct_dist->types), &displs[5]);
282
283
284
285

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