Main.c 6.62 KB
Newer Older
1
2
3
4
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
#include "../IOcodes/read_ini.h"
iker_martin's avatar
iker_martin committed
5
6
#include "../malleability/ProcessDist.h"
#include "../malleability/CommDist.h"
7
8
9

#define ROOT 0

iker_martin's avatar
iker_martin committed
10
11
12
13
14
15
int work();
void Sons_init();

int checkpoint(int iter);
void TC(int numS);

16
17
18
19
void iterate(double *matrix, int n);
void computeMatrix(double *matrix, int n);
void initMatrix(double **matrix, int n);

iker_martin's avatar
iker_martin committed
20
21
22
23
24
25
26
27
28
29
30
31
32
33
typedef struct {
  int myId;
  int numP;
  int grp;


  MPI_Comm children, parents;
  char **argv;
  char *sync_array;
} group_data;

configuration *config_file;
group_data *group;

34
35
36
37
38
int main(int argc, char *argv[]) {
    int numP, myId;

    MPI_Init(&argc, &argv);
    MPI_Comm_size(MPI_COMM_WORLD, &numP);
iker_martin's avatar
iker_martin committed
39
40
41
42
43
44
45
46
47
    MPI_Comm_rank(MPI_COMM_WORLD, &myId);

    group = malloc(1 * sizeof(group_data));
    group->myId = myId;
    group->numP = numP;
    group->grp  = 0;
    group->argv = argv;

    MPI_Comm_get_parent(&(group->parents));
48
    if(group->parents != MPI_COMM_NULL ) { // Si son procesos hijos deben comunicarse con las padres
iker_martin's avatar
iker_martin committed
49
      Sons_init();
50
    } else { // Si son el primer grupo de procesos, recogen la configuracion inicial
iker_martin's avatar
iker_martin committed
51
52
53
      config_file = read_ini_file(argv[1]);
      if(config_file->sdr > 0) {
        malloc_comm_array(&(group->sync_array), config_file->sdr , group->myId, group->numP);
54
55
      }
    }
iker_martin's avatar
iker_martin committed
56
57
58

    if(myId== ROOT) print_config(config_file);
    int res = work();
59
60
61
62
63

    if(res) { // Ultimo set de procesos comprueba resultados
	    //RESULTADOS
    }

64
65
66
  //  free_config(config_file); //FIXME DESCOMENTAR
  //  free(group->sync_array);
  //  free(group);
67
68
69
70
71
72
73
74



    MPI_Finalize();
    return 0;
}

/*
75
76
77
78
79
80
81
82
83
 * Función de trabajo principal.
 *
 * Incializa los datos para realizar el computo y a continuacion
 * pasa a realizar "maxiter" iteraciones de computo.
 *
 * Terminadas las iteraciones realiza el redimensionado de procesos.
 * Si el redimensionado se realiza de forma asincrona se 
 * siguen realizando iteraciones de computo hasta que termine la 
 * comunicacion asincrona y realizar entonces la sincrona.
84
 */
iker_martin's avatar
iker_martin committed
85
86
int work() {
  int iter, maxiter;
87
88
  double *matrix;

iker_martin's avatar
iker_martin committed
89
90
91
92
93
  maxiter = config_file->iters[group->grp];
  initMatrix(&matrix, config_file->matrix_tam);

  for(iter=0; iter < maxiter; iter++) {
    iterate(matrix, config_file->matrix_tam);
94
  }
iker_martin's avatar
iker_martin committed
95
96
97

  checkpoint(iter);

98
99
100
101
102
103
104
105
106
  /*
  iter = 0
  while(maxiter) { //FIXME AÑADIR VALOR
    iterate(matrix, config_file->matrix_tam);
    iter++;
    //check_async(iter);
  }
  */

107
108
109
  return 0;
}

110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/*
 * Se realiza el redimensionado de procesos por parte de los padres.
 *
 * Se crean los nuevos procesos con la distribucion fisica elegida y
 * a continuacion se transmite la informacion a los mismos.
 *
 * Si hay datos asincronos a transmitir, primero se comienza a
 * transmitir estos y se termina la funcion. Se tiene que comprobar con
 * la funcion "??" que se han terminado de enviar //TODO
 *
 * Si hay ademas datos sincronos a enviar, no se envian aun.
 *
 * Si solo hay datos sincronos se envian tras la creacion de los procesos
 * y finalmente se desconectan los dos grupos de procesos.
 */
