~ubuntu-branches/ubuntu/trusty/atlas/trusty

« back to all changes in this revision

Viewing changes to tune/blas/gemm/mmtime_pt.c

  • Committer: Package Import Robot
  • Author(s): Sébastien Villemot
  • Date: 2013-07-27 14:26:05 UTC
  • mfrom: (18.1.8 sid)
  • Revision ID: package-import@ubuntu.com-20130727142605-5rh3p972h1whdo99
Tags: 3.10.1-2
* Allow the generic package to build on machines with CPU throttling
  enabled. Otherwise the package FTBFS on some buildds (e.g. biber).
  Implementation is done by reactivating the "-Si cputhrchk 0" flag
  (cpu-throtthling-check.diff), and using it in debian/rules.
* Add architectural defaults for armel and mips.
* armhf.diff: do not enforce 32-registers FPU for Fortran

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include "atlas_ptmisc.h"
 
2
#include <string.h>
 
3
#define dumb_rand() ( 0.5 - ((double)rand())/((double)RAND_MAX) )
 
4
 
 
5
#ifndef KMM
 
6
   #define KMM ATL_USERMM
 
7
#endif
 
8
 
 
9
#define CINT const int
 
10
 
 
11
void KMM(const int, const int, const int, const SCALAR, const TYPE*,
 
12
         const int, const TYPE*, const int, const SCALAR, TYPE*, const int);
 
13
 
 
14
struct kmm_struct{
 
15
   int mb, nb, kb;                      /* C: mbxnb, At: kbxmb, B: kbXnb */
 
16
   int movA, movB, movC;                /* which mat move in flush array? */
 
17
   int FLSIZE;                          /* min area to move in in bytes */
 
18
   int reps;                            /* # calls to kmm in one timing */
 
19
   int LDC;                             /* what should ldc be set to? */
 
20
   int iam;                             /* thread rank */
 
21
   int p;                               /* total number of threads */
 
22
   double mf;                           /* mflop returned by timing */
 
23
};
 
24
 
 
25
double GetKmmMflop
 
26
(
 
27
   CINT mb, CINT nb, CINT kb,           /* C: mbxnb, At: kbxmb, B: kbXnb */
 
28
   CINT movA, CINT movB, CINT movC,     /* which mat move in flush array? */
 
29
   int FLSIZE,                          /* min area to move in in bytes */
 
30
   CINT reps,                           /* # calls to kmm in one timing */
 
31
   CINT LDC                             /* what should ldc be set to? */
 
32
)
 
33
/*
 
34
 * Returns MFLOP rate of matmul kernel KMM
 
35
 * LDC: if (LDC == 0), then set ldc=MB for timings.
 
36
 *      if (LDC != 0 && movC != 0), then ldc= col length in move space
 
37
 *      else ldc = LDC;
 
38
 *
 
39
 */
 
