StarPU Internal Handbook
knobs.h
Go to the documentation of this file.
1/* StarPU --- Runtime system for heterogeneous multicore architectures.
2 *
3 * Copyright (C) 2019-2022 Université de Bordeaux, CNRS (LaBRI UMR 5800), Inria
4 *
5 * StarPU is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public License as published by
7 * the Free Software Foundation; either version 2.1 of the License, or (at
8 * your option) any later version.
9 *
10 * StarPU is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 *
14 * See the GNU Lesser General Public License in COPYING.LGPL for more details.
15 */
16
17/* Performance counters and configurable knobs */
18
19#ifndef __KNOBS_H__
20#define __KNOBS_H__
21
24#include <stdint.h>
25#include <starpu.h>
26#include <common/config.h>
27
28#pragma GCC visibility push(hidden)
29
31#define STARPU_ASSERT_PERF_COUNTER_SCOPE_DEFINED(t) STARPU_ASSERT( \
32 (t == starpu_perf_counter_scope_global) \
33 || (t == starpu_perf_counter_scope_per_worker) \
34 || (t == starpu_perf_counter_scope_per_codelet) \
35 )
36
37#define STARPU_ASSERT_PERF_COUNTER_TYPE_DEFINED(t) STARPU_ASSERT( \
38 (t == starpu_perf_counter_type_int32) \
39 || (t == starpu_perf_counter_type_int64) \
40 || (t == starpu_perf_counter_type_float) \
41 || (t == starpu_perf_counter_type_double) \
42 )
43
44#define _STARPU_PERF_COUNTER_ID_SCOPE_BITS 4
45
47struct _starpu_worker;
48
49#define __STARPU_PERF_COUNTER_UPDATE_32BIT(OPNAME,OP,TYPENAME,TYPE) \
50static inline void _starpu_perf_counter_update_##OPNAME##_##TYPENAME(TYPE *ptr, TYPE value) \
51{ \
52 STARPU_ASSERT(sizeof(TYPE) == sizeof(uint32_t)); \
53 typedef uint32_t __attribute__((__may_alias__)) alias_uint32_t; \
54 typedef TYPE __attribute__((__may_alias__)) alias_##TYPE; \
55 \
56 uint32_t raw_old = *(uint32_t *)ptr; \
57 \
58 while(value OP *(alias_##TYPE*)&raw_old) \
59 { \
60 uint32_t raw_old_check = STARPU_VAL_COMPARE_AND_SWAP32((uint32_t *)ptr, raw_old, *(alias_uint32_t*)&value); \
61 if (raw_old_check == raw_old) \
62 break; \
63 raw_old = raw_old_check; \
64 } \
65}
66
67#define __STARPU_PERF_COUNTER_UPDATE_64BIT(OPNAME,OP,TYPENAME,TYPE) \
68static inline void _starpu_perf_counter_update_##OPNAME##_##TYPENAME(TYPE *ptr, TYPE value) \
69{ \
70 STARPU_ASSERT(sizeof(TYPE) == sizeof(uint64_t)); \
71 typedef uint64_t __attribute__((__may_alias__)) alias_uint64_t; \
72 typedef TYPE __attribute__((__may_alias__)) alias_##TYPE; \
73 \
74 uint64_t raw_old = *(uint64_t *)ptr; \
75 \
76 while(value OP *(alias_##TYPE*)&raw_old) \
77 { \
78 uint64_t raw_old_check = STARPU_VAL_COMPARE_AND_SWAP64((uint64_t *)ptr, raw_old, *(alias_uint64_t*)&value); \
79 if (raw_old_check == raw_old) \
80 break; \
81 raw_old = raw_old_check; \
82 } \
83}
84
85/* Atomic max */
86__STARPU_PERF_COUNTER_UPDATE_32BIT(max,>=,int32,int32_t);
87__STARPU_PERF_COUNTER_UPDATE_32BIT(max,>=,float,float);
88__STARPU_PERF_COUNTER_UPDATE_64BIT(max,>=,int64,int64_t);
89__STARPU_PERF_COUNTER_UPDATE_64BIT(max,>=,double,double);
90
91/* Atomic min */
92__STARPU_PERF_COUNTER_UPDATE_32BIT(min,<=,int32,int32_t);
93__STARPU_PERF_COUNTER_UPDATE_32BIT(min,<=,float,float);
94__STARPU_PERF_COUNTER_UPDATE_64BIT(min,<=,int64,int64_t);
95__STARPU_PERF_COUNTER_UPDATE_64BIT(min,<=,double,double);
96
97#undef __STARPU_PERF_COUNTER_UPDATE_32BIT
98#undef __STARPU_PERF_COUNTER_UPDATE_64BIT
99
101static inline void _starpu_perf_counter_update_acc_float(float *ptr, float acc_value)
102{
103 STARPU_ASSERT(sizeof(float) == sizeof(uint32_t));
104 typedef uint32_t __attribute__((__may_alias__)) alias_uint32_t;
105 typedef float __attribute__((__may_alias__)) alias_float;
106 uint32_t raw_old = *(uint32_t *)ptr;
107 while (1)
108 {
109 float value = acc_value + *(alias_float*)&raw_old;
110 uint32_t raw_old_check = STARPU_VAL_COMPARE_AND_SWAP32((uint32_t *)ptr, raw_old, *(alias_uint32_t*)&value);
111 if (raw_old_check == raw_old)
112 break;
113 raw_old = raw_old_check;
114 }
115}
116static inline void _starpu_perf_counter_update_acc_double(double *ptr, double acc_value)
117{
118 STARPU_ASSERT(sizeof(double) == sizeof(uint64_t));
119 typedef uint64_t __attribute__((__may_alias__)) alias_uint64_t;
120 typedef double __attribute__((__may_alias__)) alias_double;
121 uint64_t raw_old = *(uint64_t *)ptr;
122 while (1)
123 {
124 double value = acc_value + *(alias_double*)&raw_old;
125 uint64_t raw_old_check = STARPU_VAL_COMPARE_AND_SWAP64((uint64_t *)ptr, raw_old, *(alias_uint64_t*)&value);
126 if (raw_old_check == raw_old)
127 break;
128 raw_old = raw_old_check;
129 }
130}
131
133{
134 int id;
135 const char *name;
136 const char *help;
137 enum starpu_perf_counter_type type;
138};
139
141{
142 enum starpu_perf_counter_scope scope;
143 int size;
144 int *index_array;
145};
146
148{
149 int32_t int32_val;
150 int64_t int64_val;
151 float float_val;
152 double double_val;
153};
154
156{
157 struct starpu_perf_counter_set *set;
158 void (*callback)(struct starpu_perf_counter_listener *listener, struct starpu_perf_counter_sample *sample, void *context);
159 void *user_arg;
160};
161
163{
164 enum starpu_perf_counter_scope scope;
165 struct starpu_perf_counter_listener *listener;
166 union starpu_perf_counter_value *value_array;
167 struct _starpu_spinlock lock;
168};
169
171{
172 struct
173 {
174 int64_t total_submitted;
175 int64_t peak_submitted;
176 int64_t current_submitted;
177 int64_t peak_ready;
178 int64_t current_ready;
179 int64_t total_executed;
180 double cumul_execution_time;
181 } task;
182};
183
184typedef void (*starpu_perf_counter_sample_updater)(struct starpu_perf_counter_sample *sample, void *context);
185
186static inline enum starpu_perf_counter_scope _starpu_perf_counter_id_get_scope(const int counter_id)
187{
188 STARPU_ASSERT(counter_id >= 0);
189 return counter_id & ((1 << _STARPU_PERF_COUNTER_ID_SCOPE_BITS) - 1);
190}
191
192static inline int _starpu_perf_counter_id_get_index(const int counter_id)
193{
194 STARPU_ASSERT(counter_id >= 0);
195 return counter_id >> _STARPU_PERF_COUNTER_ID_SCOPE_BITS;
196}
197
198static inline int _starpu_perf_counter_id_build(const enum starpu_perf_counter_scope scope, const int index)
199{
201 STARPU_ASSERT(index >= 0);
202 return (index << _STARPU_PERF_COUNTER_ID_SCOPE_BITS) | scope;
203}
204
205
206void _starpu_perf_counter_sample_init(struct starpu_perf_counter_sample *sample, enum starpu_perf_counter_scope scope);
207void _starpu_perf_counter_sample_exit(struct starpu_perf_counter_sample *sample);
208void _starpu_perf_counter_init(struct _starpu_machine_config *pconfig);
209void _starpu_perf_counter_exit(void);
210
211int _starpu_perf_counter_register(enum starpu_perf_counter_scope scope, const char *name, enum starpu_perf_counter_type type, const char *help);
212void _starpu_perf_counter_unregister_all_scopes(void);
213
214void _starpu_perf_counter_register_updater(enum starpu_perf_counter_scope scope, void (*updater)(struct starpu_perf_counter_sample *sample, void *context));
215
216void _starpu_perf_counter_update_global_sample(void);
217void _starpu_perf_counter_update_per_worker_sample(unsigned workerid);
218void _starpu_perf_counter_update_per_codelet_sample(struct starpu_codelet *cl);
219
220#define __STARPU_PERF_COUNTER_SAMPLE_SET_TYPED_VALUE(STRING, TYPE) \
221static inline void _starpu_perf_counter_sample_set_##STRING##_value(struct starpu_perf_counter_sample *sample, const int counter_id, const TYPE value) \
222{ \
223 STARPU_ASSERT(starpu_perf_counter_get_type_id(counter_id) == starpu_perf_counter_type_##STRING); \
224 STARPU_ASSERT(sample->listener != NULL && sample->listener->set != NULL); \
225 STARPU_ASSERT(_starpu_perf_counter_id_get_scope(counter_id) == sample->listener->set->scope); \
226 \
227 const struct starpu_perf_counter_set * const set = sample->listener->set; \
228 const int index = _starpu_perf_counter_id_get_index(counter_id); \
229 STARPU_ASSERT(index < set->size); \
230 if (set->index_array[index] > 0) \
231 { \
232 sample->value_array[index].STRING##_val = value; \
233 } \
234}
235
236__STARPU_PERF_COUNTER_SAMPLE_SET_TYPED_VALUE(int32, int32_t);
237__STARPU_PERF_COUNTER_SAMPLE_SET_TYPED_VALUE(int64, int64_t);
238__STARPU_PERF_COUNTER_SAMPLE_SET_TYPED_VALUE(float, float);
239__STARPU_PERF_COUNTER_SAMPLE_SET_TYPED_VALUE(double, double);
240
241#undef __STARPU_PERF_COUNTER_SAMPLE_SET_TYPED_VALUE
242
243#define __STARPU_PERF_COUNTER_REG(PREFIX, SCOPE, CTR, TYPESTRING, HELP) \
244 do \
245 { \
246 __##CTR = _starpu_perf_counter_register(SCOPE, \
247 PREFIX "." #CTR, starpu_perf_counter_type_ ## TYPESTRING, \
248 HELP); \
249 } \
250 while (0)
251
252/* global counter variables */
253extern int64_t _starpu_task__g_total_submitted__value;
254extern int64_t _starpu_task__g_peak_submitted__value;
255extern int64_t _starpu_task__g_current_submitted__value;
256extern int64_t _starpu_task__g_peak_ready__value;
257extern int64_t _starpu_task__g_current_ready__value;
258
259/* performance counter registration routines per modules */
260void _starpu__task_c__register_counters(void); /* module: task.c */
261
262
263/* -------------------------------------------------------------------- */
264/* Performance Steering */
265
266#define STARPU_ASSERT_PERF_KNOB_SCOPE_DEFINED(t) STARPU_ASSERT( \
267 (t == starpu_perf_knob_scope_global) \
268 || (t == starpu_perf_knob_scope_per_worker) \
269 || (t == starpu_perf_knob_scope_per_scheduler) \
270 )
271
272#define STARPU_ASSERT_PERF_KNOB_TYPE_DEFINED(t) STARPU_ASSERT( \
273 (t == starpu_perf_knob_type_int32) \
274 || (t == starpu_perf_knob_type_int64) \
275 || (t == starpu_perf_knob_type_float) \
276 || (t == starpu_perf_knob_type_double) \
277 )
278
279#define _STARPU_PERF_KNOBS_ID_SCOPE_BITS 4
280
281struct starpu_perf_knob;
282
284{
285 enum starpu_perf_knob_type type;
286 union
287 {
288 int32_t val_int32_t;
289 int64_t val_int64_t;
290 float val_float;
291 double val_double;
292 };
293};
294
296{
297 enum starpu_perf_knob_scope scope;
298 void (*set)(const struct starpu_perf_knob * const knob, void *context, const struct starpu_perf_knob_value * const value);
299 void (*get)(const struct starpu_perf_knob * const knob, void *context, struct starpu_perf_knob_value * const value);
300 int array_size;
301 struct starpu_perf_knob **array;
302};
303
305{
306 int id;
307 int id_in_group;
308 const char *name;
309 const char *help;
310 enum starpu_perf_knob_type type;
311 struct starpu_perf_knob_group *group;
312};
313
314#define __STARPU_PERF_KNOB_REG(PREFIX, SCOPE, CTR, TYPESTRING, HELP) \
315 do \
316 { \
317 __##CTR = _starpu_perf_knob_register(SCOPE, \
318 PREFIX "." #CTR, starpu_perf_knob_type_ ## TYPESTRING, \
319 HELP); \
320 } \
321 while (0)
322
323static inline int _starpu_perf_knob_id_get_scope(const int knob_id)
324{
325 STARPU_ASSERT(knob_id >= 0);
326 return knob_id & ((1 << _STARPU_PERF_KNOBS_ID_SCOPE_BITS) - 1);
327}
328
329static inline int _starpu_perf_knob_id_get_index(const int knob_id)
330{
331 STARPU_ASSERT(knob_id >= 0);
332 return knob_id >> _STARPU_PERF_KNOBS_ID_SCOPE_BITS;
333}
334
335static inline int _starpu_perf_knob_id_build(const enum starpu_perf_knob_scope scope, const int index)
336{
337 STARPU_ASSERT_PERF_KNOB_SCOPE_DEFINED(scope);
338 STARPU_ASSERT(index >= 0);
339 return (index << _STARPU_PERF_KNOBS_ID_SCOPE_BITS) | scope;
340}
341
342void _starpu_perf_knob_init(void);
343void _starpu_perf_knob_exit(void);
344
345struct starpu_perf_knob_group *_starpu_perf_knob_group_register(enum starpu_perf_knob_scope scope,
346 void (*set_func)(const struct starpu_perf_knob * const knob, void *context, const struct starpu_perf_knob_value * const value),
347 void (*get_func)(const struct starpu_perf_knob * const knob, void *context, struct starpu_perf_knob_value * const value));
348void _starpu_perf_knob_group_unregister(struct starpu_perf_knob_group *group);
349
350int _starpu_perf_knob_register(struct starpu_perf_knob_group *group, const char *name, enum starpu_perf_knob_type type, const char *help);
351void _starpu_perf_knob_unregister_all_scopes(void);
352
353/* performance knob registration routines per modules */
354void _starpu__workers_c__register_knobs(void); /* module: workers.c */
355void _starpu__task_c__register_knobs(void); /* module: task.c */
356void _starpu__dmda_c__register_knobs(void); /* module: dmda.c */
357void _starpu__workers_c__unregister_knobs(void); /* module: workers.c */
358void _starpu__task_c__unregister_knobs(void); /* module: task.c */
359void _starpu__dmda_c__unregister_knobs(void); /* module: dmda.c */
360
361#pragma GCC visibility pop
362
363#endif // __KNOBS_H__
#define STARPU_ASSERT_PERF_COUNTER_SCOPE_DEFINED(t)
Definition: knobs.h:31
static void _starpu_perf_counter_update_acc_float(float *ptr, float acc_value)
Definition: knobs.h:101
Definition: knobs.h:133
Definition: knobs.h:163
Definition: knobs.h:141
Definition: knobs.h:305
Definition: knobs.h:284
Definition: knobs.h:148
Definition: starpu_spinlock.h:82
Definition: workers.h:441
Definition: workers.h:155
Definition: knobs.h:156
Definition: knobs.h:296