iker_martin's avatar
iker_martin committed
125
126
127
int checkpoint(int iter) {

  // Comprobar si se tiene que realizar un redimensionado
128
  if(config_file->iters[group->grp] < iter) {return 0;}
iker_martin's avatar
iker_martin committed
129
130
131
132
133
134
135
136
137
138
139
140
141

  int numS = config_file->procs[group->grp +1];

  TC(numS);

  int rootBcast = MPI_PROC_NULL;
  if(group->myId == ROOT) rootBcast = MPI_ROOT;

  // Enviar a los hijos que grupo de procesos son
  MPI_Bcast(&(group->grp), 1, MPI_INT, rootBcast, group->children);

  send_config_file(config_file, rootBcast, group->children);

142
143
144
145
  if(config_file->adr > 0) {
    send_async(group->sync_array, config_file->sdr, group->myId, group->numP, ROOT, group->children, numS);
  } else if

iker_martin's avatar
iker_martin committed
146
147
148
149
150
151
152
153
154
155
156
  if(config_file->sdr > 0) {
    send_sync(group->sync_array, config_file->sdr, group->myId, group->numP, ROOT, group->children, numS);
  }

  // Desconectar intercomunicador con los hijos
  MPI_Comm_disconnect(&(group->children));
  //MPI_Comm_free(&(group->children));

  return 1;
}

157
158
159
/*
 * Se encarga de realizar la creacion de los procesos hijos.
 */
iker_martin's avatar
iker_martin committed
160
161
162
163
164
165
166
167
168
169
170
171
172
void TC(int numS){
  // Inicialización de la comunicación con SLURM
  int dist = config_file->phy_dist[group->grp +1];
  init_slurm_comm(group->argv, group->myId, numS, ROOT, dist, COMM_SPAWN_SERIAL);

  // Esperar a que la comunicación y creación de procesos
  // haya finalizado
  int test = -1;
  while(test != MPI_SUCCESS) {
    test = check_slurm_comm(group->myId, ROOT, MPI_COMM_WORLD, &(group->children));
  }
}

173
174
175
176
177
178
/*
 * Inicializacion de los datos de los hijos.
 * En la misma se reciben datos de los padres: La configuracion
 * de la ejecucion a realizar; y los datos a recibir de los padres
 * ya sea de forma sincrona, asincrona o ambas.
 */
iker_martin's avatar
iker_martin committed
179
180
181
182
183
184
185
186
187
188
void Sons_init() {

  // Enviar a los hijos que grupo de procesos son
  MPI_Bcast(&(group->grp), 1, MPI_INT, ROOT, group->parents);
  group->grp++;


  config_file = recv_config_file(ROOT, group->parents);
  int numP_parents = config_file->procs[group->grp -1];

189
  if(config_file->sdr > 0) { // Recibir datos sincronos
iker_martin's avatar
iker_martin committed
190
191
192
193
194
    recv_sync(&(group->sync_array), config_file->sdr, group->myId, group->numP, ROOT, group->parents, numP_parents);
  }

  // Desconectar intercomunicador con los hijos
  MPI_Comm_disconnect(&(group->parents));
195
196

//  MPI_Abort(MPI_COMM_WORLD, 0);
iker_martin's avatar
iker_martin committed
197
198
199
200
201
202
203
204
205
206
}


/////////////////////////////////////////
/////////////////////////////////////////
//COMPUTE FUNCTIONS
/////////////////////////////////////////
/////////////////////////////////////////


207
208
/*
 * Simula la ejecucción de una iteración de computo en la aplicación
209
 * que dura al menos un tiempo de "time" segundos.
210
211
212
 */
void iterate(double *matrix, int n) {
  double start_time, actual_time;
iker_martin's avatar
iker_martin committed
213
  double time = config_file->general_time * config_file->factors[group->grp];
214
215

  start_time = actual_time = MPI_Wtime();
iker_martin's avatar
iker_martin committed
216
  while (actual_time - start_time < time) {
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
    computeMatrix(matrix, n);
    actual_time = MPI_Wtime();
  }
}

/*
 * Realiza una multiplicación de matrices de tamaño n
 */
void computeMatrix(double *matrix, int n) {
  int row, col, i, aux;

  for(row=0; i<n; row++) {
    /* COMPUTE */
    for(col=0; col<n; col++) {
      aux=0;
      for(i=0; i<n; i++) {
        aux += matrix[row*n + i] * matrix[i*n + col];
      }
    }
  }
}

/*
 * Init matrix
 */
void initMatrix(double **matrix, int n) {
  int i, j;

  // Init matrix
  if(matrix != NULL) {
    *matrix = malloc(n * n * sizeof(double));
    if(*matrix == NULL) { MPI_Abort(MPI_COMM_WORLD, -1);}
    for(i=0; i < n; i++) {
      for(j=0; j < n; j++) {
        (*matrix)[i*n + j] = i+j;
      }
    }
  }
}