40
{
 
41
   const int NOMOVE = !(movA|movB|movC);
 
42
   int ldc, setsz, nset, i, j, incA, incB, incC, n, extra;
 
43
   TYPE *C, *A, *B, *a, *b, *c;
 
44
   double t0, t1, mf;
 
45
   const TYPE alpha=1.0;
 
46
   TYPE beta=1.0;
 
47
   void *vp=NULL;
 
48
 
 
49
   if (NOMOVE)
 
50
   {
 
51
      ldc = (LDC) ? LDC : mb;
 
52
      setsz = (ldc * nb + kb*(mb+nb));
 
53
      vp = malloc(ATL_Cachelen + ATL_MulBySize(setsz));
 
54
      ATL_assert(vp);
 
55
      A =  ATL_AlignPtr(vp);
 
56
      B = A + mb*kb;
 
57
      C = B + kb*nb;
 
58
      for (i=0; i < setsz; i++) A[i] = dumb_rand();
 
59
      incA = incB = incC = 0;
 
60
   }
 
61
   else
 
62
   {
 
63
      if (movA && movB && movC)         /* no reuse at all */
 
64
      {
 
65
         setsz = ATL_MulBySize(mb*nb+kb*(mb+nb));
 
66
         nset = (FLSIZE+setsz-1)/setsz;
 
67
         FLSIZE = nset*setsz;
 
68
         setsz = mb*nb+kb*(mb+nb);
 
69
         vp = malloc(ATL_Cachelen + ATL_MulBySize(setsz));
 
70
         ATL_assert(vp);
 
71
         A = ATL_AlignPtr(vp);
 
72
         B = A + kb*mb*nset;
 
73
         C = B + kb*nb*nset;
 
74
         ldc = (LDC) ? mb*nset : mb;
 
75
         for (n=setsz*nset,i=0; i < n; i++) A[i] = dumb_rand();
 
76
         incA = mb*kb;
 
77
         incB = kb*nb;
 
78
         incC = mb*nb;
 
79
      }
 
80
      else if (movA && movB && !movC)   /* square-case ATLAS behavior */
 
81
      {
 
82
         setsz = kb*(mb+nb);
 
83
         ldc = (LDC) ? LDC : mb;
 
84
         ATL_assert(ldc >= mb);
 
85
         extra = ldc*nb;
 
86
         incA = mb*kb;
 
87
         incB = kb*nb;
 
88
         incC = 0;
 
89
      }
 
90
      else if (!movB && movA && movC)   /* rank-K behavior */
 
91
      {
 
92
         setsz = mb*(kb+nb);
 
93
         extra = kb*nb;
 
94
         incA = mb*kb;
 
95
         incB = 0;
 
96
         incC = mb*nb;
 
97
      }
 
98
      else
 
99
      {
 
100
         fprintf(stderr, "%s,%d: What case are you wanting?\n",
 
101
                 __FILE__, __LINE__);
 
102
         exit(-1);
 
103
      }
 
104
      if (!vp)
 
105
      {
 
106
         i = ATL_MulBySize(setsz);
 
107
         nset = (FLSIZE+i-1)/i;
 
108
         FLSIZE = nset * i;
 
109
         vp = malloc(ATL_Cachelen + ATL_MulBySize(FLSIZE+extra));
 
110
         ATL_assert(vp);
 
111
         A = ATL_AlignPtr(vp);
 
112
         if (movC)
 
113
         {
 
114
            C = A + mb*kb*nset;
 
115
            ldc = (LDC) ? mb*nset : mb;
 
116
            B = C + mb*nb*nset;
 
117
         }
 
118
         else
 
119
         {
 
120
            B = A + mb*kb*nset;
 
121
            C = B + kb*nb*nset;
 
122
         }
 
123
         for (n=setsz*nset+extra,i=0; i < n; i++) A[i] = dumb_rand();
 
124
      }
 
125
   }
 
126
   a = A; b = B; c = C;
 
127
   t0 = ATL_walltime();
 
128
   for (j=0,i=reps; i; i--)
 
129
   {
 
130
      KMM(mb, nb, kb, alpha, a, kb, b, kb, beta, c, ldc);
 
131
      if (++j != nset)
 
132
      {
 
133
         a += incA;
 
134
         b += incB;
 
135
         c += incC;
 
136
      }
 
137
      else
 
138
      {
 
139
         beta = (beta != 0.0) ? -beta : 0.0;
 
140
         j = 0;
 
141
         a = A; b = B; c = C;
 
142
      }
 
143
   }
 
144
   t1 = ATL_walltime() - t0;
 
145
   mf = (2.0*reps*mb*nb*kb) / (t1*1000000.0);
 
146
   free(vp);
 
147
   return(mf);
 
148
}
 
149
 
 
150
void *TimeOnCore(void *vp)
 
