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 
47 struct _starpu_worker;
48 
49 #define __STARPU_PERF_COUNTER_UPDATE_32BIT(OPNAME,OP,TYPENAME,TYPE) \
50 static 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) \
68 static 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 
101 static 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 }
116 static 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 
184 typedef void (*starpu_perf_counter_sample_updater)(struct starpu_perf_counter_sample *sample, void *context);
185 
186 static 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 
192 static 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 
198 static 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 
206 void _starpu_perf_counter_sample_init(struct starpu_perf_counter_sample *sample, enum starpu_perf_counter_scope scope);
207 void _starpu_perf_counter_sample_exit(struct starpu_perf_counter_sample *sample);
208 void _starpu_perf_counter_init(struct _starpu_machine_config *pconfig);
209 void _starpu_perf_counter_exit(void);
210 
211 int _starpu_perf_counter_register(enum starpu_perf_counter_scope scope, const char *name, enum starpu_perf_counter_type type, const char *help);
212 void _starpu_perf_counter_unregister_all_scopes(void);
213 
214 void _starpu_perf_counter_register_updater(enum starpu_perf_counter_scope scope, void (*updater)(struct starpu_perf_counter_sample *sample, void *context));
215 
216 void _starpu_perf_counter_update_global_sample(void);
217 void _starpu_perf_counter_update_per_worker_sample(unsigned workerid);
218 void _starpu_perf_counter_update_per_codelet_sample(struct starpu_codelet *cl);
219 
220 #define __STARPU_PERF_COUNTER_SAMPLE_SET_TYPED_VALUE(STRING, TYPE) \
221 static 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 */
253 extern int64_t _starpu_task__g_total_submitted__value;
254 extern int64_t _starpu_task__g_peak_submitted__value;
255 extern int64_t _starpu_task__g_current_submitted__value;
256 extern int64_t _starpu_task__g_peak_ready__value;
257 extern int64_t _starpu_task__g_current_ready__value;
258 
259 /* performance counter registration routines per modules */
260 void _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 
281 struct 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 
323 static 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 
329 static 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 
335 static 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 
342 void _starpu_perf_knob_init(void);
343 void _starpu_perf_knob_exit(void);
344 
345 struct 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));
348 void _starpu_perf_knob_group_unregister(struct starpu_perf_knob_group *group);
349 
350 int _starpu_perf_knob_register(struct starpu_perf_knob_group *group, const char *name, enum starpu_perf_knob_type type, const char *help);
351 void _starpu_perf_knob_unregister_all_scopes(void);
352 
353 /* performance knob registration routines per modules */
354 void _starpu__workers_c__register_knobs(void); /* module: workers.c */
355 void _starpu__task_c__register_knobs(void); /* module: task.c */
356 void _starpu__dmda_c__register_knobs(void); /* module: dmda.c */
357 void _starpu__workers_c__unregister_knobs(void); /* module: workers.c */
358 void _starpu__task_c__unregister_knobs(void); /* module: task.c */
359 void _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