Branch data Line data Source code
1 : : /* StarPU --- Runtime system for heterogeneous multicore architectures.
2 : : *
3 : : * Copyright (C) 2009-2012 Université de Bordeaux 1
4 : : * Copyright (C) 2010, 2011, 2012 Centre National de la Recherche Scientifique
5 : : * Copyright (C) 2011 Télécom-SudParis
6 : : *
7 : : * StarPU is free software; you can redistribute it and/or modify
8 : : * it under the terms of the GNU Lesser General Public License as published by
9 : : * the Free Software Foundation; either version 2.1 of the License, or (at
10 : : * your option) any later version.
11 : : *
12 : : * StarPU is distributed in the hope that it will be useful, but
13 : : * WITHOUT ANY WARRANTY; without even the implied warranty of
14 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15 : : *
16 : : * See the GNU Lesser General Public License in COPYING.LGPL for more details.
17 : : */
18 : :
19 : : #include <dirent.h>
20 : : #include <unistd.h>
21 : : #include <sys/stat.h>
22 : : #include <errno.h>
23 : : #include <common/config.h>
24 : : #include <common/utils.h>
25 : : #include <core/perfmodel/perfmodel.h>
26 : : #include <core/jobs.h>
27 : : #include <core/workers.h>
28 : : #include <pthread.h>
29 : : #include <datawizard/datawizard.h>
30 : : #include <core/perfmodel/regression.h>
31 : : #include <common/config.h>
32 : : #include <starpu_parameters.h>
33 : :
34 : : #ifdef STARPU_HAVE_WINDOWS
35 : : #include <windows.h>
36 : : #endif
37 : :
38 : : /* We want more than 10% variance on X to trust regression */
39 : : #define VALID_REGRESSION(reg_model) \
40 : : ((reg_model)->minx < (9*(reg_model)->maxx)/10 && (reg_model)->nsample >= _STARPU_CALIBRATION_MINIMUM)
41 : :
42 : : static pthread_rwlock_t registered_models_rwlock;
43 : : static struct starpu_model_list *registered_models = NULL;
44 : :
45 : : /*
46 : : * History based model
47 : : */
48 : 705 : static void insert_history_entry(struct starpu_history_entry *entry, struct starpu_history_list **list, struct starpu_htbl32_node **history_ptr)
49 : : {
50 : : struct starpu_history_list *link;
51 : : struct starpu_history_entry *old;
52 : :
53 : 705 : link = (struct starpu_history_list *) malloc(sizeof(struct starpu_history_list));
54 : 705 : link->next = *list;
55 : 705 : link->entry = entry;
56 : 705 : *list = link;
57 : :
58 : 705 : old = (struct starpu_history_entry *) _starpu_htbl_insert_32(history_ptr, entry->footprint, entry);
59 : : /* that may fail in case there is some concurrency issue */
60 [ - + ]: 705 : STARPU_ASSERT(old == NULL);
61 : 705 : }
62 : :
63 : 100 : static void dump_reg_model(FILE *f, struct starpu_perfmodel *model, unsigned arch, unsigned nimpl)
64 : : {
65 : : struct starpu_per_arch_perfmodel *per_arch_model;
66 : :
67 : 100 : per_arch_model = &model->per_arch[arch][nimpl];
68 : : struct starpu_regression_model *reg_model;
69 : 100 : reg_model = &per_arch_model->regression;
70 : :
71 : : /*
72 : : * Linear Regression model
73 : : */
74 : :
75 : : /* Unless we have enough measurements, we put NaN in the file to indicate the model is invalid */
76 : 100 : double alpha = nan(""), beta = nan("");
77 [ + + ][ + + ]: 100 : if (model->type == STARPU_REGRESSION_BASED || model->type == STARPU_NL_REGRESSION_BASED)
78 : : {
79 [ + - ]: 12 : if (reg_model->nsample > 1)
80 : : {
81 : 12 : alpha = reg_model->alpha;
82 : 12 : beta = reg_model->beta;
83 : : }
84 : : }
85 : :
86 : 100 : fprintf(f, "# sumlnx\tsumlnx2\t\tsumlny\t\tsumlnxlny\talpha\t\tbeta\t\tn\tminx\t\tmaxx\n");
87 : 100 : fprintf(f, "%-15le\t%-15le\t%-15le\t%-15le\t%-15le\t%-15le\t%u\t%-15lu\t%-15lu\n", reg_model->sumlnx, reg_model->sumlnx2, reg_model->sumlny, reg_model->sumlnxlny, alpha, beta, reg_model->nsample, reg_model->minx, reg_model->maxx);
88 : :
89 : : /*
90 : : * Non-Linear Regression model
91 : : */
92 : :
93 : 100 : double a = nan(""), b = nan(""), c = nan("");
94 : :
95 [ + + ]: 100 : if (model->type == STARPU_NL_REGRESSION_BASED)
96 : 8 : _starpu_regression_non_linear_power(per_arch_model->list, &a, &b, &c);
97 : :
98 : 100 : fprintf(f, "# a\t\tb\t\tc\n");
99 : 100 : fprintf(f, "%-15le\t%-15le\t%-15le\n", a, b, c);
100 : 100 : }
101 : :
102 : 581 : static void scan_reg_model(FILE *f, struct starpu_regression_model *reg_model)
103 : : {
104 : : int res;
105 : :
106 : : /*
107 : : * Linear Regression model
108 : : */
109 : :
110 : 581 : _starpu_drop_comments(f);
111 : :
112 : 581 : res = fscanf(f, "%le\t%le\t%le\t%le\t%le\t%le\t%u\t%lu\t%lu\n",
113 : : ®_model->sumlnx, ®_model->sumlnx2, ®_model->sumlny,
114 : : ®_model->sumlnxlny, ®_model->alpha, ®_model->beta,
115 : : ®_model->nsample,
116 : : ®_model->minx, ®_model->maxx);
117 [ - + ]: 581 : STARPU_ASSERT(res == 9);
118 : :
119 : : /* If any of the parameters describing the linear regression model is NaN, the model is invalid */
120 [ - + ][ # # ]: 581 : unsigned invalid = (isnan(reg_model->alpha)||isnan(reg_model->beta));
121 [ - + ][ # # ]: 581 : reg_model->valid = !invalid && VALID_REGRESSION(reg_model);
[ # # ]
122 : :
123 : : /*
124 : : * Non-Linear Regression model
125 : : */
126 : :
127 : 581 : _starpu_drop_comments(f);
128 : :
129 : 581 : res = fscanf(f, "%le\t%le\t%le\n", ®_model->a, ®_model->b, ®_model->c);
130 [ - + ]: 581 : STARPU_ASSERT(res == 3);
131 : :
132 : : /* If any of the parameters describing the non-linear regression model is NaN, the model is invalid */
133 [ - + ][ # # ]: 581 : unsigned nl_invalid = (isnan(reg_model->a)||isnan(reg_model->b)||isnan(reg_model->c));
[ # # ]
134 [ - + ][ # # ]: 581 : reg_model->nl_valid = !nl_invalid && VALID_REGRESSION(reg_model);
[ # # ]
135 : 581 : }
136 : :
137 : 212 : static void dump_history_entry(FILE *f, struct starpu_history_entry *entry)
138 : : {
139 : 212 : fprintf(f, "%08x\t%-15lu\t%-15le\t%-15le\t%-15le\t%-15le\t%u\n", entry->footprint, (unsigned long) entry->size, entry->mean, entry->deviation, entry->sum, entry->sum2, entry->nsample);
140 : 212 : }
141 : :
142 : 581 : static void scan_history_entry(FILE *f, struct starpu_history_entry *entry)
143 : : {
144 : : int res;
145 : :
146 : 581 : _starpu_drop_comments(f);
147 : :
148 : : /* In case entry is NULL, we just drop these values */
149 : : unsigned nsample;
150 : : uint32_t footprint;
151 : : #ifdef STARPU_HAVE_WINDOWS
152 : : unsigned size; /* in bytes */
153 : : #else
154 : : size_t size; /* in bytes */
155 : : #endif
156 : : double mean;
157 : : double deviation;
158 : : double sum;
159 : : double sum2;
160 : :
161 : : /* Read the values from the file */
162 : 581 : res = fscanf(f, "%x\t%"
163 : : #ifndef STARPU_HAVE_WINDOWS
164 : : "z"
165 : : #endif
166 : : "u\t%le\t%le\t%le\t%le\t%u\n", &footprint, &size, &mean, &deviation, &sum, &sum2, &nsample);
167 [ - + ]: 581 : STARPU_ASSERT(res == 7);
168 : :
169 [ + - ]: 581 : if (entry)
170 : : {
171 : 581 : entry->footprint = footprint;
172 : 581 : entry->size = size;
173 : 581 : entry->mean = mean;
174 : 581 : entry->deviation = deviation;
175 : 581 : entry->sum = sum;
176 : 581 : entry->sum2 = sum2;
177 : 581 : entry->nsample = nsample;
178 : : }
179 : 581 : }
180 : :
181 : 581 : static void parse_per_arch_model_file(FILE *f, struct starpu_per_arch_perfmodel *per_arch_model, unsigned scan_history)
182 : : {
183 : : unsigned nentries;
184 : :
185 : 581 : _starpu_drop_comments(f);
186 : :
187 : 581 : int res = fscanf(f, "%u\n", &nentries);
188 [ - + ]: 581 : STARPU_ASSERT(res == 1);
189 : :
190 : 581 : scan_reg_model(f, &per_arch_model->regression);
191 : :
192 : : /* parse cpu entries */
193 : : unsigned i;
194 [ + + ]: 1162 : for (i = 0; i < nentries; i++)
195 : : {
196 : 581 : struct starpu_history_entry *entry = NULL;
197 [ + - ]: 581 : if (scan_history)
198 : : {
199 : 581 : entry = (struct starpu_history_entry *) malloc(sizeof(struct starpu_history_entry));
200 [ - + ]: 581 : STARPU_ASSERT(entry);
201 : : }
202 : :
203 : 581 : scan_history_entry(f, entry);
204 : :
205 : : /* insert the entry in the hashtable and the list structures */
206 [ + - ]: 581 : if (scan_history)
207 : 581 : insert_history_entry(entry, &per_arch_model->list, &per_arch_model->history);
208 : : }
209 : 581 : }
210 : :
211 : 256 : static void parse_arch(FILE *f, struct starpu_perfmodel *model, unsigned scan_history, unsigned archmin, unsigned archmax, unsigned skiparch)
212 : : {
213 : : struct starpu_per_arch_perfmodel dummy;
214 : : int nimpls, implmax, skipimpl, impl;
215 : : unsigned ret, arch;
216 : :
217 [ + + ]: 840 : for (arch = archmin; arch < archmax; arch++)
218 : : {
219 [ + - ]: 584 : _STARPU_DEBUG("Parsing arch %u\n", arch);
220 : 584 : _starpu_drop_comments(f);
221 : 584 : ret = fscanf(f, "%d\n", &nimpls);
222 [ + - ]: 584 : _STARPU_DEBUG("%u implementations\n", nimpls);
223 [ - + ]: 584 : STARPU_ASSERT(ret == 1);
224 : 584 : implmax = STARPU_MIN(nimpls, STARPU_MAXIMPLEMENTATIONS);
225 : 584 : skipimpl = nimpls - STARPU_MAXIMPLEMENTATIONS;
226 [ + + ]: 1165 : for (impl = 0; impl < implmax; impl++)
227 : : {
228 : 581 : parse_per_arch_model_file(f, &model->per_arch[arch][impl], scan_history);
229 : : }
230 [ - + ]: 584 : if (skipimpl > 0)
231 : : {
232 [ # # ]: 0 : for (impl = 0; impl < skipimpl; impl++)
233 : : {
234 : 0 : parse_per_arch_model_file(f, &dummy, 0);
235 : : }
236 : : }
237 : : }
238 : :
239 [ - + ]: 256 : if (skiparch > 0)
240 : : {
241 : 0 : _starpu_drop_comments(f);
242 [ # # ]: 0 : for (arch = 0; arch < skiparch; arch ++)
243 : : {
244 [ # # ]: 0 : _STARPU_DEBUG("skipping arch %u\n", arch);
245 : 0 : ret = fscanf(f, "%d\n", &nimpls);
246 [ # # ]: 0 : _STARPU_DEBUG("%u implementations\n", nimpls);
247 [ # # ]: 0 : STARPU_ASSERT(ret == 1);
248 : 0 : implmax = STARPU_MIN(nimpls, STARPU_MAXIMPLEMENTATIONS);
249 : 0 : skipimpl = nimpls - STARPU_MAXIMPLEMENTATIONS;
250 [ # # ]: 0 : for (impl = 0; impl < implmax; impl++)
251 : : {
252 : 0 : parse_per_arch_model_file(f, &dummy, 0);
253 : : }
254 [ # # ]: 0 : if (skipimpl > 0)
255 : : {
256 [ # # ]: 0 : for (impl = 0; impl < skipimpl; impl++)
257 : : {
258 : 0 : parse_per_arch_model_file(f, &dummy, 0);
259 : : }
260 : : }
261 : : }
262 : : }
263 : 256 : }
264 : :
265 : 169 : static void parse_model_file(FILE *f, struct starpu_perfmodel *model, unsigned scan_history)
266 : : {
267 : : unsigned ret;
268 : 169 : unsigned archmin = 0;
269 : 169 : unsigned max_gordondevs = 1; /* XXX : we need a STARPU_MAXGORDONDEVS cst */
270 : : unsigned narchs;
271 : :
272 : : /* We could probably write a clean loop here, but the code would not
273 : : * really be easier to read. */
274 : :
275 : : /* Parsing CPUs */
276 : 169 : _starpu_drop_comments(f);
277 : 169 : ret = fscanf(f, "%u\n", &narchs);
278 [ - + ]: 169 : STARPU_ASSERT(ret == 1);
279 : :
280 [ + - ]: 169 : _STARPU_DEBUG("Parsing %u CPUs\n", narchs);
281 [ + + ]: 169 : if (narchs > 0)
282 : : {
283 [ - + ]: 96 : parse_arch(f, model, scan_history,
284 : : archmin,
285 : : STARPU_MIN(narchs, STARPU_MAXCPUS),
286 : 96 : narchs > STARPU_MAXCPUS ? narchs - STARPU_MAXCPUS : 0);
287 : : }
288 : :
289 : : /* Parsing CUDA devs */
290 : 169 : _starpu_drop_comments(f);
291 : 169 : ret = fscanf(f, "%u\n", &narchs);
292 [ - + ]: 169 : STARPU_ASSERT(ret == 1);
293 : 169 : archmin += STARPU_MAXCPUS;
294 [ + - ]: 169 : _STARPU_DEBUG("Parsing %u CUDA devices\n", narchs);
295 [ + + ]: 169 : if (narchs > 0)
296 : : {
297 [ - + ]: 160 : parse_arch(f, model, scan_history,
298 : : archmin,
299 : 160 : archmin + STARPU_MIN(narchs, STARPU_MAXCUDADEVS),
300 : 160 : narchs > STARPU_MAXCUDADEVS ? narchs - STARPU_MAXCUDADEVS : 0);
301 : : }
302 : :
303 : : /* Parsing OpenCL devs */
304 : 169 : _starpu_drop_comments(f);
305 : 169 : ret = fscanf(f, "%u\n", &narchs);
306 [ - + ]: 169 : STARPU_ASSERT(ret == 1);
307 : :
308 : 169 : archmin += STARPU_MAXCUDADEVS;
309 [ + - ]: 169 : _STARPU_DEBUG("Parsing %u OpenCL devices\n", narchs);
310 [ - + ]: 169 : if (narchs > 0)
311 : : {
312 [ # # ]: 0 : parse_arch(f, model, scan_history,
313 : : archmin,
314 : 0 : archmin + STARPU_MIN(narchs, STARPU_MAXOPENCLDEVS),
315 : 0 : narchs > STARPU_MAXOPENCLDEVS ? narchs - STARPU_MAXOPENCLDEVS : 0);
316 : : }
317 : :
318 : : /* Parsing Gordon implementations */
319 : 169 : _starpu_drop_comments(f);
320 : 169 : ret = fscanf(f, "%u\n", &narchs);
321 [ - + ]: 169 : STARPU_ASSERT(ret == 1);
322 : :
323 : 169 : archmin += STARPU_MAXOPENCLDEVS;
324 [ + - ]: 169 : _STARPU_DEBUG("Parsing %u Gordon devices\n", narchs);
325 [ - + ]: 169 : if (narchs > 0)
326 : : {
327 [ # # ]: 0 : parse_arch(f, model, scan_history,
328 : : archmin,
329 : : archmin + max_gordondevs,
330 : 0 : narchs > max_gordondevs ? narchs - max_gordondevs : 0);
331 : : }
332 : 169 : }
333 : :
334 : :
335 : 100 : static void dump_per_arch_model_file(FILE *f, struct starpu_perfmodel *model, unsigned arch, unsigned nimpl)
336 : : {
337 : : struct starpu_per_arch_perfmodel *per_arch_model;
338 : :
339 : 100 : per_arch_model = &model->per_arch[arch][nimpl];
340 : : /* count the number of elements in the lists */
341 : 100 : struct starpu_history_list *ptr = NULL;
342 : 100 : unsigned nentries = 0;
343 : :
344 [ + + ][ + + ]: 100 : if (model->type == STARPU_HISTORY_BASED || model->type == STARPU_NL_REGRESSION_BASED)
345 : : {
346 : : /* Dump the list of all entries in the history */
347 : 96 : ptr = per_arch_model->list;
348 [ + + ]: 308 : while(ptr)
349 : : {
350 : 212 : nentries++;
351 : 212 : ptr = ptr->next;
352 : : }
353 : : }
354 : :
355 : : /* header */
356 : : char archname[32];
357 : 100 : starpu_perfmodel_get_arch_name((enum starpu_perf_archtype) arch, archname, 32, nimpl);
358 : 100 : fprintf(f, "# Model for %s\n", archname);
359 : 100 : fprintf(f, "# number of entries\n%u\n", nentries);
360 : :
361 : 100 : dump_reg_model(f, model, arch, nimpl);
362 : :
363 : : /* Dump the history into the model file in case it is necessary */
364 [ + + ][ + + ]: 100 : if (model->type == STARPU_HISTORY_BASED || model->type == STARPU_NL_REGRESSION_BASED)
365 : : {
366 : 96 : fprintf(f, "# hash\t\tsize\t\tmean\t\tdev\t\tsum\t\tsum2\t\tn\n");
367 : 96 : ptr = per_arch_model->list;
368 [ + + ]: 308 : while (ptr)
369 : : {
370 : 212 : dump_history_entry(f, ptr->entry);
371 : 212 : ptr = ptr->next;
372 : : }
373 : : }
374 : :
375 : 100 : fprintf(f, "\n##################\n");
376 : 100 : }
377 : :
378 : 15728 : static unsigned get_n_entries(struct starpu_perfmodel *model, unsigned arch, unsigned impl)
379 : : {
380 : : struct starpu_per_arch_perfmodel *per_arch_model;
381 : 15728 : per_arch_model = &model->per_arch[arch][impl];
382 : : /* count the number of elements in the lists */
383 : 15728 : struct starpu_history_list *ptr = NULL;
384 : 15728 : unsigned nentries = 0;
385 : :
386 [ + + ][ + - ]: 15728 : if (model->type == STARPU_HISTORY_BASED || model->type == STARPU_NL_REGRESSION_BASED)
387 : : {
388 : : /* Dump the list of all entries in the history */
389 : 15728 : ptr = per_arch_model->list;
390 [ + + ]: 16152 : while(ptr)
391 : : {
392 : 424 : nentries++;
393 : 424 : ptr = ptr->next;
394 : : }
395 : : }
396 : 15728 : return nentries;
397 : : }
398 : :
399 : 27 : static void dump_model_file(FILE *f, struct starpu_perfmodel *model)
400 : : {
401 : 27 : unsigned narch[4] = { 0, 0, 0, 0};
402 : 27 : unsigned arch, arch_base = 0, my_narch = 0;
403 : : unsigned nimpl;
404 : 27 : unsigned idx = 0;
405 : :
406 : : /* Finding the number of archs to write for each kind of device */
407 [ + + ]: 2106 : for (arch = 0; arch < STARPU_NARCH_VARIATIONS; arch++)
408 : : {
409 [ + + ]: 2079 : switch (arch)
410 : : {
411 : : case STARPU_CUDA_DEFAULT:
412 : : case STARPU_OPENCL_DEFAULT:
413 : : case STARPU_GORDON_DEFAULT:
414 : 81 : arch_base = arch;
415 : 81 : idx++;
416 : 81 : break;
417 : : default:
418 : 1998 : break;
419 : : }
420 : :
421 [ + + ][ + + ]: 4081 : if (model->type == STARPU_HISTORY_BASED || model->type == STARPU_NL_REGRESSION_BASED)
422 : : {
423 [ + + ]: 9626 : for (nimpl = 0; nimpl < STARPU_MAXIMPLEMENTATIONS; nimpl++)
424 [ + + ]: 7720 : if (get_n_entries(model, arch, nimpl))
425 : : {
426 : 96 : narch[idx]=arch-arch_base+1;
427 : 96 : break;
428 : : }
429 : : }
430 [ + - ]: 77 : else if (model->type == STARPU_REGRESSION_BASED)
431 : : {
432 [ + + ]: 373 : for (nimpl = 0; nimpl < STARPU_MAXIMPLEMENTATIONS; nimpl++)
433 [ + + ]: 296 : if (model->per_arch[arch][nimpl].regression.nsample)
434 : : {
435 : 4 : narch[idx]=arch-arch_base+1;
436 : 4 : break;
437 : : }
438 : : }
439 : : else
440 : 0 : STARPU_ASSERT_MSG(0, "Unknown history-based performance model");
441 : : }
442 : :
443 : : /* Writing stuff */
444 : 27 : char *name = "unknown";
445 : 27 : unsigned substract_to_arch = 0;
446 [ + + ]: 2106 : for (arch = 0; arch < STARPU_NARCH_VARIATIONS; arch++)
447 : : {
448 [ + + + + : 2079 : switch (arch)
+ ]
449 : : {
450 : : case STARPU_CPU_DEFAULT:
451 : 27 : arch_base = arch;
452 : 27 : name = "CPU";
453 : 27 : fprintf(f, "##################\n");
454 : 27 : fprintf(f, "# %ss\n", name);
455 : 27 : fprintf(f, "# maximum number of %ss\n", name);
456 : 27 : fprintf(f, "%u\n", my_narch = narch[0]);
457 : 27 : break;
458 : : case STARPU_CUDA_DEFAULT:
459 : 27 : arch_base = arch;
460 : 27 : name = "CUDA";
461 : 27 : substract_to_arch = STARPU_MAXCPUS;
462 : 27 : fprintf(f, "##################\n");
463 : 27 : fprintf(f, "# %ss\n", name);
464 : 27 : fprintf(f, "# number of %s architectures\n", name);
465 : 27 : fprintf(f, "%u\n", my_narch = narch[1]);
466 : 27 : break;
467 : : case STARPU_OPENCL_DEFAULT:
468 : 27 : arch_base = arch;
469 : 27 : name = "OPENCL";
470 : 27 : substract_to_arch += STARPU_MAXCUDADEVS;
471 : 27 : fprintf(f, "##################\n");
472 : 27 : fprintf(f, "# %ss\n", name);
473 : 27 : fprintf(f, "# number of %s architectures\n", name);
474 : 27 : fprintf(f, "%u\n", my_narch = narch[2]);
475 : 27 : break;
476 : : case STARPU_GORDON_DEFAULT:
477 : 27 : arch_base = arch;
478 : 27 : name = "GORDON";
479 : 27 : substract_to_arch += STARPU_MAXOPENCLDEVS;
480 : 27 : fprintf(f, "##################\n");
481 : 27 : fprintf(f, "# %ss\n", name);
482 : 27 : fprintf(f, "# number of %s architectures\n", name);
483 : 27 : fprintf(f, "%u\n", my_narch = narch[3]);
484 : 27 : break;
485 : : default:
486 : 1971 : break;
487 : : }
488 : :
489 : 2079 : unsigned max_impl = 0;
490 [ + + ][ + + ]: 4081 : if (model->type == STARPU_HISTORY_BASED || model->type == STARPU_NL_REGRESSION_BASED)
491 : : {
492 [ + + ]: 10010 : for (nimpl = 0; nimpl < STARPU_MAXIMPLEMENTATIONS; nimpl++)
493 [ + + ]: 8008 : if (get_n_entries(model, arch, nimpl))
494 : 96 : max_impl = nimpl + 1;
495 : : }
496 [ + - ]: 77 : else if (model->type == STARPU_REGRESSION_BASED)
497 : : {
498 [ + + ]: 385 : for (nimpl = 0; nimpl < STARPU_MAXIMPLEMENTATIONS; nimpl++)
499 [ + + ]: 308 : if (model->per_arch[arch][nimpl].regression.nsample)
500 : 4 : max_impl = nimpl + 1;
501 : : }
502 : : else
503 : 0 : STARPU_ASSERT_MSG(0, "Unknown history-based performance model");
504 : :
505 [ + + ]: 2079 : if (arch >= my_narch + arch_base)
506 : 1979 : continue;
507 : :
508 : 100 : fprintf(f, "###########\n");
509 [ + + ]: 100 : if (substract_to_arch)
510 : 81 : fprintf(f, "# %s_%u\n", name, arch - substract_to_arch);
511 : : else
512 : : /* CPU */
513 : 19 : fprintf(f, "# %u CPU(s) in parallel\n", arch + 1);
514 : 100 : fprintf(f, "# number of implementations\n");
515 : 100 : fprintf(f, "%u\n", max_impl);
516 [ + + ]: 200 : for (nimpl = 0; nimpl < max_impl; nimpl++)
517 : : {
518 : 100 : dump_per_arch_model_file(f, model, arch, nimpl);
519 : : }
520 : : }
521 : 27 : }
522 : :
523 : 924 : static void initialize_per_arch_model(struct starpu_per_arch_perfmodel *per_arch_model)
524 : : {
525 : 924 : per_arch_model->history = NULL;
526 : 924 : per_arch_model->list = NULL;
527 : 924 : }
528 : :
529 : 3 : static void initialize_model(struct starpu_perfmodel *model)
530 : : {
531 : : unsigned arch;
532 : : unsigned nimpl;
533 [ + + ]: 234 : for (arch = 0; arch < STARPU_NARCH_VARIATIONS; arch++)
534 : : {
535 [ + + ]: 1155 : for (nimpl = 0; nimpl < STARPU_MAXIMPLEMENTATIONS; nimpl++)
536 : : {
537 : 924 : initialize_per_arch_model(&model->per_arch[arch][nimpl]);
538 : : }
539 : : }
540 : 3 : }
541 : :
542 : 0 : static void get_model_debug_path(struct starpu_perfmodel *model, const char *arch, char *path, size_t maxlen)
543 : : {
544 [ # # ]: 0 : STARPU_ASSERT(path);
545 : :
546 : 0 : _starpu_get_perf_model_dir_debug(path, maxlen);
547 : 0 : strncat(path, model->symbol, maxlen);
548 : :
549 : : char hostname[32];
550 : 0 : char *forced_hostname = getenv("STARPU_HOSTNAME");
551 [ # # ][ # # ]: 0 : if (forced_hostname && forced_hostname[0])
552 : 0 : snprintf(hostname, sizeof(hostname), "%s", forced_hostname);
553 : : else
554 : 0 : gethostname(hostname, sizeof(hostname));
555 : 0 : strncat(path, ".", maxlen);
556 : 0 : strncat(path, hostname, maxlen);
557 : 0 : strncat(path, ".", maxlen);
558 : 0 : strncat(path, arch, maxlen);
559 : 0 : strncat(path, ".debug", maxlen);
560 : 0 : }
561 : :
562 : : /*
563 : : * Returns 0 is the model was already loaded, 1 otherwise.
564 : : */
565 : 176 : int _starpu_register_model(struct starpu_perfmodel *model)
566 : : {
567 : : /* If the model has already been loaded, there is nothing to do */
568 [ - + ]: 176 : _STARPU_PTHREAD_RWLOCK_RDLOCK(®istered_models_rwlock);
569 [ + + ]: 176 : if (model->is_loaded)
570 : : {
571 [ - + ]: 4 : _STARPU_PTHREAD_RWLOCK_UNLOCK(®istered_models_rwlock);
572 : 4 : return 0;
573 : : }
574 [ - + ]: 172 : _STARPU_PTHREAD_RWLOCK_UNLOCK(®istered_models_rwlock);
575 : :
576 : : /* We have to make sure the model has not been loaded since the
577 : : * last time we took the lock */
578 [ - + ]: 172 : _STARPU_PTHREAD_RWLOCK_WRLOCK(®istered_models_rwlock);
579 [ - + ]: 172 : if (model->is_loaded)
580 : : {
581 [ # # ]: 0 : _STARPU_PTHREAD_RWLOCK_UNLOCK(®istered_models_rwlock);
582 : 0 : return 0;
583 : : }
584 : :
585 : : /* add the model to a linked list */
586 : 172 : struct starpu_model_list *node = (struct starpu_model_list *) malloc(sizeof(struct starpu_model_list));
587 : :
588 : 172 : node->model = model;
589 : : //model->debug_modelid = debug_modelid++;
590 : :
591 : : /* put this model at the beginning of the list */
592 : 172 : node->next = registered_models;
593 : 172 : registered_models = node;
594 : :
595 : : #ifdef STARPU_MODEL_DEBUG
596 : : _starpu_create_sampling_directory_if_needed();
597 : :
598 : : unsigned arch;
599 : : unsigned nimpl;
600 : :
601 : : for (arch = 0; arch < STARPU_NARCH_VARIATIONS; arch++)
602 : : {
603 : : for (nimpl = 0; nimpl < STARPU_MAXIMPLEMENTATIONS; nimpl++)
604 : : {
605 : : starpu_perfmodel_debugfilepath(model, arch, model->per_arch[arch][nimpl].debug_path, 256, nimpl);
606 : : }
607 : : }
608 : : #endif
609 : :
610 [ - + ]: 172 : _STARPU_PTHREAD_RWLOCK_UNLOCK(®istered_models_rwlock);
611 : 176 : return 1;
612 : : }
613 : :
614 : 199 : static void get_model_path(struct starpu_perfmodel *model, char *path, size_t maxlen)
615 : : {
616 : 199 : _starpu_get_perf_model_dir_codelets(path, maxlen);
617 : 199 : strncat(path, model->symbol, maxlen);
618 : :
619 : : char hostname[32];
620 : 199 : char *forced_hostname = getenv("STARPU_HOSTNAME");
621 [ - + ][ # # ]: 199 : if (forced_hostname && forced_hostname[0])
622 : 0 : snprintf(hostname, sizeof(hostname), "%s", forced_hostname);
623 : : else
624 : 199 : gethostname(hostname, sizeof(hostname));
625 : 199 : strncat(path, ".", maxlen);
626 : 199 : strncat(path, hostname, maxlen);
627 : 199 : }
628 : :
629 : 27 : static void save_history_based_model(struct starpu_perfmodel *model)
630 : : {
631 [ - + ]: 27 : STARPU_ASSERT(model);
632 [ - + ]: 27 : STARPU_ASSERT(model->symbol);
633 : :
634 : : /* TODO checks */
635 : :
636 : : /* filename = $STARPU_PERF_MODEL_DIR/codelets/symbol.hostname */
637 : : char path[256];
638 : 27 : get_model_path(model, path, 256);
639 : :
640 [ + - ]: 27 : _STARPU_DEBUG("Opening performance model file %s for model %s\n", path, model->symbol);
641 : :
642 : : /* overwrite existing file, or create it */
643 : : FILE *f;
644 : 27 : f = fopen(path, "w+");
645 [ - + ]: 27 : STARPU_ASSERT(f);
646 : :
647 : 27 : dump_model_file(f, model);
648 : :
649 : 27 : fclose(f);
650 : 27 : }
651 : :
652 : 8 : static void _starpu_dump_registered_models(void)
653 : : {
654 [ - + ]: 8 : _STARPU_PTHREAD_RWLOCK_WRLOCK(®istered_models_rwlock);
655 : :
656 : : struct starpu_model_list *node;
657 : 8 : node = registered_models;
658 : :
659 [ + - ]: 8 : _STARPU_DEBUG("DUMP MODELS !\n");
660 : :
661 [ + + ]: 35 : while (node)
662 : : {
663 : 27 : save_history_based_model(node->model);
664 : 27 : node = node->next;
665 : : }
666 : :
667 [ - + ]: 8 : _STARPU_PTHREAD_RWLOCK_UNLOCK(®istered_models_rwlock);
668 : 8 : }
669 : :
670 : 225 : void _starpu_initialize_registered_performance_models(void)
671 : : {
672 : 225 : registered_models = NULL;
673 : :
674 [ - + ]: 225 : _STARPU_PTHREAD_RWLOCK_INIT(®istered_models_rwlock, NULL);
675 : 225 : }
676 : :
677 : 225 : void _starpu_deinitialize_registered_performance_models(void)
678 : : {
679 [ + + ]: 225 : if (_starpu_get_calibrate_flag())
680 : 8 : _starpu_dump_registered_models();
681 : :
682 [ - + ]: 225 : _STARPU_PTHREAD_RWLOCK_WRLOCK(®istered_models_rwlock);
683 : :
684 : : struct starpu_model_list *node, *pnode;
685 : 225 : node = registered_models;
686 : :
687 [ + - ]: 225 : _STARPU_DEBUG("FREE MODELS !\n");
688 : :
689 [ + + ]: 397 : while (node)
690 : : {
691 : 172 : struct starpu_perfmodel *model = node->model;
692 : : unsigned arch;
693 : : unsigned nimpl;
694 : :
695 [ - + ]: 172 : _STARPU_PTHREAD_RWLOCK_WRLOCK(&model->model_rwlock);
696 [ + + ]: 13416 : for (arch = 0; arch < STARPU_NARCH_VARIATIONS; arch++)
697 : : {
698 [ + + ]: 66220 : for (nimpl = 0; nimpl < STARPU_MAXIMPLEMENTATIONS; nimpl++)
699 : : {
700 : 52976 : struct starpu_per_arch_perfmodel *archmodel = &model->per_arch[arch][nimpl];
701 : : struct starpu_history_list *list, *plist;
702 : 52976 : _starpu_htbl_destroy_32(archmodel->history, NULL);
703 : 52976 : archmodel->history = NULL;
704 : 52976 : list = archmodel->list;
705 [ + + ]: 53681 : while (list) {
706 : 705 : free(list->entry);
707 : 705 : plist = list;
708 : 705 : list = list->next;
709 : 705 : free(plist);
710 : : }
711 : 52976 : archmodel->list = NULL;
712 : : }
713 : : }
714 : :
715 : 172 : model->is_loaded = 0;
716 [ - + ]: 172 : _STARPU_PTHREAD_RWLOCK_UNLOCK(&model->model_rwlock);
717 : :
718 : 172 : pnode = node;
719 : 172 : node = node->next;
720 : 172 : free(pnode);
721 : : }
722 : 225 : registered_models = NULL;
723 : :
724 [ - + ]: 225 : _STARPU_PTHREAD_RWLOCK_UNLOCK(®istered_models_rwlock);
725 [ - + ]: 225 : _STARPU_PTHREAD_RWLOCK_DESTROY(®istered_models_rwlock);
726 : 225 : }
727 : :
728 : : /* We first try to grab the global lock in read mode to check whether the model
729 : : * was loaded or not (this is very likely to have been already loaded). If the
730 : : * model was not loaded yet, we take the lock in write mode, and if the model
731 : : * is still not loaded once we have the lock, we do load it. */
732 : 172 : void _starpu_load_history_based_model(struct starpu_perfmodel *model, unsigned scan_history)
733 : : {
734 [ - + ]: 172 : STARPU_ASSERT(model);
735 [ - + ]: 172 : STARPU_ASSERT(model->symbol);
736 : :
737 : : int already_loaded;
738 : :
739 [ - + ]: 172 : _STARPU_PTHREAD_RWLOCK_RDLOCK(®istered_models_rwlock);
740 : 172 : already_loaded = model->is_loaded;
741 [ - + ]: 172 : _STARPU_PTHREAD_RWLOCK_UNLOCK(®istered_models_rwlock);
742 : :
743 [ - + ]: 172 : if (already_loaded)
744 : 0 : return;
745 : :
746 : : /* The model is still not loaded so we grab the lock in write mode, and
747 : : * if it's not loaded once we have the lock, we do load it. */
748 : :
749 [ - + ]: 172 : _STARPU_PTHREAD_RWLOCK_WRLOCK(®istered_models_rwlock);
750 : :
751 : : /* Was the model initialized since the previous test ? */
752 [ - + ]: 172 : if (model->is_loaded)
753 : : {
754 [ # # ]: 0 : _STARPU_PTHREAD_RWLOCK_UNLOCK(®istered_models_rwlock);
755 : 0 : return;
756 : : }
757 : :
758 [ - + ]: 172 : _STARPU_PTHREAD_RWLOCK_INIT(&model->model_rwlock, NULL);
759 : :
760 [ - + ]: 172 : _STARPU_PTHREAD_RWLOCK_WRLOCK(&model->model_rwlock);
761 : :
762 : : /* make sure the performance model directory exists (or create it) */
763 : 172 : _starpu_create_sampling_directory_if_needed();
764 : :
765 : : char path[256];
766 : 172 : get_model_path(model, path, 256);
767 : :
768 [ + - ]: 172 : _STARPU_DEBUG("Opening performance model file %s for model %s ...\n", path, model->symbol);
769 : :
770 : 172 : unsigned calibrate_flag = _starpu_get_calibrate_flag();
771 : 172 : model->benchmarking = calibrate_flag;
772 : :
773 : : /* try to open an existing file and load it */
774 : : int res;
775 : 172 : res = access(path, F_OK);
776 [ + - ]: 172 : if (res == 0)
777 : : {
778 [ + + ]: 172 : if (calibrate_flag == 2)
779 : : {
780 : : /* The user specified that the performance model should
781 : : * be overwritten, so we don't load the existing file !
782 : : * */
783 [ + - ]: 3 : _STARPU_DEBUG("Overwrite existing file\n");
784 : 3 : initialize_model(model);
785 : : }
786 : : else
787 : : {
788 : : /* We load the available file */
789 [ + - ]: 169 : _STARPU_DEBUG("File exists\n");
790 : : FILE *f;
791 : 169 : f = fopen(path, "r");
792 [ - + ]: 169 : STARPU_ASSERT(f);
793 : :
794 : 169 : parse_model_file(f, model, scan_history);
795 : :
796 : 169 : fclose(f);
797 : : }
798 : : }
799 : : else
800 : : {
801 [ # # ]: 0 : _STARPU_DEBUG("File does not exists\n");
802 [ # # ]: 0 : if (!calibrate_flag)
803 : : {
804 : 0 : _STARPU_DISP("Warning: model %s is not calibrated, forcing calibration for this run. Use the STARPU_CALIBRATE environment variable to control this.\n", model->symbol);
805 : 0 : _starpu_set_calibrate_flag(1);
806 : 0 : model->benchmarking = 1;
807 : : }
808 : 0 : initialize_model(model);
809 : : }
810 : :
811 [ + - ]: 172 : _STARPU_DEBUG("Performance model file %s for model %s is loaded\n", path, model->symbol);
812 : :
813 : 172 : model->is_loaded = 1;
814 : :
815 [ - + ]: 172 : _STARPU_PTHREAD_RWLOCK_UNLOCK(&model->model_rwlock);
816 : :
817 [ - + ]: 172 : _STARPU_PTHREAD_RWLOCK_UNLOCK(®istered_models_rwlock);
818 : : }
819 : :
820 : : /* This function is intended to be used by external tools that should read
821 : : * the performance model files */
822 : 0 : int starpu_list_models(FILE *output)
823 : : {
824 : : char path[256];
825 : : DIR *dp;
826 : : struct dirent *ep;
827 : :
828 : : char perf_model_dir_codelets[256];
829 : 0 : _starpu_get_perf_model_dir_codelets(perf_model_dir_codelets, 256);
830 : :
831 : 0 : strncpy(path, perf_model_dir_codelets, 256);
832 : 0 : dp = opendir(path);
833 [ # # ]: 0 : if (dp != NULL)
834 : : {
835 [ # # ]: 0 : while ((ep = readdir(dp)))
836 : : {
837 [ # # ][ # # ]: 0 : if (strcmp(ep->d_name, ".") && strcmp(ep->d_name, ".."))
838 : 0 : fprintf(output, "file: <%s>\n", ep->d_name);
839 : : }
840 : 0 : closedir (dp);
841 : 0 : return 0;
842 : : }
843 : : else
844 : : {
845 : 0 : perror("Couldn't open the directory");
846 : 0 : return 1;
847 : : }
848 : : }
849 : :
850 : : /* This function is intended to be used by external tools that should read the
851 : : * performance model files */
852 : 0 : int starpu_load_history_debug(const char *symbol, struct starpu_perfmodel *model)
853 : : {
854 : 0 : model->symbol = strdup(symbol);
855 : :
856 : : /* where is the file if it exists ? */
857 : : char path[256];
858 : 0 : get_model_path(model, path, 256);
859 : :
860 : : // _STARPU_DEBUG("get_model_path -> %s\n", path);
861 : :
862 : : /* does it exist ? */
863 : : int res;
864 : 0 : res = access(path, F_OK);
865 [ # # ]: 0 : if (res)
866 : : {
867 : 0 : const char *dot = strrchr(symbol, '.');
868 [ # # ]: 0 : if (dot)
869 : : {
870 : 0 : char *symbol2 = strdup(symbol);
871 : 0 : symbol2[dot-symbol] = '\0';
872 : : int ret;
873 : 0 : fprintf(stderr,"note: loading history from %s instead of %s\n", symbol2, symbol);
874 : 0 : ret = starpu_load_history_debug(symbol2,model);
875 : 0 : free(symbol2);
876 : 0 : return ret;
877 : : }
878 : 0 : _STARPU_DISP("There is no performance model for symbol %s\n", symbol);
879 : 0 : return 1;
880 : : }
881 : :
882 : 0 : FILE *f = fopen(path, "r");
883 [ # # ]: 0 : STARPU_ASSERT(f);
884 : :
885 : 0 : parse_model_file(f, model, 1);
886 : :
887 [ # # ]: 0 : STARPU_ASSERT(fclose(f) == 0);
888 : :
889 : 0 : return 0;
890 : : }
891 : :
892 : 100 : void starpu_perfmodel_get_arch_name(enum starpu_perf_archtype arch, char *archname, size_t maxlen,unsigned nimpl)
893 : : {
894 [ + + ]: 100 : if (arch < STARPU_CUDA_DEFAULT)
895 : : {
896 [ + + ]: 19 : if (arch == STARPU_CPU_DEFAULT)
897 : : {
898 : : /* NB: We could just use cpu_1 as well ... */
899 : 15 : snprintf(archname, maxlen, "cpu_impl_%u",nimpl);
900 : : }
901 : : else
902 : : {
903 : : /* For combined CPU workers */
904 : 4 : int cpu_count = arch - STARPU_CPU_DEFAULT + 1;
905 : 4 : snprintf(archname, maxlen, "cpu_%d_impl_%u", cpu_count,nimpl);
906 : : }
907 : : }
908 [ + - ]: 81 : else if ((STARPU_CUDA_DEFAULT <= arch)
909 [ + - ]: 81 : && (arch < STARPU_CUDA_DEFAULT + STARPU_MAXCUDADEVS))
910 : 81 : {
911 : 81 : int devid = arch - STARPU_CUDA_DEFAULT;
912 : 81 : snprintf(archname, maxlen, "cuda_%d_impl_%u", devid,nimpl);
913 : : }
914 [ # # ]: 0 : else if ((STARPU_OPENCL_DEFAULT <= arch)
915 [ # # ]: 0 : && (arch < STARPU_OPENCL_DEFAULT + STARPU_MAXOPENCLDEVS))
916 : 0 : {
917 : 0 : int devid = arch - STARPU_OPENCL_DEFAULT;
918 : 0 : snprintf(archname, maxlen, "opencl_%d_impl_%u", devid,nimpl);
919 : : }
920 [ # # ]: 0 : else if (arch == STARPU_GORDON_DEFAULT)
921 : : {
922 : 0 : snprintf(archname, maxlen, "gordon_impl_%u",nimpl);
923 : : }
924 : : else
925 : : {
926 : 0 : STARPU_ABORT();
927 : : }
928 : 100 : }
929 : :
930 : 0 : void starpu_perfmodel_debugfilepath(struct starpu_perfmodel *model,
931 : : enum starpu_perf_archtype arch, char *path, size_t maxlen, unsigned nimpl)
932 : : {
933 : : char archname[32];
934 : 0 : starpu_perfmodel_get_arch_name(arch, archname, 32, nimpl);
935 : :
936 [ # # ]: 0 : STARPU_ASSERT(path);
937 : :
938 : 0 : get_model_debug_path(model, archname, path, maxlen);
939 : 0 : }
940 : :
941 : 32 : double _starpu_regression_based_job_expected_perf(struct starpu_perfmodel *model, enum starpu_perf_archtype arch, struct _starpu_job *j, unsigned nimpl)
942 : : {
943 : 32 : double exp = NAN;
944 : 32 : size_t size = _starpu_job_get_data_size(model, arch, nimpl, j);
945 : : struct starpu_regression_model *regmodel;
946 : :
947 : 32 : regmodel = &model->per_arch[arch][nimpl].regression;
948 : :
949 [ + + ]: 32 : if (regmodel->valid)
950 : 8 : exp = regmodel->alpha*pow((double)size, regmodel->beta);
951 : :
952 : 32 : return exp;
953 : : }
954 : :
955 : 32 : double _starpu_non_linear_regression_based_job_expected_perf(struct starpu_perfmodel *model, enum starpu_perf_archtype arch, struct _starpu_job *j,unsigned nimpl)
956 : : {
957 : 32 : double exp = NAN;
958 : 32 : size_t size = _starpu_job_get_data_size(model, arch, nimpl, j);
959 : : struct starpu_regression_model *regmodel;
960 : :
961 : 32 : regmodel = &model->per_arch[arch][nimpl].regression;
962 : :
963 [ - + ][ # # ]: 32 : if (regmodel->nl_valid && size >= regmodel->minx * 0.9 && size <= regmodel->maxx * 1.1)
[ # # ]
964 : 0 : exp = regmodel->a*pow((double)size, regmodel->b) + regmodel->c;
965 : : else
966 : : {
967 : 32 : uint32_t key = _starpu_compute_buffers_footprint(model, arch, nimpl, j);
968 : 32 : struct starpu_per_arch_perfmodel *per_arch_model = &model->per_arch[arch][nimpl];
969 : : struct starpu_htbl32_node *history;
970 : : struct starpu_history_entry *entry;
971 : :
972 [ - + ]: 32 : _STARPU_PTHREAD_RWLOCK_RDLOCK(&model->model_rwlock);
973 : 32 : history = per_arch_model->history;
974 : 32 : entry = (struct starpu_history_entry *) _starpu_htbl_search_32(history, key);
975 [ - + ]: 32 : _STARPU_PTHREAD_RWLOCK_UNLOCK(&model->model_rwlock);
976 : :
977 [ - + ][ # # ]: 32 : if (entry && entry->nsample >= _STARPU_CALIBRATION_MINIMUM)
978 : 0 : exp = entry->mean;
979 [ - + ]: 32 : else if (!model->benchmarking)
980 : : {
981 : 0 : _STARPU_DISP("Warning: model %s is not calibrated enough, forcing calibration for this run. Use the STARPU_CALIBRATE environment variable to control this.\n", model->symbol);
982 : 0 : _starpu_set_calibrate_flag(1);
983 : 0 : model->benchmarking = 1;
984 : : }
985 : : }
986 : :
987 : 32 : return exp;
988 : : }
989 : :
990 : 257789 : double _starpu_history_based_job_expected_perf(struct starpu_perfmodel *model, enum starpu_perf_archtype arch, struct _starpu_job *j,unsigned nimpl)
991 : : {
992 : : double exp;
993 : : struct starpu_per_arch_perfmodel *per_arch_model;
994 : : struct starpu_history_entry *entry;
995 : : struct starpu_htbl32_node *history;
996 : :
997 : 257789 : uint32_t key = _starpu_compute_buffers_footprint(model, arch, nimpl, j);
998 : :
999 : 257795 : per_arch_model = &model->per_arch[arch][nimpl];
1000 : :
1001 [ - + ]: 257795 : _STARPU_PTHREAD_RWLOCK_RDLOCK(&model->model_rwlock);
1002 : 257819 : history = per_arch_model->history;
1003 [ - + ]: 257819 : if (!history) {
1004 [ # # ]: 0 : _STARPU_PTHREAD_RWLOCK_UNLOCK(&model->model_rwlock);
1005 : 0 : return NAN;
1006 : : }
1007 : :
1008 : 257819 : entry = (struct starpu_history_entry *) _starpu_htbl_search_32(history, key);
1009 [ - + ]: 257807 : _STARPU_PTHREAD_RWLOCK_UNLOCK(&model->model_rwlock);
1010 : :
1011 [ + - ]: 257833 : exp = entry?entry->mean:NAN;
1012 : :
1013 [ + - ][ - + ]: 257833 : if (entry && entry->nsample < _STARPU_CALIBRATION_MINIMUM)
1014 : : /* TODO: report differently if we've scheduled really enough
1015 : : * of that task and the scheduler should perhaps put it aside */
1016 : : /* Not calibrated enough */
1017 : 0 : exp = NAN;
1018 : :
1019 [ - + ][ # # ]: 257833 : if (isnan(exp) && !model->benchmarking)
1020 : : {
1021 : 0 : _STARPU_DISP("Warning: model %s is not calibrated enough, forcing calibration for this run. Use the STARPU_CALIBRATE environment variable to control this.\n", model->symbol);
1022 : 0 : _starpu_set_calibrate_flag(1);
1023 : 0 : model->benchmarking = 1;
1024 : : }
1025 : :
1026 : 257833 : return exp;
1027 : : }
1028 : :
1029 : 29370 : void _starpu_update_perfmodel_history(struct _starpu_job *j, struct starpu_perfmodel *model, enum starpu_perf_archtype arch, unsigned cpuid STARPU_ATTRIBUTE_UNUSED, double measured, unsigned nimpl)
1030 : : {
1031 [ + - ]: 29370 : if (model)
1032 : : {
1033 [ - + ]: 29370 : _STARPU_PTHREAD_RWLOCK_WRLOCK(&model->model_rwlock);
1034 : :
1035 : 29372 : struct starpu_per_arch_perfmodel *per_arch_model = &model->per_arch[arch][nimpl];
1036 : :
1037 [ + + ][ + + ]: 29372 : if (model->type == STARPU_HISTORY_BASED || model->type == STARPU_NL_REGRESSION_BASED)
1038 : : {
1039 : : struct starpu_history_entry *entry;
1040 : : struct starpu_htbl32_node *history;
1041 : : struct starpu_htbl32_node **history_ptr;
1042 : : struct starpu_history_list **list;
1043 : 27972 : uint32_t key = _starpu_compute_buffers_footprint(model, arch, nimpl, j);
1044 : :
1045 : 27971 : history = per_arch_model->history;
1046 : 27971 : history_ptr = &per_arch_model->history;
1047 : 27971 : list = &per_arch_model->list;
1048 : :
1049 : 27971 : entry = (struct starpu_history_entry *) _starpu_htbl_search_32(history, key);
1050 : :
1051 [ + + ]: 27972 : if (!entry)
1052 : : {
1053 : : /* this is the first entry with such a footprint */
1054 : 124 : entry = (struct starpu_history_entry *) malloc(sizeof(struct starpu_history_entry));
1055 [ - + ]: 124 : STARPU_ASSERT(entry);
1056 : 124 : entry->mean = measured;
1057 : 124 : entry->sum = measured;
1058 : :
1059 : 124 : entry->deviation = 0.0;
1060 : 124 : entry->sum2 = measured*measured;
1061 : :
1062 : 124 : entry->size = _starpu_job_get_data_size(model, arch, nimpl, j);
1063 : :
1064 : 124 : entry->footprint = key;
1065 : 124 : entry->nsample = 1;
1066 : :
1067 : 124 : insert_history_entry(entry, list, history_ptr);
1068 : :
1069 : : }
1070 : : else
1071 : : {
1072 : : /* there is already some entry with the same footprint */
1073 : 27848 : entry->sum += measured;
1074 : 27848 : entry->sum2 += measured*measured;
1075 : 27848 : entry->nsample++;
1076 : :
1077 : 27848 : unsigned n = entry->nsample;
1078 : 27848 : entry->mean = entry->sum / n;
1079 : 27848 : entry->deviation = sqrt((entry->sum2 - (entry->sum*entry->sum)/n)/n);
1080 : : }
1081 : :
1082 [ - + ]: 27972 : STARPU_ASSERT(entry);
1083 : : }
1084 : :
1085 [ + + ][ + + ]: 29372 : if (model->type == STARPU_REGRESSION_BASED || model->type == STARPU_NL_REGRESSION_BASED)
1086 : : {
1087 : : struct starpu_regression_model *reg_model;
1088 : 6200 : reg_model = &per_arch_model->regression;
1089 : :
1090 : : /* update the regression model */
1091 : 6200 : size_t job_size = _starpu_job_get_data_size(model, arch, nimpl, j);
1092 : : double logy, logx;
1093 : 6200 : logx = log((double)job_size);
1094 : 6200 : logy = log(measured);
1095 : :
1096 : 6200 : reg_model->sumlnx += logx;
1097 : 6200 : reg_model->sumlnx2 += logx*logx;
1098 : 6200 : reg_model->sumlny += logy;
1099 : 6200 : reg_model->sumlnxlny += logx*logy;
1100 [ + + ][ - + ]: 6200 : if (reg_model->minx == 0 || job_size < reg_model->minx)
1101 : 12 : reg_model->minx = job_size;
1102 [ + + ][ + + ]: 6200 : if (reg_model->maxx == 0 || job_size > reg_model->maxx)
1103 : 180 : reg_model->maxx = job_size;
1104 : 6200 : reg_model->nsample++;
1105 : :
1106 : 6200 : unsigned n = reg_model->nsample;
1107 : :
1108 : 6200 : double num = (n*reg_model->sumlnxlny - reg_model->sumlnx*reg_model->sumlny);
1109 : 6200 : double denom = (n*reg_model->sumlnx2 - reg_model->sumlnx*reg_model->sumlnx);
1110 : :
1111 : 6200 : reg_model->beta = num/denom;
1112 : 6200 : reg_model->alpha = exp((reg_model->sumlny - reg_model->beta*reg_model->sumlnx)/n);
1113 : :
1114 [ + + ][ + - ]: 6200 : if (VALID_REGRESSION(reg_model))
1115 : 5800 : reg_model->valid = 1;
1116 : : }
1117 : :
1118 : : #ifdef STARPU_MODEL_DEBUG
1119 : : struct starpu_task *task = j->task;
1120 : : FILE *f = fopen(per_arch_model->debug_path, "a+");
1121 : : if (f == NULL)
1122 : : {
1123 : : _STARPU_DISP("Error <%s> when opening file <%s>\n", strerror(errno), per_arch_model->debug_path);
1124 : : STARPU_ASSERT(0);
1125 : : }
1126 : :
1127 : : if (!j->footprint_is_computed)
1128 : : (void) _starpu_compute_buffers_footprint(model, arch, nimpl, j);
1129 : :
1130 : : STARPU_ASSERT(j->footprint_is_computed);
1131 : :
1132 : : fprintf(f, "0x%x\t%lu\t%f\t%f\t%f\t%d\t\t", j->footprint, (unsigned long) _starpu_job_get_data_size(model, arch, nimpl, j), measured, task->predicted, task->predicted_transfer, cpuid);
1133 : : unsigned i;
1134 : :
1135 : : for (i = 0; i < task->cl->nbuffers; i++)
1136 : : {
1137 : : starpu_data_handle_t handle = task->handles[i];
1138 : :
1139 : : STARPU_ASSERT(handle->ops);
1140 : : STARPU_ASSERT(handle->ops->display);
1141 : : handle->ops->display(handle, f);
1142 : : }
1143 : : fprintf(f, "\n");
1144 : : fclose(f);
1145 : : #endif
1146 [ - + ]: 29372 : _STARPU_PTHREAD_RWLOCK_UNLOCK(&model->model_rwlock);
1147 : : }
1148 : 29369 : }
|