Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
MPI_Comm_split is back to life.
[simgrid.git] / src / smpi / smpi_bench.c
1 /* Copyright (c) 2007, 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 "private.h"
8 #include "xbt/dict.h"
9 #include "xbt/sysdep.h"
10
11 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(smpi_bench, smpi,
12                                 "Logging specific to SMPI (benchmarking)");
13
14 xbt_dict_t allocs = NULL;       /* Allocated on first use */
15 xbt_dict_t samples = NULL;      /* Allocated on first use */
16
17 typedef struct {
18   int count;
19   char data[];
20 } shared_data_t;
21
22 typedef struct {
23   double time;
24   int count;
25   int max;
26   int started;
27 } local_data_t;
28
29 void smpi_bench_destroy(void)
30 {
31   if (allocs) {
32     xbt_dict_free(&allocs);
33   }
34   if (samples) {
35     xbt_dict_free(&samples);
36   }
37 }
38
39 static void smpi_execute_flops(double flops)
40 {
41   smx_host_t host;
42   smx_action_t action;
43   smx_mutex_t mutex;
44   smx_cond_t cond;
45   e_surf_action_state_t state;
46
47   host = SIMIX_host_self();
48   mutex = SIMIX_mutex_init();
49   cond = SIMIX_cond_init();
50   DEBUG1("Handle real computation time: %f flops", flops);
51   action = SIMIX_action_execute(host, "computation", flops);
52   SIMIX_mutex_lock(mutex);
53   SIMIX_register_action_to_condition(action, cond);
54   for (state = SIMIX_action_get_state(action);
55        state == SURF_ACTION_READY ||
56        state == SURF_ACTION_RUNNING;
57        state = SIMIX_action_get_state(action)) {
58     SIMIX_cond_wait(cond, mutex);
59   }
60   SIMIX_unregister_action_to_condition(action, cond);
61   SIMIX_mutex_unlock(mutex);
62   SIMIX_action_destroy(action);
63   SIMIX_cond_destroy(cond);
64   SIMIX_mutex_destroy(mutex);
65 }
66
67 static void smpi_execute(double duration)
68 {
69   if (duration >= xbt_cfg_get_double(_surf_cfg_set, "smpi/cpu_threshold")) {
70     DEBUG1("Sleep for %f to handle real computation time", duration);
71     smpi_execute_flops(duration *
72                        xbt_cfg_get_double(_surf_cfg_set,
73                                           "smpi/running_power"));
74   }
75 }
76
77 void smpi_bench_begin(int rank, const char *mpi_call)
78 {
79   if (mpi_call && rank >= 0
80       && xbt_cfg_get_int(_surf_cfg_set, "smpi/log_events")) {
81     INFO3("SMPE: ts=%f rank=%d type=end et=%s", SIMIX_get_clock(), rank,
82           mpi_call);
83   }
84   xbt_os_timer_start(smpi_process_timer());
85 }
86
87 void smpi_bench_end(int rank, const char *mpi_call)
88 {
89   xbt_os_timer_t timer = smpi_process_timer();
90
91   xbt_os_timer_stop(timer);
92   smpi_execute(xbt_os_timer_elapsed(timer));
93   if (mpi_call && rank >= 0
94       && xbt_cfg_get_int(_surf_cfg_set, "smpi/log_events")) {
95     INFO3("SMPE: ts=%f rank=%d type=begin et=%s", SIMIX_get_clock(), rank,
96           mpi_call);
97   }
98 }
99
100 unsigned int smpi_sleep(unsigned int secs)
101 {
102   smpi_execute((double) secs);
103   return secs;
104 }
105
106 int smpi_gettimeofday(struct timeval *tv, struct timezone *tz)
107 {
108   double now = SIMIX_get_clock();
109
110   if (tv) {
111     tv->tv_sec = (time_t) now;
112     tv->tv_usec = (suseconds_t) (now * 1e6);
113   }
114   return 0;
115 }
116
117 static char *sample_location(int global, const char *file, int line)
118 {
119   if (global) {
120     return bprintf("%s:%d", file, line);
121   } else {
122     return bprintf("%s:%d:%d", file, line, smpi_process_index());
123   }
124 }
125
126 void smpi_sample_1(int global, const char *file, int line, int max)
127 {
128   char *loc = sample_location(global, file, line);
129   local_data_t *data;
130
131   smpi_bench_end(-1, NULL);     /* Take time from previous MPI call into account */
132   if (!samples) {
133     samples = xbt_dict_new();
134   }
135   data = xbt_dict_get_or_null(samples, loc);
136   if (!data) {
137     data = (local_data_t *) xbt_new(local_data_t, 1);
138     data->time = 0.0;
139     data->count = 0;
140     data->max = max;
141     data->started = 0;
142     xbt_dict_set(samples, loc, data, &free);
143   }
144   free(loc);
145 }
146
147 int smpi_sample_2(int global, const char *file, int line)
148 {
149   char *loc = sample_location(global, file, line);
150   local_data_t *data;
151
152   xbt_assert0(samples, "You did something very inconsistent, didn't you?");
153   data = xbt_dict_get_or_null(samples, loc);
154   if (!data) {
155     xbt_assert0(data, "Please, do thing in order");
156   }
157   if (!data->started) {
158     if (data->count < data->max) {
159       data->started = 1;
160       data->count++;
161     } else {
162       DEBUG1("Perform some wait of %f", data->time / (double) data->count);
163       smpi_execute(data->time / (double) data->count);
164     }
165   } else {
166     data->started = 0;
167   }
168   free(loc);
169   smpi_bench_begin(-1, NULL);
170   smpi_process_simulated_start();
171   return data->started;
172 }
173
174 void smpi_sample_3(int global, const char *file, int line)
175 {
176   char *loc = sample_location(global, file, line);
177   local_data_t *data;
178
179   xbt_assert0(samples, "You did something very inconsistent, didn't you?");
180   data = xbt_dict_get_or_null(samples, loc);
181   if (!data || !data->started || data->count >= data->max) {
182     xbt_assert0(data, "Please, do thing in order");
183   }
184   smpi_bench_end(-1, NULL);
185   data->time += smpi_process_simulated_elapsed();
186   DEBUG2("Average mean after %d steps is %f", data->count,
187          data->time / (double) data->count);
188 }
189
190 void smpi_sample_flops(double flops)
191 {
192   smpi_execute_flops(flops);
193 }
194
195 void *smpi_shared_malloc(size_t size, const char *file, int line)
196 {
197   char *loc = bprintf("%s:%d:%zu", file, line, size);
198   shared_data_t *data;
199
200   if (!allocs) {
201     allocs = xbt_dict_new();
202   }
203   data = xbt_dict_get_or_null(allocs, loc);
204   if (!data) {
205     data = (shared_data_t *) xbt_malloc0(sizeof(int) + size);
206     data->count = 1;
207     xbt_dict_set(allocs, loc, data, &free);
208   } else {
209     data->count++;
210   }
211   free(loc);
212   return data->data;
213 }
214
215 void smpi_shared_free(void *ptr)
216 {
217   shared_data_t *data = (shared_data_t *) ((int *) ptr - 1);
218   char *loc;
219
220   if (!allocs) {
221     WARN0("Cannot free: nothing was allocated");
222     return;
223   }
224   loc = xbt_dict_get_key(allocs, data);
225   if (!loc) {
226     WARN1("Cannot free: %p was not shared-allocated by SMPI", ptr);
227     return;
228   }
229   data->count--;
230   if (data->count <= 0) {
231     xbt_dict_remove(allocs, loc);
232   }
233 }