malleabilityTypes.c 9.21 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
35
  
  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;

36
37
38
39
40
  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;
    }
41
42
43
44
  }
  data_struct->entries+=1;
}

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
/*
 * 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;

  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;
    }
  }
}
73
74
75
76
77
78
79
80
81

/*
 * 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) {
82
83
  int is_intercomm, rootBcast = MPI_PROC_NULL;
  size_t i;
84
85
  MPI_Datatype entries_type, struct_type;

86
87
88
89

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

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

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

  def_malleability_qty_type(data_struct_dist, data_struct_rep, &struct_type);
104
  MPI_Bcast(MPI_BOTTOM, 1, struct_type, rootBcast, intercomm);
105
106

  if(is_children_group) {
107
108
109
110
111
   /* 
    size_t request_qty = 1; // TODO Obtener desde la funcion
    data_struct_rep->requests[data_struct_rep->entries] = (MPI_Request *) malloc(request_qty * sizeof(MPI_Request));
    data_struct_dist->requests[data_struct_dist->entries] = (MPI_Request *) malloc(request_qty * sizeof(MPI_Request));
   */
112
113
114
115
116
117
118
119
    
    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
    }
    for(i=0; i < data_struct_dist->entries; i++) {
      data_struct_dist->arrays[i] = (void *) malloc(data_struct_dist->qty[i] * sizeof(int)); //TODO Tener en cuenta que no siempre es int
    }
  }
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135

  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.
 */
136
void init_malleability_data_struct(malleability_data_t *data_struct, size_t size) {
137
  data_struct->max_entries = size;
138
  data_struct->qty = (size_t *) malloc(size * sizeof(size_t));
139
140
141
142
143
144
145
146
147
148
149
150
  data_struct->types = (int *) malloc(size * sizeof(int));
  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;
}

/*
 * 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.
 */
151
152
153
void realloc_malleability_data_struct(malleability_data_t *data_struct, size_t qty_to_add) {
  size_t needed, *qty_aux;
  int *types_aux;
154
155
156
157
  MPI_Request **requests_aux;
  void **arrays_aux;

  needed = data_struct->max_entries + qty_to_add;
158
  qty_aux = (size_t *) realloc(data_struct->qty, needed * sizeof(int));
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
  types_aux = (int *) realloc(data_struct->types, needed * sizeof(int));
  requests_aux = (MPI_Request **) realloc(data_struct->requests, needed * sizeof(MPI_Request *));
  arrays_aux = (void **) realloc(data_struct->arrays, needed * sizeof(void *));

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

  data_struct->qty = qty_aux;
  data_struct->types = types_aux;
  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) {
176
  size_t i, max;
177
178
179
180

  max = data_struct->entries;
  if(max != 0) {
    for(i=0; i<max; i++) {
181
182
      //free(data_struct->arrays[i]); //FIXME Valores alojados con 1 elemento no se liberan?
      //free(data_struct->requests[i]); //TODO Plantear como crearlos
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
    }

    free(data_struct->qty);
    free(data_struct->types);
    free(data_struct->requests);
    free(data_struct->arrays);
  }
}

//======================================================||
//======================================================||
//================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;
204
205
206
207
208
  int blocklengths[counts];
  MPI_Aint displs[counts];
  MPI_Datatype types[counts];

  blocklengths[0] = blocklengths[1] = 1;
209
  types[0] = types[1] = MPI_UNSIGNED_LONG;
210
211

  // Obtener direccion base
212
213
  MPI_Get_address(&(data_struct_rep->entries), &displs[0]);
  MPI_Get_address(&(data_struct_dist->entries), &displs[1]);
214

215
  MPI_Type_create_struct(counts, blocklengths, displs, types, new_type);
216
217
218
219
220
221
222
223
  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.
224
 * TODO Refactor?
225
226
 */
void def_malleability_qty_type(malleability_data_t *data_struct_rep, malleability_data_t *data_struct_dist, MPI_Datatype *new_type) {
227
  int counts = 4;
228
  int blocklengths[counts];
229
  MPI_Aint displs[counts];
230
231
  MPI_Datatype types[counts];

232
233
  types[0] = types[2] = MPI_UNSIGNED_LONG;
  types[1] = types[3] = MPI_INT;
234
235
  blocklengths[0] = blocklengths[1] = data_struct_rep->entries;
  blocklengths[2] = blocklengths[3] = data_struct_dist->entries;
236

237
238
239
240
  MPI_Get_address((data_struct_rep->qty), &displs[0]);
  MPI_Get_address((data_struct_rep->types), &displs[1]);
  MPI_Get_address((data_struct_dist->qty), &displs[2]);
  MPI_Get_address((data_struct_dist->types), &displs[3]);
241
242
243
244

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