malleabilityTypes.c 8.18 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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
  
  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;

  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;
  }
  data_struct->entries+=1;
}


/*
 * 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) {
52
53
  int is_intercomm, rootBcast = MPI_PROC_NULL;
  size_t i;
54
55
  MPI_Datatype entries_type, struct_type;

56
57
58
59

  MPI_Comm_test_inter(intercomm, &is_intercomm);
  if(is_intercomm && !is_children_group) {
    rootBcast = myId == root ? MPI_ROOT : MPI_PROC_NULL;
60
  } else {
61
    rootBcast = root;
62
63
64
65
  }

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

  if(is_children_group) {
69
70
    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);
71
72
73
  }

  def_malleability_qty_type(data_struct_dist, data_struct_rep, &struct_type);
74
75
76
77
78
79
80
81
82
83
84
85
86
  MPI_Bcast(MPI_BOTTOM, 1, struct_type, rootBcast, intercomm); //FIXME Doy error

  if(is_children_group) {
    //data_struct->requests[data_struct->entries] = (MPI_Request *) malloc(request_qty * sizeof(MPI_Request)); FIXME Crear los requests?
    //data_struct->requests[data_struct->entries][i] = MPI_REQUEST_NULL;
    
    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
    }
  }
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102

  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.
 */
103
void init_malleability_data_struct(malleability_data_t *data_struct, size_t size) {
104
  data_struct->max_entries = size;
105
  data_struct->qty = (size_t *) malloc(size * sizeof(size_t));
106
107
108
109
110
111
112
113
114
115
116
117
  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.
 */
118
119
120
void realloc_malleability_data_struct(malleability_data_t *data_struct, size_t qty_to_add) {
  size_t needed, *qty_aux;
  int *types_aux;
121
122
123
124
  MPI_Request **requests_aux;
  void **arrays_aux;

  needed = data_struct->max_entries + qty_to_add;
125
  qty_aux = (size_t *) realloc(data_struct->qty, needed * sizeof(int));
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
  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) {
143
  size_t i, max;
144
145
146
147

  max = data_struct->entries;
  if(max != 0) {
    for(i=0; i<max; i++) {
148
149
      //free(data_struct->arrays[i]); //FIXME Valores alojados con 1 elemento no se liberan?
      //free(data_struct->requests[i]); //TODO Plantear como crearlos
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
    }

    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;
171
172
173
174
175
  int blocklengths[counts];
  MPI_Aint displs[counts];
  MPI_Datatype types[counts];

  blocklengths[0] = blocklengths[1] = 1;
176
  types[0] = types[1] = MPI_UNSIGNED_LONG;
177
178

  // Obtener direccion base
179
180
  MPI_Get_address(&(data_struct_rep->entries), &displs[0]);
  MPI_Get_address(&(data_struct_dist->entries), &displs[1]);
181

182
  MPI_Type_create_struct(counts, blocklengths, displs, types, new_type);
183
184
185
186
187
188
189
190
  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.
191
 * TODO Refactor?
192
193
 */
void def_malleability_qty_type(malleability_data_t *data_struct_rep, malleability_data_t *data_struct_dist, MPI_Datatype *new_type) {
194
  int counts = 4;
195
  int blocklengths[counts];
196
  MPI_Aint displs[counts];
197
198
  MPI_Datatype types[counts];

199
200
  types[0] = types[2] = MPI_UNSIGNED_LONG;
  types[1] = types[3] = MPI_INT;
201
202
  blocklengths[0] = blocklengths[1] = data_struct_rep->entries;
  blocklengths[2] = blocklengths[3] = data_struct_dist->entries;
203

204
205
206
207
  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]);
208
209
210
211

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