Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
2b736c5a9e9f153476064b43c7599f2f2facd9ba
[simgrid.git] / src / smpi / smpi_global.c
1 /* Copyright (c) 2007, 2008, 2009, 2010. The SimGrid Team.
2  * All rights reserved.                                                     */
3
4 /* This program is free software; you can redistribute it and/or modify it
5   * under the terms of the license (GNU LGPL) which comes with this package. */
6
7 #include <stdint.h>
8 #include <stdlib.h>
9
10 #include "private.h"
11 #include "smpi_mpi_dt_private.h"
12 #include "mc/mc.h"
13
14 XBT_LOG_NEW_CATEGORY(smpi, "All SMPI categories");
15
16 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(smpi_kernel, smpi,
17                                 "Logging specific to SMPI (kernel)");
18
19 typedef struct s_smpi_process_data {
20   int index;
21   int* argc;
22   char*** argv;
23   xbt_fifo_t pending_sent;
24   xbt_fifo_t pending_recv;
25   xbt_os_timer_t timer;
26   double simulated;
27   MPI_Comm comm_self;
28 } s_smpi_process_data_t;
29
30 static smpi_process_data_t *process_data = NULL;
31 static int process_count = 0;
32
33 MPI_Comm MPI_COMM_WORLD = MPI_COMM_NULL;
34
35 void smpi_process_init(int *argc, char ***argv)
36 {
37   int index;
38   smpi_process_data_t data;
39   smx_process_t proc;
40
41   if(argc && argv) {
42     proc = SIMIX_process_self();
43     index = atoi((*argv)[1]);
44     data = smpi_process_remote_data(index);
45     SIMIX_req_process_set_data(proc, data);
46     if (*argc > 2) {
47       free((*argv)[1]);
48       memmove(&(*argv)[1], &(*argv)[2], sizeof(char *) * (*argc - 2));
49       (*argv)[(*argc) - 1] = NULL;
50     }
51     (*argc)--;
52     data->argc = argc;
53     data->argv = argv;
54     DEBUG2("<%d> New process in the game: %p", index, proc);
55   }
56 }
57
58 void smpi_process_destroy(void)
59 {
60   int index = smpi_process_index();
61
62   DEBUG1("<%d> Process left the game", index);
63 }
64
65 int smpi_process_argc(void) {
66   smpi_process_data_t data = smpi_process_data();
67
68   return data->argc ? *(data->argc) - 1 : 0;
69 }
70
71 int smpi_process_getarg(int* index, char* dst, size_t len) {
72   smpi_process_data_t data = smpi_process_data();
73   char* arg;
74   size_t i;
75
76   if(!data->argc || !data->argv
77      || *index < 1 || *index >= *(data->argc)) {
78     return -1;
79   }
80   arg = (*data->argv)[*index];
81   for(i = 0; i < len && arg[i] != '\0'; i++) {
82     dst[i] = arg[i];
83   }
84   for(; i < len; i++) {
85     dst[i] = ' ';
86   }
87   return 0;
88 }
89
90 int smpi_global_rank(void) {
91    return smpi_process_index();
92 }
93
94 int smpi_global_size(void) {
95    char* value = getenv("SMPI_GLOBAL_SIZE");
96
97    if(!value) {
98       abort();
99    }
100    return atoi(value);
101 }
102
103 smpi_process_data_t smpi_process_data(void)
104 {
105   return SIMIX_req_process_get_data(SIMIX_process_self());
106 }
107
108 smpi_process_data_t smpi_process_remote_data(int index)
109 {
110   return process_data[index];
111 }
112
113 int smpi_process_count(void)
114 {
115   return process_count;
116 }
117
118 int smpi_process_index(void)
119 {
120   smpi_process_data_t data = smpi_process_data();
121
122   return data->index;
123 }
124
125 xbt_os_timer_t smpi_process_timer(void)
126 {
127   smpi_process_data_t data = smpi_process_data();
128
129   return data->timer;
130 }
131
132 void smpi_process_simulated_start(void)
133 {
134   smpi_process_data_t data = smpi_process_data();
135
136   data->simulated = SIMIX_get_clock();
137 }
138
139 double smpi_process_simulated_elapsed(void)
140 {
141   smpi_process_data_t data = smpi_process_data();
142
143   return SIMIX_get_clock() - data->simulated;
144 }
145
146 MPI_Comm smpi_process_comm_self(void)
147 {
148   smpi_process_data_t data = smpi_process_data();
149
150   return data->comm_self;
151 }
152
153 void print_request(const char *message, MPI_Request request)
154 {
155   char *req =
156       bprintf
157       ("[buf = %p, size = %zu, src = %d, dst = %d, tag= %d, complete = %d, flags = %u]",
158        request->buf, request->size, request->src, request->dst,
159        request->tag, request->complete, request->flags);
160
161   DEBUG5("%s  (request %p with rdv %p and match %p) %s",
162          message, request, request->rdv, request->match, req);
163   free(req);
164 }
165
166 void smpi_process_post_send(MPI_Comm comm, MPI_Request request)
167 {
168   int index = smpi_group_index(smpi_comm_group(comm), request->dst);
169   smpi_process_data_t data = smpi_process_remote_data(index);
170   xbt_fifo_item_t item;
171   MPI_Request req;
172
173   print_request("Isend", request);
174   xbt_fifo_foreach(data->pending_recv, item, req, MPI_Request) {
175     if (req->comm == request->comm
176         && (req->src == MPI_ANY_SOURCE || req->src == request->src)
177         && (req->tag == MPI_ANY_TAG || req->tag == request->tag)) {
178       print_request("Match found", req);
179       xbt_fifo_remove_item(data->pending_recv, item);
180       /* Materialize the *_ANY_* fields from corresponding irecv request */
181       req->src = request->src;
182       req->tag = request->tag;
183       req->match = request;
184       request->rdv = req->rdv;
185       request->match = req;
186       return;
187     }
188   }
189   request->rdv = SIMIX_req_rdv_create(NULL);
190   xbt_fifo_push(data->pending_sent, request);
191 }
192
193 void smpi_process_post_recv(MPI_Request request)
194 {
195   smpi_process_data_t data = smpi_process_data();
196   xbt_fifo_item_t item;
197   MPI_Request req;
198
199   print_request("Irecv", request);
200   xbt_fifo_foreach(data->pending_sent, item, req, MPI_Request) {
201     if (req->comm == request->comm
202         && (request->src == MPI_ANY_SOURCE || req->src == request->src)
203         && (request->tag == MPI_ANY_TAG || req->tag == request->tag)) {
204       print_request("Match found", req);
205       xbt_fifo_remove_item(data->pending_sent, item);
206       /* Materialize the *_ANY_* fields from the irecv request */
207       req->match = request;
208       request->src = req->src;
209       request->tag = req->tag;
210       request->rdv = req->rdv;
211       request->match = req;
212       return;
213     }
214   }
215   request->rdv = SIMIX_req_rdv_create(NULL);
216   xbt_fifo_push(data->pending_recv, request);
217 }
218
219 void smpi_global_init(void)
220 {
221   int i;
222   MPI_Group group;
223
224   SIMIX_comm_set_copy_data_callback
225       (&SIMIX_comm_copy_buffer_callback);
226   process_count = SIMIX_process_count();
227   process_data = xbt_new(smpi_process_data_t, process_count);
228   for (i = 0; i < process_count; i++) {
229     process_data[i] = xbt_new(s_smpi_process_data_t, 1);
230     process_data[i]->index = i;
231     process_data[i]->argc = NULL;
232     process_data[i]->argv = NULL;
233     process_data[i]->pending_sent = xbt_fifo_new();
234     process_data[i]->pending_recv = xbt_fifo_new();
235     process_data[i]->timer = xbt_os_timer_new();
236     group = smpi_group_new(1);
237     process_data[i]->comm_self = smpi_comm_new(group);
238     smpi_group_set_mapping(group, i, 0);
239   }
240   group = smpi_group_new(process_count);
241   MPI_COMM_WORLD = smpi_comm_new(group);
242   for (i = 0; i < process_count; i++) {
243     smpi_group_set_mapping(group, i, i);
244   }
245 }
246
247 void smpi_global_destroy(void)
248 {
249   int count = smpi_process_count();
250   int i;
251
252   smpi_bench_destroy();
253   smpi_comm_destroy(MPI_COMM_WORLD);
254   MPI_COMM_WORLD = MPI_COMM_NULL;
255   for (i = 0; i < count; i++) {
256     smpi_comm_destroy(process_data[i]->comm_self);
257     xbt_os_timer_free(process_data[i]->timer);
258     xbt_fifo_free(process_data[i]->pending_recv);
259     xbt_fifo_free(process_data[i]->pending_sent);
260     xbt_free(process_data[i]);
261   }
262   xbt_free(process_data);
263   process_data = NULL;
264 }
265
266 /* Fortran specific stuff */
267 /* With smpicc, the following weak symbols are used */
268 /* With smpiff, the following weak symbols are replaced by those in libf2c */
269 int __attribute__((weak)) xargc;
270 char** __attribute__((weak)) xargv;
271
272 int __attribute__((weak)) main(int argc, char** argv) {
273    xargc = argc;
274    xargv = argv;
275    return MAIN__();
276 }
277
278 int MAIN__(void)
279 {
280   srand(SMPI_RAND_SEED);
281
282   double default_reference_speed = 20000.0;
283   xbt_cfg_register(&_surf_cfg_set, "smpi/running_power",
284                    "Power of the host running the simulation (in flop/s). Used to bench the operations.",
285                    xbt_cfgelm_double, &default_reference_speed, 1, 1, NULL,
286                    NULL);
287
288   int default_display_timing = 0;
289   xbt_cfg_register(&_surf_cfg_set, "smpi/display_timing",
290                    "Boolean indicating whether we should display the timing after simulation.",
291                    xbt_cfgelm_int, &default_display_timing, 1, 1, NULL,
292                    NULL);
293
294   double default_threshold = 1e-6;
295   xbt_cfg_register(&_surf_cfg_set, "smpi/cpu_threshold",
296                    "Minimal computation time (in seconds) not discarded.",
297                    xbt_cfgelm_double, &default_threshold, 1, 1, NULL,
298                    NULL);
299
300 #ifdef HAVE_TRACING
301   TRACE_global_init(&xargc, xargv);
302 #endif
303
304   SIMIX_global_init(&xargc, xargv);
305
306 #ifdef HAVE_TRACING
307   TRACE_smpi_start();
308 #endif
309
310   // parse the platform file: get the host list
311   SIMIX_create_environment(xargv[1]);
312
313   SIMIX_function_register("smpi_simulated_main", smpi_simulated_main);
314   SIMIX_launch_application(xargv[2]);
315
316   smpi_global_init();
317
318   /* Clean IO before the run */
319   fflush(stdout);
320   fflush(stderr);
321
322   if (MC_IS_ENABLED)
323     MC_modelcheck();
324   else
325     SIMIX_run();
326
327   if (xbt_cfg_get_int(_surf_cfg_set, "smpi/display_timing"))
328     INFO1("simulation time %g", SIMIX_get_clock());
329
330   smpi_global_destroy();
331
332 #ifdef HAVE_TRACING
333   TRACE_smpi_release();
334 #endif
335
336   SIMIX_clean();
337   return 0;
338 }