151
{
 
152
   struct kmm_struct *kp = vp;
 
153
 
 
154
   kp->mf = GetKmmMflop(kp->mb, kp->nb, kp->kb, kp->movA, kp->movB, kp->movC,
 
155
                        kp->FLSIZE, kp->reps, kp->LDC);
 
156
   return(NULL);
 
157
}
 
158
 
 
159
double *TimeOnCores(struct kmm_struct *kb)
 
160
{
 
161
   struct kmm_struct *kp;
 
162
   pthread_t *threads;
 
163
   pthread_attr_t *attr;
 
164
   unsigned long cpuset;
 
165
   double *mflops;
 
166
   int i, p;
 
167
 
 
168
   p = kb->p;
 
169
   kp = malloc(sizeof(struct kmm_struct)*p);
 
170
   threads = malloc(sizeof(pthread_t)*p);
 
171
   attr = malloc(sizeof(pthread_attr_t)*p);
 
172
   mflops = malloc(sizeof(double)*p);
 
173
   ATL_assert(kp && threads && attr && mflops);
 
174
   for (i=0; i < p; i++)
 
175
   {
 
176
      memcpy(kp+i, kb, sizeof(struct kmm_struct));
 
177
      kp[i].iam = i;
 
178
      cpuset = (1<<i);
 
179
      pthread_attr_setaffinity_np(attr+i, sizeof(cpuset), &cpuset);
 
180
      pthread_create(threads+i, attr+i, TimeOnCore, kp+i);
 
181
   }
 
182
   for (i=0; i < p; i++)
 
183
   {
 
184
      pthread_join(threads[i], NULL);
 
185
      mflops[i] = kp[i].mf;
 
186
   }
 
187
   free(kp);
 
188
   free(threads);
 
189
   free(attr);
 
190
   return(mflops);
 
191
}
 
192
 
 
193
void GetStat(int n, double *d, double *min, double *max, double *avg)
 
194
{
 
195
   int i;
 
196
   double dmin, dmax, dsum;
 
197
 
 
198
   dmin = dmax = dsum = d[0];
 
199
   for (i=1; i < n; i++)
 
200
   {
 
201
      dmax = (dmax >= d[i]) ? dmax : d[i];
 
202
      dmin = (dmin <= d[i]) ? dmin : d[i];
 
203
      dsum += d[i];
 
204
   }
 
205
   *min = dmin;
 
206
   *max = dmax;
 
207
   *avg = dsum / (double)n;
 
208
}
 
209
 
 
210
void PrintUsage(char *name, int iarg, char *arg)
 
211
{
 
212
   fprintf(stderr, "\nERROR around arg %d (%s).\n", iarg, arg ? arg:"unknown");
 
213
   fprintf(stderr, "USAGE: %s [flags], where flags are:\n", name);
 
214
   fprintf(stderr, "   -B <#> : mb = nb = kb = #\n");
 
215
   fprintf(stderr, "   -m <#> : mb = #\n");
 
216
   fprintf(stderr, "   -n <#> : nb = #\n");
 
217
   fprintf(stderr, "   -k <#> : kb = #\n");
 
218
   fprintf(stderr, "   -r <#> : set the # of times to call KMM\n");
 
219
   fprintf(stderr, "   -F <kb> : set flush size in kilobytes\n");
 
220
   fprintf(stderr, "   -C <#> : set ldc; 0 means mb\n");
 
221
   fprintf(stderr, "   -M[a,b,c] <#> : mov[A,B,C] = #\n");
 
222
   exit(iarg ? iarg : -1);
 
223
}
 
224
 
 
225
struct kmm_struct *GetFlags(int nargs, char **args)
 
