results.c 6.65 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
14
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
60
61
62
63
64
/*
 * Define un tipo derivado de MPI para mandar los tiempos
 * con una sola comunicacion.
 *
 * En concreto son tres escales y un vector de tamaño "resizes"
 */
void def_results_type(results_data *results, int resizes, MPI_Datatype *results_type) {
  int i, counts = 4;
  int blocklengths[4] = {1, 1, 1, 1};
65
66
67
68
  MPI_Aint displs[counts], dir;
  MPI_Datatype types[counts];

  // Rellenar vector types
69
70
  types[0] = types[1] = types[2] = types[3] = MPI_DOUBLE;
  blocklengths[3] = 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
78
  MPI_Get_address(&(results->exec_start), &displs[2]);
  MPI_Get_address(&(results->spawn_time[0]), &displs[3]); //TODO Revisar si se puede simplificar
79
80
81
82
83
84
85
86
87
88
89
90

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

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

//======================================================||
//======================================================||
//===============PRINT RESULTS FUNCTIONS================||
//======================================================||
//======================================================||
91
92
93
94
95
96
97

/*
 * 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.
 */
98
99
100
101
102
103
104
105
void print_iter_results(results_data *results, int last_normal_iter_index) {
  int i, aux;

  printf("Titer: ");
  for(i=0; i< results->iter_index; i++) {
    printf("%lf ", results->iters_time[i]);
  }

106
  printf("\nTtype: "); //FIXME modificar a imprimir solo la cantidad de asincronas
107
108
109
110
  for(i=0; i< results->iter_index; i++) {
    printf("%d ", results->iters_type[i] == 0);
  }

111
  printf("\nTop: "); //TODO modificar a imprimir solo cuantas operaciones cuestan una iteracion?
112
113
114
115
116
117
118
  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];
    printf("%d ", aux);
  }
  printf("\n");
}

119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/*
 * 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.
 */
void print_global_results(results_data *results, int resizes) {
  int i;

  printf("Tspawn: ");
  for(i=0; i< resizes - 1; i++) {
    printf("%lf ", results->spawn_time[i]);
  }

  printf("\nTsync: ");
  for(i=1; i < resizes; i++) {
    printf("%lf ", results->sync_time[i]);
  }

  printf("\nTasync: ");
  for(i=1; i < resizes; i++) {
    printf("%lf ", results->async_time[i]);
  }

  printf("\nTex: %lf\n", results->exec_time);
}

145
146
147
148
149
150
//======================================================||
//======================================================||
//=============INIT/FREE RESULTS FUNCTIONS==============||
//======================================================||
//======================================================||

151
152
153
154
155
156
/*
 * 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.
 */
157
158
159
160
161
162
163
void init_results_data(results_data **results, int resizes, int iters_size) {
  *results = malloc(1 * sizeof(results_data));

  (*results)->spawn_time = calloc(resizes, sizeof(double));
  (*results)->sync_time = calloc(resizes, sizeof(double));
  (*results)->async_time = calloc(resizes, sizeof(double));

164
  (*results)->iters_size = iters_size + 100;
165
  (*results)->iters_time = calloc(iters_size + 100, sizeof(double)); //FIXME Numero magico
166
  (*results)->iters_type = calloc(iters_size + 100, sizeof(int));
167
168
169
  (*results)->iter_index = 0;
}

170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
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, "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;
}

186
187
188
/*
 * Libera toda la memoria asociada con una estructura de resultados.
 */
189
void free_results_data(results_data **results) {
190
191
192
    free((*results)->spawn_time);
    free((*results)->sync_time);
    free((*results)->async_time);
193
194
195
196
197

    free((*results)->iters_time);
    free((*results)->iters_type);
    free(*results);
}