LCOV - code coverage report
Current view: top level - src/core/perfmodel - perfmodel_history.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 430 534 80.5 %
Date: 2012-04-13 Functions: 25 29 86.2 %
Branches: 210 387 54.3 %

           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                 :            :                 &reg_model->sumlnx, &reg_model->sumlnx2, &reg_model->sumlny,
     114                 :            :                 &reg_model->sumlnxlny, &reg_model->alpha, &reg_model->beta,
     115                 :            :                 &reg_model->nsample,
     116                 :            :                 &reg_model->minx, &reg_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", &reg_model->a, &reg_model->b, &reg_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(&registered_models_rwlock);
     569         [ +  + ]:        176 :         if (model->is_loaded)
     570                 :            :         {
     571         [ -  + ]:          4 :                 _STARPU_PTHREAD_RWLOCK_UNLOCK(&registered_models_rwlock);
     572                 :          4 :                 return 0;
     573                 :            :         }
     574         [ -  + ]:        172 :         _STARPU_PTHREAD_RWLOCK_UNLOCK(&registered_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(&registered_models_rwlock);
     579         [ -  + ]:        172 :         if (model->is_loaded)
     580                 :            :         {
     581         [ #  # ]:          0 :                 _STARPU_PTHREAD_RWLOCK_UNLOCK(&registered_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(&registered_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(&registered_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(&registered_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(&registered_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(&registered_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(&registered_models_rwlock);
     725         [ -  + ]:        225 :         _STARPU_PTHREAD_RWLOCK_DESTROY(&registered_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(&registered_models_rwlock);
     740                 :        172 :         already_loaded = model->is_loaded;
     741         [ -  + ]:        172 :         _STARPU_PTHREAD_RWLOCK_UNLOCK(&registered_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(&registered_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(&registered_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(&registered_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 : }

Generated by: LCOV version 1.9