results.c 9.13 KB
Newer Older
1
2
3
4
5
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
#include "results.h"

6
void def_results_type(results_data *results, int resizes, MPI_Datatype *results_type);
7
8
9
10
11
12

//======================================================||
//======================================================||
//================MPI RESULTS FUNCTIONS=================||
//======================================================||
//======================================================||
13

Iker Martín's avatar
Iker Martín committed
14
//TODO Generalizar ambas funciones en una sola
15
16
17
18
19
20
21
22
23
/*
 * Envia una estructura de resultados 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 los
 * resultados al otro grupo.
 */
void send_results(results_data *results, int root, int resizes, MPI_Comm intercomm) {
24
25
26
27
  MPI_Datatype results_type;

  // Obtener un tipo derivado para enviar todos los
  // datos escalares con una sola comunicacion
28
  def_results_type(results, resizes, &results_type);
29
30
31
32
33
34
  MPI_Bcast(results, 1, results_type, root, intercomm);

  //Liberar tipos derivados
  MPI_Type_free(&results_type);
}

35
36
37
38
39
40
41
42
43
44
/*
 * Recibe una estructura de resultados desde otro grupo de procesos
 * y la devuelve. La memoria de la estructura se tiene que reservar con antelacion
 * con la función "init_results_data".
 *
 * 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
 * los resultados a este grupo.
 */
void recv_results(results_data *results, int root, int resizes, MPI_Comm intercomm) {
45
46
47
48
  MPI_Datatype results_type;

  // Obtener un tipo derivado para enviar todos los
  // datos escalares con una sola comunicacion
49
  def_results_type(results, resizes, &results_type);
50
51
52
53
54
55
  MPI_Bcast(results, 1, results_type, root, intercomm);

  //Liberar tipos derivados
  MPI_Type_free(&results_type);
}

56
57
58
59
/*
 * Define un tipo derivado de MPI para mandar los tiempos
 * con una sola comunicacion.
 *
Iker Martín's avatar
Iker Martín committed
60
 * En concreto son tres escalares y dos vectores de tamaño "resizes"
61
62
 */
void def_results_type(results_data *results, int resizes, MPI_Datatype *results_type) {
Iker Martín's avatar
Iker Martín committed
63
64
  int i, counts = 5;
  int blocklengths[] = {1, 1, 1, 1, 1};
65
66
67
68
  MPI_Aint displs[counts], dir;
  MPI_Datatype types[counts];

  // Rellenar vector types
Iker Martín's avatar
Iker Martín committed
69
70
  types[0] = types[1] = types[2] = types[3] = types[4] = MPI_DOUBLE;
  blocklengths[3] = blocklengths[4] = resizes;
71
72
73
74
75
76

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

  MPI_Get_address(&(results->sync_start), &displs[0]);
  MPI_Get_address(&(results->async_start), &displs[1]);
77
  MPI_Get_address(&(results->exec_start), &displs[2]);
Iker Martín's avatar
Iker Martín committed
78
79
  MPI_Get_address(&(results->spawn_real_time[0]), &displs[3]);
  MPI_Get_address(&(results->spawn_time[0]), &displs[4]); //TODO Revisar si se puede simplificar //FIXME Si hay mas de un spawn error?
80
81
82
83
84
85

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

  MPI_Type_create_struct(counts, blocklengths, displs, types, results_type);
  MPI_Type_commit(results_type);
}
Iker Martín's avatar
Iker Martín committed
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
//======================================================||
//======================================================||
//================SET RESULTS FUNCTIONS=================||
//======================================================||
//======================================================||

/*
 * Guarda los resultados respecto a la redistribución de datos
 * tras una reconfiguración. A llamar por los hijos tras
 * terminar la redistribución y obtener la configuración.
 */
void set_results_post_reconfig(results_data *results, int grp, int sdr, int adr) {
  if(sdr) { // Si no hay datos sincronos, el tiempo es 0
    results->sync_time[grp]  = results->sync_end - results->sync_start;
  } else {
    results->sync_time[grp]  = 0;
  }
  if(adr) { // Si no hay datos asincronos, el tiempo es 0
    results->async_time[grp]  = results->async_end - results->async_start;
  } else {
    results->async_time[grp]  = 0;
  }
}

/*
 * Pone el indice del siguiente elemento a escribir a 0 para los vectores
 * que tengan que ver con las iteraciones.
 * Por tanto, todos los anteriores valores de esos vectores pasan a ser invalidos
 * si se intentan acceder desde un código externo.
 *
 * Solo es necesario llamar a esta funcion cuando se ha realizado una
 * expansion con el metodo MERGE
 */
void reset_results_index(results_data *results) {
  results->iter_index = 0;
}


/*
 * Obtiene para cada iteracion, el tiempo maximo entre todos los procesos
 * que han participado.
 *
 * Es necesario obtener el maximo, pues es el que representa el tiempo real
 * que se ha utilizado.
 */
void compute_results_iter(results_data *results, int myId, int root, MPI_Comm comm) {
  if(myId == root)
    MPI_Reduce(MPI_IN_PLACE, results->iters_time, results->iter_index, MPI_DOUBLE, MPI_MAX, root, comm);
  else
    MPI_Reduce(results->iters_time, NULL, results->iter_index, MPI_DOUBLE, MPI_MAX, root, comm);
}
137
138
139
140
141
142

