-
Notifications
You must be signed in to change notification settings - Fork 30
/
Copy pathmpiP-mt-stats.c
316 lines (274 loc) · 8.81 KB
/
mpiP-mt-stats.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
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
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
#include "mpiPi.h"
#include "mpiP-stats.h"
#include "mpiP-mt-stats.h"
#include "mpiPi_proto.h"
/*
* ============================================================================
*
* Multi-thread management code
*
* ============================================================================
*/
static void key_destruct(void *data)
{
mpiPi_mt_stat_tls_t *hndl = (mpiPi_mt_stat_tls_t *)data;
mpiPi_thread_stat_t *s = hndl->tls_ptr;
/* Stop the timer and disable this TLS */
mpiPi_stats_thr_timer_stop(hndl->tls_ptr);
s->disabled = 1;
hndl->is_active = 0;
}
/*
* ============================================================================
*
* Multi-threaded layer
*
* ============================================================================
*/
static mpiPi_mt_stat_tls_t *_alloc_tls(mpiPi_mt_stat_t *mt_state)
{
mpiPi_mt_stat_tls_t *hndl = calloc(1, sizeof(*hndl));
if (NULL == hndl) {
mpiPi_abort("failed to allocate TLS handler");
}
hndl->mt_state = mt_state;
hndl->tls_ptr = calloc(1, sizeof(*hndl->mt_state));
if (NULL == hndl->tls_ptr) {
mpiPi_abort("failed to allocate TLS");
}
return hndl;
}
static void _free_tls(mpiPi_mt_stat_tls_t *hndl)
{
hndl->mt_state = NULL;
free(hndl->tls_ptr);
free(hndl);
}
static void _release_all_tls(mpiP_tslist_t *tls_list)
{
mpiPi_mt_stat_tls_t *hndl = mpiPi_tslist_dequeue(tls_list);
while(hndl) {
_free_tls(hndl);
hndl = mpiPi_tslist_dequeue(tls_list);
}
}
int mpiPi_stats_mt_init(mpiPi_mt_stat_t *mt_state, mpiPi_thr_mode_t mode)
{
mt_state->mode = mode;
mpiPi_stats_thr_init(&mt_state->rank_stats);
switch(mt_state->mode) {
case MPIPI_MODE_ST:
mt_state->st_hndl.mt_state = mt_state;
mt_state->st_hndl.tls_ptr = &mt_state->rank_stats;
case MPIPI_MODE_MT:
mt_state->tls_list = mpiPi_tslist_create();
pthread_key_create(&mt_state->tls_this, key_destruct);
default:
break;
}
/* Initialize TLS for the main thread */
(void)mpiPi_stats_mt_gettls(mt_state);
return 0;
}
void mpiPi_stats_mt_fini(mpiPi_mt_stat_t *mt_state)
{
switch(mt_state->mode)
{
case MPIPI_MODE_ST:
mpiPi_stats_thr_fini(&mt_state->rank_stats);
break;
case MPIPI_MODE_MT:
// TODO: Make sure that list is drained
_release_all_tls(mt_state->tls_list);
mpiPi_tslist_release(mt_state->tls_list);
pthread_key_delete(mt_state->tls_this);
mpiPi_stats_thr_init(&mt_state->rank_stats);
break;
}
}
mpiPi_mt_stat_tls_t *
mpiPi_stats_mt_gettls(mpiPi_mt_stat_t *mt_state)
{
mpiPi_mt_stat_tls_t *hndl = NULL;
if (MPIPI_MODE_ST == mt_state->mode)
{
/* For all non-MPI_THREAD_MULTIPLE modes use
* embedded data structure
*/
return &mt_state->st_hndl;
} else {
/* For the MPI_THREAD_MULTIPLE mode use TLS
*/
hndl = pthread_getspecific(mt_state->tls_this);
if (NULL == hndl)
{
hndl = _alloc_tls(mt_state);
(void) pthread_setspecific(mt_state->tls_this, hndl);
mpiPi_stats_thr_init(hndl->tls_ptr);
hndl->is_active = 1;
if( mpiPi.enabled ) {
/* NOTE: this is not precise!
* - The thread could have been started long time ago
* - In the scope of mpiP we only rely on the MPI API
* hich doesn't track thread creation
* - we only can only start tracking a thread after the first
* invocation of any MPI operation tracked by mpiP.
* - This is still important to track threads at least this way
* because we don't want to have MPI operations to span more
* than 100% of the application time.
*/
mpiPi_stats_thr_timer_start(hndl->tls_ptr);
}
mpiPi_tslist_append(mt_state->tls_list, hndl);
}
}
return hndl;
}
void mpiPi_stats_mt_merge(mpiPi_mt_stat_t *mt_state)
{
mpiP_tslist_elem_t *curr = NULL;
if(MPIPI_MODE_ST == mt_state->mode) {
/* Nothing to do here */
return;
}
curr = mpiPi_tslist_first(mt_state->tls_list);
mpiPi_stats_thr_cs_reset(&mt_state->rank_stats);
/* Go over all TLS structures and merge them into the rank-wide callsite info */
while (curr)
{
mpiPi_mt_stat_tls_t *hndl = curr->ptr;
mpiPi_thread_stat_t *s = hndl->tls_ptr;
mpiPi_stats_thr_merge_all(&mt_state->rank_stats, s);
curr = mpiPi_tslist_next(curr);
}
}
void mpiPi_stats_mt_timer_start(mpiPi_mt_stat_t *mt_state)
{
mpiP_tslist_elem_t *curr = NULL;
if(MPIPI_MODE_ST == mt_state->mode) {
/* Only update the cumulative time */
mpiPi_stats_thr_timer_start(&mt_state->rank_stats);
return;
}
curr = mpiPi_tslist_first(mt_state->tls_list);
/* Go over all TLS structures and update the timers */
while (curr)
{
mpiPi_mt_stat_tls_t *hndl = curr->ptr;
if( hndl->is_active )
{
mpiPi_stats_thr_timer_start(hndl->tls_ptr);
}
curr = mpiPi_tslist_next(curr);
}
}
void mpiPi_stats_mt_timer_stop(mpiPi_mt_stat_t *mt_state)
{
mpiP_tslist_elem_t *curr = NULL;
if(MPIPI_MODE_ST == mt_state->mode) {
/* Only update the cumulative time */
mpiPi_stats_thr_timer_stop(&mt_state->rank_stats);
return;
}
curr = mpiPi_tslist_first(mt_state->tls_list);
/* Go over all TLS structures and update the timers */
while (curr)
{
mpiPi_mt_stat_tls_t *hndl = curr->ptr;
if( hndl->is_active )
{
mpiPi_stats_thr_timer_stop(hndl->tls_ptr);
}
curr = mpiPi_tslist_next(curr);
}
}
double mpiPi_stats_mt_cum_time(mpiPi_mt_stat_t *mt_state)
{
return mpiPi_stats_thr_cum_time(&mt_state->rank_stats);
}
void mpiPi_stats_mt_cs_gather(mpiPi_mt_stat_t *mt_state,
int *ac, callsite_stats_t ***av)
{
mpiPi_stats_thr_cs_gather(&mt_state->rank_stats, ac, av);
}
void mpiPi_stats_mt_cs_upd (mpiPi_mt_stat_tls_t *hndl,
unsigned op, unsigned rank, void **pc,
double dur, double sendSize, double ioSize,
double rmaSize)
{
mpiPi_stats_thr_cs_upd(hndl->tls_ptr, op, rank, pc, dur,
sendSize, ioSize, rmaSize);
}
void mpiPi_stats_mt_cs_lookup(mpiPi_mt_stat_t *stat,
callsite_stats_t *task_stats,
callsite_stats_t **task_lookup,
callsite_stats_t *dummy_buf,
int initMax)
{
mpiPi_stats_thr_cs_lookup(&stat->rank_stats, task_stats, task_lookup,
dummy_buf, initMax);
}
void mpiPi_stats_mt_coll_upd(mpiPi_mt_stat_tls_t *hndl,
int op, double dur, double size,
MPI_Comm * comm)
{
mpiPi_stats_thr_coll_upd(hndl->tls_ptr, op, dur, size, comm);
}
void mpiPi_stats_mt_coll_gather(mpiPi_mt_stat_t *stat, double **_outbuf)
{
mpiPi_stats_thr_coll_gather(&stat->rank_stats, _outbuf);
}
void mpiPi_stats_mt_cs_reset(mpiPi_mt_stat_t *mt_state)
{
mpiP_tslist_elem_t *curr = NULL;
mpiPi_stats_thr_cs_reset(&mt_state->rank_stats);
if(MPIPI_MODE_ST == mt_state->mode) {
/* Only update the cumulative time */
return;
}
curr = mpiPi_tslist_first(mt_state->tls_list);
/* Go over all TLS structures and merge them into the rank-wide callsite info */
while (curr)
{
mpiPi_mt_stat_tls_t *hndl = curr->ptr;
mpiPi_stats_thr_cs_reset(hndl->tls_ptr);
curr = mpiPi_tslist_next(curr);
}
}
void mpiPi_stats_mt_coll_binstrings(mpiPi_mt_stat_t *stat,
int comm_idx, char *comm_buf,
int size_idx, char *size_buf)
{
mpiPi_stats_thr_coll_binstrings(&stat->rank_stats,
comm_idx, comm_buf,
size_idx, size_buf);
}
void mpiPi_stats_mt_pt2pt_upd (mpiPi_mt_stat_tls_t *hndl,
int op, double dur, double size,
MPI_Comm * comm)
{
mpiPi_stats_thr_pt2pt_upd(hndl->tls_ptr, op, dur, size, comm);
}
void mpiPi_stats_mt_pt2pt_gather(mpiPi_mt_stat_t *stat, double **_outbuf)
{
mpiPi_stats_thr_pt2pt_gather(&stat->rank_stats, _outbuf);
}
void mpiPi_stats_mt_pt2pt_binstrings(mpiPi_mt_stat_t *stat,
int comm_idx, char *comm_buf,
int size_idx, char *size_buf)
{
mpiPi_stats_thr_pt2pt_binstrings(&stat->rank_stats, comm_idx, comm_buf,
size_idx, size_buf);
}
void mpiPi_stats_mt_exit(mpiPi_mt_stat_tls_t *hndl)
{
mpiPi_stats_thr_exit(hndl->tls_ptr);
}
void mpiPi_stats_mt_enter(mpiPi_mt_stat_tls_t *hndl)
{
mpiPi_stats_thr_enter(hndl->tls_ptr);
}
int mpiPi_stats_mt_is_on(mpiPi_mt_stat_tls_t *hndl)
{
return mpiPi_stats_thr_is_on(hndl->tls_ptr);
}