Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Added local and global sampling.
[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    if (allocs) {
31       xbt_dict_free(&allocs);
32    }
33    if (samples) {
34       xbt_dict_free(&samples);
35    }
36 }
37
38 static void smpi_execute(double duration) {
39   smx_host_t host;
40   smx_action_t action;
41   smx_mutex_t mutex;
42   smx_cond_t cond;
43   e_surf_action_state_t state;
44
45   if(duration >= xbt_cfg_get_double(_surf_cfg_set, "smpi/cpu_threshold")) {
46     host = SIMIX_host_self();
47     mutex = SIMIX_mutex_init();
48     cond = SIMIX_cond_init();
49     DEBUG1("Sleep for %f to handle real computation time", duration);
50     duration *= xbt_cfg_get_double(_surf_cfg_set, "smpi/running_power");
51     action = SIMIX_action_execute(host, "computation", duration);
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; state = SIMIX_action_get_state(action)) {
57       SIMIX_cond_wait(cond, mutex);
58     }
59     SIMIX_unregister_action_to_condition(action, cond);
60     SIMIX_mutex_unlock(mutex);
61     SIMIX_action_destroy(action);
62     SIMIX_cond_destroy(cond);
63     SIMIX_mutex_destroy(mutex);
64   }
65 }
66
67 void smpi_bench_begin(int rank, const char* mpi_call) {
68   if(mpi_call && rank >= 0 && xbt_cfg_get_int(_surf_cfg_set, "smpi/log_events")) {
69     INFO3("SMPE: ts=%f rank=%d type=end et=%s", SIMIX_get_clock(), rank, mpi_call);
70   }
71   xbt_os_timer_start(smpi_process_timer());
72 }
73
74 void smpi_bench_end(int rank, const char* mpi_call) {
75   xbt_os_timer_t timer = smpi_process_timer();
76
77   xbt_os_timer_stop(timer);
78   smpi_execute(xbt_os_timer_elapsed(timer));
79   if(mpi_call && rank >= 0 && xbt_cfg_get_int(_surf_cfg_set, "smpi/log_events")) {
80     INFO3("SMPE: ts=%f rank=%d type=begin et=%s", SIMIX_get_clock(), rank, mpi_call);
81   }
82 }
83
84 unsigned int smpi_sleep(unsigned int secs) {
85    smpi_execute((double)secs);
86 }
87
88 int smpi_gettimeofday(struct timeval* tv, struct timezone* tz) {
89    double now = SIMIX_get_clock();
90
91    if(tv) {
92       tv->tv_sec = (time_t)now;
93       tv->tv_usec = (suseconds_t)(now * 1e6);
94    }
95    return 0;
96 }
97
98 static char* sample_location(int global, const char* file, int line) {
99    if(global) {
100       return bprintf("%s:%d", file, line);
101    } else {
102       return bprintf("%s:%d:%d", file, line, smpi_process_index());
103    }
104 }
105
106 void smpi_sample_1(int global, const char* file, int line, int max) {
107    char* loc = sample_location(global, file, line);
108    local_data_t* data;
109
110    smpi_bench_end(-1, NULL); /* Take time from previous MPI call into account */
111    if (!samples) {
112       samples = xbt_dict_new();
113    }
114    data = xbt_dict_get_or_null(samples, loc);
115    if (!data) {
116       data = (local_data_t*)xbt_new(local_data_t, 1);
117       data->time = 0.0;
118       data->count = 0;
119       data->max = max;
120       data->started = 0;
121       xbt_dict_set(samples, loc, data, &free);
122    }
123    free(loc);
124 }
125
126 int smpi_sample_2(int global, const char* file, int line) {
127    char* loc = sample_location(global, file, line);
128    local_data_t* data;
129    double* simu;
130
131    xbt_assert0(samples, "You did something very inconsistent, didn't you?");
132    data = xbt_dict_get_or_null(samples, loc);
133    if (!data) {
134       xbt_assert0(data, "Please, do thing in order");
135    }
136    if (!data->started) {
137       if (data->count < data->max) {
138          data->started = 1;
139          data->count++;
140       } else {
141          DEBUG1("Perform some wait of %f", data->time / (double)data->count);
142          smpi_execute(data->time / (double)data->count);
143       }
144    } else {
145       data->started = 0;
146    }
147    free(loc);
148    smpi_bench_begin(-1, NULL);
149    smpi_process_simulated_start();
150    return data->started;
151 }
152
153 void smpi_sample_3(int global, const char* file, int line) {
154    char* loc = sample_location(global, file, line);
155    local_data_t* data;
156    double spent;
157
158    xbt_assert0(samples, "You did something very inconsistent, didn't you?");
159    data = xbt_dict_get_or_null(samples, loc);
160    if (!data || !data->started || data->count >= data->max) {
161       xbt_assert0(data, "Please, do thing in order");
162    }
163    smpi_bench_end(-1, NULL);
164    data->time += smpi_process_simulated_elapsed();
165    DEBUG2("Average mean after %d steps is %f", data->count, data->time / (double)data->count);
166 }
167
168 void* smpi_shared_malloc(size_t size, const char* file, int line) {
169    char* loc = bprintf("%s:%d:%zu", file, line, size);
170    shared_data_t* data;
171
172    if (!allocs) {
173       allocs = xbt_dict_new();
174    }
175    data = xbt_dict_get_or_null(allocs, loc);
176    if (!data) {
177       data = (shared_data_t*)xbt_malloc0(sizeof(int) + size);
178       data->count = 1;
179       xbt_dict_set(allocs, loc, data, &free);
180    } else {
181       data->count++;
182    }
183    free(loc);
184    return data->data;
185 }
186
187 void smpi_shared_free(void* ptr) {
188    shared_data_t* data = (shared_data_t*)((int*)ptr - 1);
189    char* loc;
190
191    if (!allocs) {
192       WARN0("Cannot free: nothing was allocated");
193       return;
194    }
195    loc = xbt_dict_get_key(allocs, data);
196    if (!loc) {
197       WARN1("Cannot free: %p was not shared-allocated by SMPI", ptr);
198       return;
199    }
200    data->count--;
201    if (data->count <= 0) {
202       xbt_dict_remove(allocs, loc);
203    }
204 }