//======================================================||
//======================================================||
//===============PRINT RESULTS FUNCTIONS================||
//======================================================||
//======================================================||
143
144
145
146
147
148
149

/*
 * Imprime por pantalla los resultados locales.
 * Estos son los relacionados con las iteraciones, que son el tiempo
 * por iteracion, el tipo (Normal o durante communicacion asincrona)
 * y cuantas operaciones internas se han realizado en cada iteracion.
 */
Iker Martín's avatar
Iker Martín committed
150
void print_iter_results(results_data results, int last_normal_iter_index) {
151
152
153
  int i, aux;

  printf("Titer: ");
Iker Martín's avatar
Iker Martín committed
154
155
  for(i=0; i< results.iter_index; i++) {
    printf("%lf ", results.iters_time[i]);
156
157
  }

158
  printf("\nTtype: "); //FIXME modificar a imprimir solo la cantidad de asincronas
Iker Martín's avatar
Iker Martín committed
159
160
  for(i=0; i< results.iter_index; i++) {
    printf("%d ", results.iters_type[i] == 0);
161
162
  }

Iker Martín's avatar
Iker Martín committed
163
164
165
  printf("\nTop: "); //TODO modificar a imprimir solo cuantas operaciones cuestan una iteracion?
  for(i=0; i< results.iter_index; i++) {
    aux = results.iters_type[i] == 0 ? results.iters_type[last_normal_iter_index] : results.iters_type[i];
166
167
168
169
170
    printf("%d ", aux);
  }
  printf("\n");
}

171
172
173
174
175
/*
 * Imprime por pantalla los resultados globales.
 * Estos son el tiempo de creacion de procesos, los de comunicacion
 * asincrona y sincrona y el tiempo total de ejecucion.
 */
Iker Martín's avatar
Iker Martín committed
176
void print_global_results(results_data results, int resizes) {
177
178
  int i;

Iker Martín's avatar
Iker Martín committed
179
180
181
182
183
184
  printf("Tspawn: ");  // FIXME REFACTOR Cambiar nombre a T_resize_real
  for(i=0; i< resizes - 1; i++) {
    printf("%lf ", results.spawn_time[i]);
  }

  printf("\nTspawn_real: "); // FIXME REFACTOR Cambiar nombre a T_resize
185
  for(i=0; i< resizes - 1; i++) {
Iker Martín's avatar
Iker Martín committed
186
    printf("%lf ", results.spawn_real_time[i]);
187
188
189
190
  }

  printf("\nTsync: ");
  for(i=1; i < resizes; i++) {
Iker Martín's avatar
Iker Martín committed
191
    printf("%lf ", results.sync_time[i]);
192
193
194
195
  }

  printf("\nTasync: ");
  for(i=1; i < resizes; i++) {
Iker Martín's avatar
Iker Martín committed
196
    printf("%lf ", results.async_time[i]);
197
198
  }

Iker Martín's avatar
Iker Martín committed
199
  printf("\nTex: %lf\n", results.exec_time);
200
201
}

202
203
204
205
206
207
//======================================================||
//======================================================||
//=============INIT/FREE RESULTS FUNCTIONS==============||
//======================================================||
//======================================================||

208
209
210
211
212
213
/*
 * Inicializa los datos relacionados con una estructura de resultados.
 *
 * Los argumentos "resizes" y "iters_size" se necesitan para obtener el tamaño
 * de los vectores de resultados.
 */
Iker Martín's avatar
Iker Martín committed
214
215
void init_results_data(results_data *results, int resizes, int iters_size) {
  //*results = malloc(1 * sizeof(results_data)); FIXME Borrar
216

Iker Martín's avatar
Iker Martín committed
217
218
219
220
  results->spawn_time = calloc(resizes, sizeof(double));
  results->spawn_real_time = calloc(resizes, sizeof(double));
  results->sync_time = calloc(resizes, sizeof(double));
  results->async_time = calloc(resizes, sizeof(double));
221

Iker Martín's avatar
Iker Martín committed
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
  results->iters_size = iters_size + 100;
  results->iters_time = calloc(iters_size + 100, sizeof(double)); //FIXME Numero magico
  results->iters_type = calloc(iters_size + 100, sizeof(int));
  results->iter_index = 0;

}

void realloc_results_iters(results_data *results, int needed) {
  double *time_aux;
  int *type_aux;

  time_aux = (double *) realloc(results->iters_time, needed * sizeof(double));
  type_aux = (int *) realloc(results->iters_type, needed * sizeof(int));

  if(time_aux == NULL || type_aux == NULL) {
    fprintf(stderr, "Fatal error - No se ha podido realojar la memoria de resultados\n");
    MPI_Abort(MPI_COMM_WORLD, 1);
  }

  results->iters_time = time_aux;
  results->iters_type = type_aux;
243
244
}

245
246
/*
 * Libera toda la memoria asociada con una estructura de resultados.
Iker Martín's avatar
Iker Martín committed
247
 * TODO Asegurar que ha sido inicializado?
248
 */
Iker Martín's avatar
Iker Martín committed
249
250
251
252
253
254
255
256
257
258
259
void free_results_data(results_data *results) {
    if(results != NULL) {
      free(results->spawn_time);
      free(results->spawn_real_time);
      free(results->sync_time);
      free(results->async_time);

      free(results->iters_time);
      free(results->iters_type);
      }
      //free(*results); FIXME Borrar
260
}