Main.c 6.43 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
64

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

    free_config(config_file);
iker_martin's avatar
iker_martin committed
65
66
    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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
int checkpoint(int iter) {

  // Comprobar si se tiene que realizar un redimensionado
  if(config_file->iters[group->grp] < iter || group->grp!= 0) {return 0;}

  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);

  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;
}

153
154
155
/*
 * Se encarga de realizar la creacion de los procesos hijos.
 */
iker_martin's avatar
iker_martin committed
156
157
158
159
160
161
162
163
164
165
166
167
168
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));
  }
}

169
170
171
172
173
174
/*
 * 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
175
176
177
178
179
180
181
182
183
184
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];

185
  if(config_file->sdr > 0) { // Recibir datos sincronos
iker_martin's avatar
iker_martin committed
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
    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));
}


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


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

  start_time = actual_time = MPI_Wtime();
iker_martin's avatar
iker_martin committed
210
  while (actual_time - start_time < time) {
211
212
213
214
215
216
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
    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;
      }
    }
  }
}