226
{
 
227
   struct kmm_struct *kp;
 
228
   int i;
 
229
 
 
230
   kp = malloc(sizeof(struct kmm_struct));
 
231
   ATL_assert(kp);
 
232
   kp->p = 1;
 
233
   kp->mb = kp->nb = kp->kb = 40;
 
234
   kp->movA = kp->movB = kp->movC = 0;
 
235
   kp->FLSIZE = L2SIZE;
 
236
   kp->reps = 200;
 
237
   kp->LDC = 0;
 
238
   for (i=1; i < nargs; i++)
 
239
   {
 
240
      if (args[i][0] != '-')
 
241
         PrintUsage(args[0], i, args[i]);
 
242
      switch(args[i][1])
 
243
      {
 
244
      case 'F':
 
245
         if (++i >= nargs)
 
246
            PrintUsage(args[0], i, "out of arguments");
 
247
         kp->FLSIZE = atoi(args[i]) * 1024;
 
248
         break;
 
249
      case 'C':
 
250
         if (++i >= nargs)
 
251
            PrintUsage(args[0], i, "out of arguments");
 
252
         kp->LDC = atoi(args[i]);
 
253
         break;
 
254
      case 'r':
 
255
         if (++i >= nargs)
 
256
            PrintUsage(args[0], i, "out of arguments");
 
257
         kp->reps = atoi(args[i]);
 
258
         break;
 
259
      case 'p':
 
260
         if (++i >= nargs)
 
261
            PrintUsage(args[0], i, "out of arguments");
 
262
         kp->p = atoi(args[i]);
 
263
         break;
 
264
      case 'm':
 
265
         if (++i >= nargs)
 
266
            PrintUsage(args[0], i, "out of arguments");
 
267
         kp->mb = atoi(args[i]);
 
268
         break;
 
269
      case 'n':
 
270
         if (++i >= nargs)
 
271
            PrintUsage(args[0], i, "out of arguments");
 
272
         kp->nb = atoi(args[i]);
 
273
         break;
 
274
      case 'k':
 
275
         if (++i >= nargs)
 
276
            PrintUsage(args[0], i, "out of arguments");
 
277
         kp->kb = atoi(args[i]);
 
278
         break;
 
279
      case 'B':
 
280
         if (++i >= nargs)
 
281
            PrintUsage(args[0], i, "out of arguments");
 
282
         kp->mb = kp->nb = kp->kb = atoi(args[i]);
 
283
         break;
 
284
      case 'M':
 
285
         if (++i >= nargs)
 
286
            PrintUsage(args[0], i, "out of arguments");
 
287
         switch(args[i-1][2])
 
288
         {
 
289
         case 'c':
 
290
         case 'C':
 
291
            kp->movC = atoi(args[i]);
 
292
            break;
 
293
         case 'b':
 
294
         case 'B':
 
295
            kp->movB = atoi(args[i]);
 
296
            break;
 
297
         case 'a':
 
298
         case 'A':
 
299
            kp->movA = atoi(args[i]);
 
300
            break;
 
301
         default:
 
302
            PrintUsage(args[0], i-1, "unknown mov matrix");
 
303
         }
 
304
         break;
 
305
      default:
 
306
         PrintUsage(args[0], i, args[i]);
 
307
      }
 
308
   }
 
309
   return(kp);
 
310
}
 
311
 
 
312
int main(int nargs, char **args)
 
313
{
 
314
   struct kmm_struct *kp;
 
315
   int i, p;
 
316
   double *dp;
 
317
   double min, max, avg;
 
318
   FILE *fpout = stdout;
 
319
 
 
320
   kp = GetFlags(nargs, args);
 
321
   p = kp->p;
 
322
   dp = TimeOnCores(kp);
 
323
   free(kp);
 
324
   GetStat(p, dp, &min, &max, &avg);
 
325
   fprintf(fpout, "ALL CORES: min=%le, max=%le, avg=%le\n", min, max, avg);
 
326
   fprintf(fpout, "PER-CORE: %le", dp[0]);
 
327
   for (i=1; i < p; i++)
 
328
      fprintf(fpout, ", %le", dp[i]);
 
329
   fprintf(fpout, "\n\n%.2f\n", avg);
 
330
   free(dp);
 
331
   exit(0);
 
332
}