malleabilityTypes.c 11.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
void add_data(void *data, size_t total_qty, MPI_Datatype type, size_t request_qty, malleability_data_t *data_struct) {
24
  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
/*
 * 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.
 */
52
void modify_data(void *data, size_t index, size_t total_qty, MPI_Datatype type, size_t request_qty, malleability_data_t *data_struct) {
53
54
55
56
57
58
59
60
61
62
63
64
65
  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, type_size;
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
  if(is_children_group && ( data_struct_rep->entries != 0 || data_struct_dist->entries != 0 )) {
101
102
    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

  if(is_children_group) {
    for(i=0; i < data_struct_rep->entries; i++) {
110
111
      MPI_Type_size(data_struct_rep->types[i], &type_size);
      data_struct_rep->arrays[i] = (void *) malloc(data_struct_rep->qty[i] * type_size);
112
113
114
115
      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;
      }
116
117
    }
    for(i=0; i < data_struct_dist->entries; i++) {
118
      data_struct_dist->arrays[i] = (void *) NULL; // TODO Se podria inicializar aqui?
119
120
121
122
      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;
      }
123
124
    }
  }
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140

  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.
 */
141
void init_malleability_data_struct(malleability_data_t *data_struct, size_t size) {
142
143
  size_t i;

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

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
  MPI_Datatype *types_aux;
166
  MPI_Win *windows_aux;
167
168
169
170
  MPI_Request **requests_aux;
  void **arrays_aux;

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

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

183
184
185
186
187
  for(i=data_struct->max_entries; i<needed; i++) { //realloc does not ensure a NULL value
    requests_aux[i] = NULL;
    arrays_aux[i] = NULL;
  }

188
189
190
191
192
193
194
195
  // Check if old array can be freed
  if(data_struct->qty != qty_aux && data_struct->qty != NULL) free(data_struct->qty);
  if(data_struct->types != types_aux && data_struct->types != NULL) free(data_struct->types);
  if(data_struct->request_qty != request_qty_aux && data_struct->request_qty != NULL) free(data_struct->request_qty);
  if(data_struct->requests != requests_aux && data_struct->requests != NULL) free(data_struct->requests);
  if(data_struct->windows != windows_aux && data_struct->windows != NULL) free(data_struct->windows);
  if(data_struct->arrays != arrays_aux && data_struct->arrays != NULL) free(data_struct->arrays);

196
197
  data_struct->qty = qty_aux;
  data_struct->types = types_aux;
198
  data_struct->request_qty = request_qty_aux;
199
  data_struct->requests = requests_aux;
200
  data_struct->windows = windows_aux;
201
202
203
204
205
  data_struct->arrays = arrays_aux;
  data_struct->max_entries = needed;
}

void free_malleability_data_struct(malleability_data_t *data_struct) {
206
  size_t i, j, max;
207
208
209

  max = data_struct->entries;
  if(max != 0) {
210
211
212
213
214
215
    if(data_struct->qty != NULL) {
      free(data_struct->qty);
    }
    if(data_struct->types != NULL) {
      free(data_struct->types);
    }
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
    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);  
    }

    if(data_struct->windows != NULL) {
      free(data_struct->windows);
234
    }
235

236
237
238
    if(data_struct->arrays != NULL) {
      free(data_struct->arrays);
    }
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
  }
}

//======================================================||
//======================================================||
//================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;
254
255
256
257
258
  int blocklengths[counts];
  MPI_Aint displs[counts];
  MPI_Datatype types[counts];

  blocklengths[0] = blocklengths[1] = 1;
259
  types[0] = types[1] = MPI_UNSIGNED_LONG;
260
261

  // Obtener direccion base
262
263
  MPI_Get_address(&(data_struct_rep->entries), &displs[0]);
  MPI_Get_address(&(data_struct_dist->entries), &displs[1]);
264

265
  MPI_Type_create_struct(counts, blocklengths, displs, types, new_type);
266
267
268
269
270
271
272
273
  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.
274
 * TODO Refactor?
275
276
 */
void def_malleability_qty_type(malleability_data_t *data_struct_rep, malleability_data_t *data_struct_dist, MPI_Datatype *new_type) {
277
  int counts = 6;
278
  int blocklengths[counts];
279
  MPI_Aint displs[counts];
280
281
  MPI_Datatype types[counts];

282
283
284
285
  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;
286

287
  MPI_Get_address((data_struct_rep->qty), &displs[0]);
288
  MPI_Get_address((data_struct_rep->request_qty), &displs[1]);
289
  MPI_Get_address((data_struct_rep->types), &displs[2]); // MPI_Datatype uses typedef int to be declared
290
291
  MPI_Get_address((data_struct_dist->qty), &displs[3]);
  MPI_Get_address((data_struct_dist->request_qty), &displs[4]);
292
  MPI_Get_address((data_struct_dist->types), &displs[5]); // MPI_Datatype uses typedef int to be declared
293
294
295
296

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