Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
do-nothing program that uses only MPI_Init and MPI_Finalize works now.
[simgrid.git] / src / smpi / src / smpi_base.c
1 #include <stdio.h>
2
3 #include <signal.h>
4 #include <sys/time.h>
5 #include "xbt/xbt_portability.h"
6 #include "simix/simix.h"
7 #include "simix/private.h"
8 #include "smpi.h"
9
10 xbt_fifo_t *smpi_pending_send_requests      = NULL;
11 xbt_fifo_t *smpi_pending_recv_requests      = NULL;
12 xbt_fifo_t *smpi_received_messages          = NULL;
13
14 int smpi_running_hosts = 0;
15
16 smpi_mpi_communicator_t smpi_mpi_comm_world;
17
18 smpi_mpi_status_t smpi_mpi_status_ignore;
19
20 smpi_mpi_datatype_t smpi_mpi_byte;
21 smpi_mpi_datatype_t smpi_mpi_int;
22 smpi_mpi_datatype_t smpi_mpi_double;
23
24 smpi_mpi_op_t smpi_mpi_land;
25 smpi_mpi_op_t smpi_mpi_sum;
26
27 static xbt_os_timer_t smpi_timer;
28 static int smpi_benchmarking;
29 static double smpi_reference_speed;
30
31 // mutexes
32 smx_mutex_t smpi_running_hosts_mutex = NULL;
33 smx_mutex_t init_mutex = NULL;
34 smx_cond_t init_cond  = NULL;
35
36 int rootready = 0;
37 int readycount = 0;
38
39 XBT_LOG_NEW_DEFAULT_CATEGORY(smpi, "SMPI");
40
41 int smpi_sender(int argc, char **argv)
42 {
43         return 0;
44 }
45
46 int smpi_receiver(int argc, char **argv)
47 {
48         return 0;
49 }
50
51 int smpi_run_simulation(int argc, char **argv)
52 {
53         smx_cond_t   cond           = NULL;
54         smx_action_t action         = NULL;
55
56         xbt_fifo_t   actions_failed = xbt_fifo_new();
57         xbt_fifo_t   actions_done   = xbt_fifo_new();
58
59         srand(SMPI_RAND_SEED);
60
61         SIMIX_global_init(&argc, argv);
62
63         init_mutex = SIMIX_mutex_init();
64         init_cond  = SIMIX_cond_init();
65
66         SIMIX_function_register("smpi_simulated_main", smpi_simulated_main);
67         SIMIX_create_environment(argv[1]);
68         SIMIX_launch_application(argv[2]);
69
70         /* Prepare to display some more info when dying on Ctrl-C pressing */
71         //signal(SIGINT, inthandler);
72
73         /* Clean IO before the run */
74         fflush(stdout);
75         fflush(stderr);
76
77         while (SIMIX_solve(actions_done, actions_failed) != -1.0) {
78                 while (action = xbt_fifo_pop(actions_failed)) {
79                         DEBUG1("** %s failed **", action->name);
80                         while (cond = xbt_fifo_pop(action->cond_list)) {
81                                 SIMIX_cond_broadcast(cond);
82                         }
83                         SIMIX_action_destroy(action);
84                 }
85                 while (action = xbt_fifo_pop(actions_done)) {
86                         DEBUG1("** %s done **",action->name);
87                         while (cond = xbt_fifo_pop(action->cond_list)) {
88                                 SIMIX_cond_broadcast(cond);
89                         }
90                         SIMIX_action_destroy(action);
91                 }
92         }
93         xbt_fifo_free(actions_failed);
94         xbt_fifo_free(actions_done);
95         INFO1("simulation time %g", SIMIX_get_clock());
96         SIMIX_clean();
97         return 0;
98 }
99
100 void smpi_mpi_land_func(void *x, void *y, void *z)
101 {
102         *(int *)z = *(int *)x && *(int *)y;
103 }
104
105 void smpi_mpi_sum_func(void *x, void *y, void *z)
106 {
107         *(int *)z = *(int *)x + *(int *)y;
108 }
109
110 int smpi_mpi_rank(smpi_mpi_communicator_t *comm, smx_host_t host)
111 {
112         int i;
113
114         for(i = comm->size - 1; i > 0 && host != comm->hosts[i]; i--);
115
116         return i;
117 }
118
119 int inline smpi_mpi_rank_self(smpi_mpi_communicator_t *comm)
120 {
121         return smpi_mpi_rank(comm, SIMIX_host_self());
122 }
123
124 void smpi_mpi_init()
125 {
126         int i;
127         int size;
128         smx_process_t process;
129         smx_host_t *hosts;
130         smx_host_t host;
131         double duration;
132
133         // initialize some local variables
134         host  = SIMIX_host_self();
135         hosts = SIMIX_host_get_table();
136         size  = SIMIX_host_get_number();
137
138         // node 0 sets the globals
139         if (host == hosts[0]) {
140
141                 // running hosts
142                 smpi_running_hosts_mutex          = SIMIX_mutex_init();
143                 smpi_running_hosts                = size;
144
145                 // global communicator
146                 smpi_mpi_comm_world.size          = size;
147                 smpi_mpi_comm_world.barrier       = 0;
148                 smpi_mpi_comm_world.barrier_mutex = SIMIX_mutex_init();
149                 smpi_mpi_comm_world.barrier_cond  = SIMIX_cond_init();
150                 smpi_mpi_comm_world.hosts         = hosts;
151                 smpi_mpi_comm_world.processes     = xbt_new0(smx_process_t, size);
152                 smpi_mpi_comm_world.processes[0]  = SIMIX_process_self();
153
154                 // mpi datatypes
155                 smpi_mpi_byte.size                = (size_t)1;
156                 smpi_mpi_int.size                 = sizeof(int);
157                 smpi_mpi_double.size              = sizeof(double);
158
159                 // mpi operations
160                 smpi_mpi_land.func                = &smpi_mpi_land_func;
161                 smpi_mpi_sum.func                 = &smpi_mpi_sum_func;
162
163                 // smpi globals
164                 smpi_pending_send_requests        = xbt_new0(xbt_fifo_t, size);
165                 smpi_pending_recv_requests        = xbt_new0(xbt_fifo_t, size);
166                 smpi_received_messages            = xbt_new0(xbt_fifo_t, size);
167
168                 for(i = 0; i < size; i++) {
169                         smpi_pending_send_requests[i] = xbt_fifo_new();
170                         smpi_pending_recv_requests[i] = xbt_fifo_new();
171                         smpi_received_messages[i]     = xbt_fifo_new();
172                 }
173
174                 smpi_timer                      = xbt_os_timer_new();
175                 smpi_reference_speed            = SMPI_DEFAULT_SPEED;
176                 smpi_benchmarking               = 0;
177
178                 // signal all nodes to perform initialization
179                 SIMIX_mutex_lock(init_mutex);
180                 rootready = 1;
181                 SIMIX_cond_broadcast(init_cond);
182                 SIMIX_mutex_unlock(init_mutex);
183
184         } else {
185
186                 // make sure root is done before own initialization
187                 SIMIX_mutex_lock(init_mutex);
188                 if (!rootready) {
189                         SIMIX_cond_wait(init_cond, init_mutex);
190                 }
191                 SIMIX_mutex_unlock(init_mutex);
192
193                 smpi_mpi_comm_world.processes[smpi_mpi_rank_self(&smpi_mpi_comm_world)] = SIMIX_process_self();
194
195         }
196
197         // wait for all nodes to signal initializatin complete
198         SIMIX_mutex_lock(init_mutex);
199         readycount++;
200         if (readycount < size) {
201                 SIMIX_cond_wait(init_cond, init_mutex);
202         } else {
203                 SIMIX_cond_broadcast(init_cond);
204         }
205         SIMIX_mutex_unlock(init_mutex);
206
207 }
208
209 void smpi_mpi_finalize()
210 {
211         int i;
212
213         SIMIX_mutex_lock(smpi_running_hosts_mutex);
214         i = --smpi_running_hosts;
215         SIMIX_mutex_unlock(smpi_running_hosts_mutex);
216
217         if (0 >= i) {
218
219                 SIMIX_mutex_destroy(smpi_running_hosts_mutex);
220
221                 for (i = 0 ; i < smpi_mpi_comm_world.size; i++) {
222                         xbt_fifo_free(smpi_pending_send_requests[i]);
223                         xbt_fifo_free(smpi_pending_recv_requests[i]);
224                         xbt_fifo_free(smpi_received_messages[i]);
225                 }
226
227                 xbt_free(smpi_pending_send_requests);
228                 xbt_free(smpi_pending_recv_requests);
229                 xbt_free(smpi_received_messages);
230
231                 SIMIX_mutex_destroy(smpi_mpi_comm_world.barrier_mutex);
232                 SIMIX_cond_destroy(smpi_mpi_comm_world.barrier_cond);
233                 xbt_free(smpi_mpi_comm_world.processes);
234
235                 xbt_os_timer_free(smpi_timer);
236         }
237
238 }
239
240 void smpi_bench_begin()
241 {
242         xbt_assert0(!smpi_benchmarking, "Already benchmarking");
243         smpi_benchmarking = 1;
244         xbt_os_timer_start(smpi_timer);
245         return;
246 }
247
248 void smpi_bench_end()
249 {
250         double duration;
251         xbt_assert0(smpi_benchmarking, "Not benchmarking yet");
252         smpi_benchmarking = 0;
253         xbt_os_timer_stop(smpi_timer);
254         duration = xbt_os_timer_elapsed(smpi_timer);
255         // FIXME: add simix call to perform computation
256         return;
257 }
258
259 void smpi_barrier(smpi_mpi_communicator_t *comm) {
260         int i;
261         SIMIX_mutex_lock(comm->barrier_mutex);
262         comm->barrier++;
263         if(i < comm->size) {
264                 SIMIX_cond_wait(comm->barrier_cond, comm->barrier_mutex);
265         } else {
266                 comm->barrier = 0;
267                 SIMIX_cond_broadcast(comm->barrier_cond);
268         }
269         SIMIX_mutex_unlock(comm->barrier_mutex);
270 }
271
272 int smpi_comm_rank(smpi_mpi_communicator_t *comm, smx_host_t host)
273 {
274         int i;
275         for(i = 0; i < comm->size && host != comm->hosts[i]; i++);
276         if (i >= comm->size) i = -1;
277         return i;
278 }
279
280 // FIXME: move into own file
281 int smpi_gettimeofday(struct timeval *tv, struct timezone *tz)
282 {
283         double now;
284         int retval = 0;
285         smpi_bench_end();
286         if (NULL == tv) {
287                 retval = -1;
288         } else {
289                 now = SIMIX_get_clock();
290                 tv->tv_sec  = now;
291                 tv->tv_usec = ((now - (double)tv->tv_sec) * 1000000.0);
292         }
293         smpi_bench_begin();
294         return retval;
295 }
296
297 unsigned int smpi_sleep(unsigned int seconds)
298 {
299         smx_mutex_t mutex;
300         smx_cond_t cond;
301         smx_host_t host;
302         smx_action_t sleep_action;
303
304         smpi_bench_end();
305         host         = SIMIX_host_self();
306         sleep_action = SIMIX_action_sleep(host, seconds);
307         mutex        = SIMIX_mutex_init();
308         cond         = SIMIX_cond_init();
309         SIMIX_mutex_lock(mutex);
310         SIMIX_register_condition_to_action(sleep_action, cond);
311         SIMIX_register_action_to_condition(sleep_action, cond);
312         SIMIX_cond_wait(cond, mutex);
313         SIMIX_mutex_unlock(mutex);
314         SIMIX_mutex_destroy(mutex);
315         SIMIX_cond_destroy(cond);
316         // FIXME: check for success/failure?
317         smpi_bench_begin();
318         return 0;
319 }
320
321 void smpi_exit(int status)
322 {
323         smpi_bench_end();
324         SIMIX_mutex_lock(smpi_running_hosts_mutex);
325         smpi_running_hosts--;
326         SIMIX_mutex_unlock(smpi_running_hosts_mutex);
327         SIMIX_process_kill(SIMIX_process_self());
328         return;
329 }