~ubuntu-branches/ubuntu/vivid/atlas/vivid

« back to all changes in this revision

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

  • Committer: Bazaar Package Importer
  • Author(s): Camm Maguire
  • Date: 2002-04-13 10:07:52 UTC
  • Revision ID: james.westby@ubuntu.com-20020413100752-va9zm0rd4gpurdkq
Tags: upstream-3.2.1ln
ImportĀ upstreamĀ versionĀ 3.2.1ln

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *             Automatically Tuned Linear Algebra Software v3.2
 
3
 *                    (C) Copyright 1997 R. Clint Whaley                     
 
4
 *
 
5
 * Redistribution and use in source and binary forms, with or without
 
6
 * modification, are permitted provided that the following conditions
 
7
 * are met:
 
8
 *   1. Redistributions of source code must retain the above copyright
 
9
 *      notice, this list of conditions and the following disclaimer.
 
10
 *   2. Redistributions in binary form must reproduce the above copyright
 
11
 *      notice, this list of conditions, and the following disclaimer in the
 
12
 *      documentation and/or other materials provided with the distribution.
 
13
 *   3. The name of the University of Tennessee, the ATLAS group,
 
14
 *      or the names of its contributers may not be used to endorse
 
15
 *      or promote products derived from this software without specific
 
16
 *      written permission.
 
17
 *
 
18
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
 
19
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 
20
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 
21
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE
 
22
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 
23
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 
24
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 
25
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 
26
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 
27
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 
28
 * POSSIBILITY OF SUCH DAMAGE. 
 
29
 *
 
30
 */
 
31
 
 
32
#include <stdio.h>
 
33
#include <stdlib.h>
 
34
#include <assert.h>
 
35
#include <string.h>
 
36
#include "atlas_misc.h"
 
37
#include "atlas_fopen.h"
 
38
 
 
39
#define Mmin(x, y) ( (x) > (y) ? (y) : (x) )
 
40
 
 
41
#define TOLERANCE 1.2
 
42
#define REPS 4096
 
43
#define L1FNAME "L1CacheSize"
 
44
#define NTIM 3
 
45
#define MAXLAT 6
 
46
 
 
47
char LANG;
 
48
 
 
49
void PrintUsage(char *xnam)
 
50
{
 
51
   fprintf(stderr, "\n\nUsage: %s [-r #][-h][-f][-l #][-p s/d/c/z][-m #]\n",
 
52
           xnam);
 
53
   fprintf(stderr, "-h         : Print this help screen\n");
 
54
   fprintf(stderr, "-f         : Force complete search over given parameters\n");
 
55
   fprintf(stderr, "-p s/d/c/z : set the precision to search for\n");
 
56
   fprintf(stderr, "-r #       : Set max number of registers to use to # (default 32)\n");
 
57
   fprintf(stderr, "-m #       : Set max L1 cache size (kilobytes) to #\n");
 
58
   fprintf(stderr, "-L <c/f>   : Select what language to use (C or Fortran77)\n");
 
59
   fprintf(stderr, "-K #       : Set K-loop unrolling to # (-1 = K).\n");
 
60
   fprintf(stderr, "-l #       : Use latency factor #.  If set to 0,\n");
 
61
   fprintf(stderr, 
 
62
"             do not do latency checking.  By default, latency checking is\n");
 
63
   fprintf(stderr, 
 
64
"             done only if initial timings show it is a win.\n");
 
65
   exit(-1);
 
66
}
 
67
 
 
68
void GetSettings(int nargs, char *args[], char *pre, char *lang, int *ku, 
 
69
                 int *LAT, int *FRC, int *nreg, int *MaxL1Size, int *ROUT)
 
70
{
 
71
   int i;
 
72
 
 
73
   *FRC = 0;
 
74
   *LAT = -1;
 
75
   *nreg = -1;
 
76
   *MaxL1Size = 64;
 
77
   *pre = 'd';
 
78
   *lang = 'C';
 
79
   *ku = 0;
 
80
   *ROUT = 0;
 
81
   for (i=1; i < nargs; i++)
 
82
   {
 
83
      if (*args[i] != '-') PrintUsage(args[0]);
 
84
      switch(args[i][1])
 
85
      {
 
86
      case 'K':
 
87
         *ku = atoi(args[++i]);
 
88
         break;
 
89
      case 'L':
 
90
         i++;
 
91
         if ( (*args[i] == 'F') || (*args[i] == 'f') ) *lang = 'F';
 
92
         break;
 
93
      case 'm' :
 
94
         *MaxL1Size = atoi(args[++i]);
 
95
         break;
 
96
      case 'r' :
 
97
         *nreg = atoi(args[++i]);
 
98
         break;
 
99
      case 'f' :
 
100
         *FRC = atoi(args[++i]);
 
101
         break;
 
102
      case 'l' :
 
103
         *LAT = atoi(args[++i]);
 
104
         break;
 
105
      case 'p' :
 
106
         *pre = *args[++i];
 
107
         break;
 
108
      default:
 
109
      case 'R':
 
110
         *ROUT = atoi(args[++i]);
 
111
         break;
 
112
      case 'h' :
 
113
         PrintUsage(args[0]);
 
114
      }
 
115
   }
 
116
}
 
117
 
 
118
int L1Elts(char pre, int MaxL1Size)
 
119
{
 
120
   FILE *L1f;
 
121
   int L1Size, tsize;
 
122
   char ln[128];
 
123
 
 
124
   if (!FileExists("res/L1CacheSize"))
 
125
   {
 
126
      sprintf(ln, "make RunL1 MaxL1=%d\n",MaxL1Size);
 
127
      if (system(ln) != 0)
 
128
      {
 
129
         remove("res/L1CacheSize");
 
130
         fprintf(stderr, "Error in command: %s", ln);
 
131
         exit(-1);
 
132
      }
 
133
   }
 
134
   L1f = fopen("res/L1CacheSize", "r");
 
135
   assert(L1f != NULL);
 
136
   fscanf(L1f, "%d", &L1Size);
 
137
   fclose(L1f);
 
138
   switch (pre)
 
139
   {
 
140
      case 's':
 
141
         tsize = sizeof(float);
 
142
         break;
 
143
      case 'd':
 
144
         tsize = sizeof(double);
 
145
         break;
 
146
      case 'q':
 
147
         tsize = sizeof(long double);
 
148
         break;
 
149
      case 'c':
 
150
         tsize = sizeof(float);
 
151
         break;
 
152
      case 'z':
 
153
         tsize = sizeof(double);
 
154
         break;
 
155
   }
 
156
   return( (L1Size*1024) / tsize);
 
157
}
 
158
 
 
159
int GetCacheSize(int MaxL1Size)
 
160
/*
 
161
 * Returns L1 size in kilobytes
 
162
 */
 
163
{
 
164
   FILE *L1f;
 
165
   int L1Size;
 
166
   char ln[32];
 
167
 
 
168
   if (!FileExists("res/L1CacheSize"))
 
169
   {
 
170
      sprintf(ln, "make RunL1 MaxL1=%d\n",MaxL1Size);
 
171
      if (system(ln) != 0)
 
172
      {
 
173
         remove("res/L1CacheSize");
 
174
         fprintf(stderr, "Error in command: %s", ln);
 
175
         exit(-1);
 
176
      }
 
177
   }
 
178
   L1f = fopen("res/L1CacheSize", "r");
 
179
   assert(L1f != NULL);
 
180
   fscanf(L1f, "%d", &L1Size);
 
181
   fclose(L1f);
 
182
   fprintf(stderr, "\n      Read in L1 Cache size as = %dKB.\n",L1Size);
 
183
   return(L1Size);
 
184
}
 
185
 
 
186
int GetTypeSize(char pre)
 
187
{
 
188
   int tsize;
 
189
   if (pre == 'c' || pre == 's') tsize = ATL_ssize;
 
190
   else tsize = ATL_dsize;
 
191
   return(tsize);
 
192
}
 
193
void findNBs(char prec, char *NBnam, int MaxL1Size)
 
194
{
 
195
   FILE *NBf;
 
196
   char ln[80];
 
197
   int i, L1Size, tmp, tsize, tL1Size, CL, nNB;
 
198
   int NB[100];
 
199
 
 
200
   fprintf(stderr, "NB setting not supplied; calculating:\n");
 
201
 
 
202
   L1Size = GetCacheSize(MaxL1Size);
 
203
   tsize = GetTypeSize(prec);
 
204
 
 
205
   tL1Size = L1Size * (1024 / tsize);
 
206
   tmp = CL = ATL_Cachelen / tsize;
 
207
   if (!tmp) tmp=1;
 
208
   nNB = 0;
 
209
   fprintf(stderr, "tmp=%d, tL1size=%d\n",tmp, tL1Size);
 
210
   while (tmp*tmp <= tL1Size)
 
211
   {
 
212
      if (tmp >= 16)        /* no block sizes smaller than 16 */
 
213
         NB[nNB++] = tmp;
 
214
      if (tmp >= 80) break;  /* no block sizes bigger than 80 */
 
215
      tmp += CL;
 
216
   }
 
217
   if (!nNB)  /* this should never happen */
 
218
   {
 
219
      nNB = 3;
 
220
      NB[0] = 8;
 
221
      NB[1] = 4;
 
222
      NB[2] = 16;
 
223
   }
 
224
   else if (nNB > 2)  /* put second biggest blocking factor first in list */
 
225
   {
 
226
      tmp = NB[nNB-2];
 
227
      NB[nNB-2] = NB[0];
 
228
      NB[0] = tmp;
 
229
   }
 
230
 
 
231
   NBf = fopen(NBnam, "w");
 
232
   fprintf(NBf, "%d\n", nNB);
 
233
   for (i=0; i != nNB; i++) fprintf(NBf, "%d\n", NB[i]);
 
234
   fclose(NBf);
 
235
}
 
236
 
 
237
int GetSafeNB(char pre, int MaxL1)
 
238
{
 
239
   int i, L1, tsize, inc;
 
240
 
 
241
   tsize = GetTypeSize(pre);
 
242
   inc = ATL_MinMMAlign / tsize;
 
243
   if (inc < 4) inc = 4;
 
244
   L1 = (GetCacheSize(MaxL1) * 1024) / tsize;
 
245
   for (i=inc; i*i < L1; i += inc);
 
246
   if (i*i > L1) i -= inc;
 
247
   if (pre == 'd' || pre == 's')
 
248
   {
 
249
      if (i*i == L1) i -= inc;
 
250
   }
 
251
   else
 
252
   {
 
253
      if (i*i == L1) i -= 2*inc;
 
254
      else i -= inc;
 
255
   }
 
256
   if (i < 16) i = 16;
 
257
   if (i > 80) i = 80;
 
258
   return(i);
 
259
}
 
260
 
 
261
double GetAvg(int n, double tolerance, double *mflop)
 
262
{
 
263
   int i, j;
 
264
   double t0, tavg;
 
265
/*
 
266
 * Sort results, largest first
 
267
 */
 
268
   for (i=0; i != n; i++)
 
269
   {
 
270
      for (j=i+1; j < n; j++)
 
271
      {
 
272
         if (mflop[i] < mflop[j])
 
273
         {
 
274
            t0 = mflop[i];
 
275
            mflop[i] = mflop[j];
 
276
            mflop[j] = t0;
 
277
         }
 
278
      }
 
279
   }
 
280
 
 
281
/*
 
282
 * Throw out result if it is outside tolerance; rerun if two mflop not within
 
283
 * tolerance;  this code assumes n == 3
 
284
 */
 
285
   if (tolerance*mflop[1] < mflop[0])  /* too big a range in results */
 
286
   {
 
287
      if (tolerance*mflop[2] < mflop[1]) return(-1.0);
 
288
      tavg = (mflop[1] + mflop[2]) / 2.0;
 
289
   }
 
290
   else if (tolerance*mflop[2] < mflop[0]) tavg = (mflop[0] + mflop[1]) / 2.0;
 
291
   else tavg = (mflop[0] + mflop[1] + mflop[2]) / 3.0;
 
292
 
 
293
   return(tavg);
 
294
}
 
295
 
 
296
double mms_case(char pre, int MULADD, int NB, int mu, int nu, int ku, int lat)
 
297
{
 
298
   char fnam[128], ln[256];
 
299
   int i;
 
300
   double mflop[NTIM], t0;
 
301
   FILE *fp;
 
302
 
 
303
   if (ku > NB) ku = NB;
 
304
   else if (ku == -1) ku = NB;
 
305
   sprintf(fnam, "res/%c%smm%c%c%d_%dx%dx%d_%dx%dx%d_%dx%dx%d%s%s_%dx%d_%d",
 
306
           pre, "JIK", 'T', 'N', NB, NB, NB, NB, NB, NB, 0, mu, nu, ku, 
 
307
           "_a1", "_b1", MULADD, lat, 1);
 
308
#if 0
 
309
   sprintf(fnam, "res/%c%cNB%d_%dx%dx%d_%d-%d.mflop", LANG, pre, NB, mu, nu,
 
310
           ku, MULADD, lat);
 
311
#endif
 
312
   if (!FileExists(fnam))
 
313
   {
 
314
      if (pre == 'c' || pre == 'z')
 
315
         sprintf(ln,
 
316
" make mmcase pre=%c loopO=%s ta=%c tb=%c mb=%d nb=%d kb=%d lda=%d ldb=%d ldc=%d mu=%d nu=%d ku=%d alpha=%d beta=%d muladd=%d lat=%d csA=1 csB=1 csC=2 cleanup=%d\n",
 
317
                   pre, "JIK", 'T', 'N', NB, NB, NB, NB, NB, 0, mu, nu, ku,
 
318
                   1, 1, MULADD, lat, 1);
 
319
      else sprintf(ln,
 
320
" make mmcase pre=%c loopO=%s ta=%c tb=%c mb=%d nb=%d kb=%d lda=%d ldb=%d ldc=%d mu=%d nu=%d ku=%d alpha=%d beta=%d muladd=%d lat=%d cleanup=%d\n",
 
321
                   pre, "JIK", 'T', 'N', NB, NB, NB, NB, NB, 0, mu, nu, ku,
 
322
                   1, 1, MULADD, lat, 1);
 
323
      fprintf(stderr, "%s:\n",ln);
 
324
      if (system(ln) != 0)
 
325
      {
 
326
         fprintf(stderr, "Error in command: %s", ln);
 
327
         sprintf(ln, "rm -f %s\n", fnam);
 
328
         system(ln);
 
329
         exit(-1);
 
330
      }
 
331
   }
 
332
   assert( (fp = fopen(fnam, "r")) != NULL );
 
333
   for (i=0; i != NTIM; i++)
 
334
   {
 
335
      assert( fscanf(fp, "%lf", &mflop[i]) == 1 );
 
336
   }
 
337
   fclose(fp);
 
338
 
 
339
   t0 = GetAvg(NTIM, TOLERANCE, mflop);
 
340
   if (t0 == -1.0)
 
341
   {
 
342
      fprintf(stderr, "NB=%d, MU=%d, NU=%d, KU=%d: rerun with higher reps; variation exceeds tolerence\n", NB, mu, nu, ku);
 
343
      sprintf(ln, "rm -f res/%s\n", fnam);
 
344
      system(ln);
 
345
      exit(-1);
 
346
   }
 
347
   fprintf(stdout, 
 
348
      "\npre=%c, muladd=%d, lat=%d, nb=%d, mu=%d, nu=%d, ku=%d, mflop=%.2f\n",
 
349
           pre, MULADD, lat, NB, mu, nu, ku, t0);
 
350
   return(t0);
 
351
}
 
352
 
 
353
double mmcase0(char *nam, char pre, char *loopO, char ta, char tb, 
 
354
              int M, int N, int K, int mb, int nb, int kb, 
 
355
              int lda, int ldb, int ldc, int mu, int nu, int ku, 
 
356
              int muladd, int lat, int beta, int csA, int csB, int csC, 
 
357
              int FFetch, int ifetch, int nfetch, char *mmnam)
 
358
{
 
359
   char fnam[128], ln[512], bnam[16], casnam[128], mmcase[128];
 
360
   int i, N0, lda2=lda, ldb2=ldb, ldc2=ldc;
 
361
   double mflop[NTIM], t0;
 
362
   FILE *fp;
 
363
 
 
364
   if (lda < 0) { lda2 = -lda; lda = 0; }
 
365
   if (ldb < 0) { ldb2 = -ldb; ldb = 0; }
 
366
   if (ldc < 0) { ldc2 = -ldc; ldc = 0; }
 
367
   if (mmnam) sprintf(mmcase, "mmucase mmrout=%s", mmnam);
 
368
   else sprintf(mmcase, "mmcase");
 
369
   if (ifetch == -1 || nfetch == -1) { ifetch = mu+nu; nfetch = 1; }
 
370
   if (beta == 1) sprintf(bnam, "_b1");
 
371
   else if (beta == -1) sprintf(bnam, "_bn1");
 
372
   else if (beta == 0) sprintf(bnam, "_b0");
 
373
   else sprintf(bnam, "_bX");
 
374
   N0 = Mmax(M,N);
 
375
   if (N0 < K) N0 = K;
 
376
   if (ku > K) ku = K;
 
377
   else if (ku == -1) ku = K;
 
378
   if (nam)
 
379
   {
 
380
      strcpy(fnam, nam);
 
381
      sprintf(casnam, "casnam=%s", nam);
 
382
   }
 
383
   else
 
384
   {
 
385
      sprintf(fnam, "res/%c%smm%c%c%d_%dx%dx%d_%dx%dx%d_%dx%dx%d%s%s_%dx%d_%d",
 
386
              pre, loopO, ta, tb, N0, mb, nb, kb, lda, ldb, ldc, mu, nu, ku, 
 
387
              "_a1", bnam, muladd, lat, 1);
 
388
      casnam[0] = '\0';
 
389
   }
 
390
   if (!FileExists(fnam))
 
391
   {
 
392
      if (pre == 'c' || pre == 'z')
 
393
         sprintf(ln,
 
394
" make %s pre=%c loopO=%s ta=%c tb=%c M=%d N=%d K=%d mb=%d nb=%d kb=%d lda=%d ldb=%d ldc=%d lda2=%d ldb2=%d ldc2=%d mu=%d nu=%d ku=%d alpha=%d beta=%d muladd=%d lat=%d cleanup=%d csA=%d csB=%d csC=%d ff=%d if=%d nf=%d %s\n",
 
395
                 mmcase,pre, loopO, ta, tb, M, N, K, mb, nb, kb, lda, ldb, ldc, 
 
396
                 lda2, ldb2, ldc2, mu, nu, ku, 1, beta, muladd, lat, 1, 
 
397
                 csA, csB, csC, FFetch, ifetch, nfetch, casnam);
 
398
      else sprintf(ln,
 
399
" make %s pre=%c loopO=%s ta=%c tb=%c M=%d N=%d K=%d mb=%d nb=%d kb=%d lda=%d ldb=%d ldc=%d lda2=%d ldb2=%d ldc2=%d mu=%d nu=%d ku=%d alpha=%d beta=%d muladd=%d lat=%d cleanup=%d ff=%d if=%d nf=%d %s\n",
 
400
                   mmcase, pre, loopO, ta, tb, M, N, K, mb, nb, kb, lda, ldb,
 
401
                   ldc, lda2, ldb2, ldc2, mu, nu, ku, 1, beta, muladd, lat, 1, 
 
402
                   FFetch, ifetch, nfetch, casnam);
 
403
      fprintf(stderr, "%s:\n",ln);
 
404
      if (system(ln) != 0)
 
405
      {
 
406
/*
 
407
 *       User cases, and large leading dimensions can fail to run
 
408
 */
 
409
         if (mmnam) return(-1.0);  /* user cases can fail to compile */
 
410
         if (lda2 != lda || ldb2 != ldb || ldc2 != ldc) return(-1);
 
411
         fprintf(stderr, "Error in command: %s", ln);
 
412
         sprintf(ln, "rm -f %s\n", fnam);
 
413
         system(ln);
 
414
         exit(-1);
 
415
      }
 
416
   }
 
417
   fp = fopen(fnam, "r");
 
418
   if (!fp) fprintf(stderr, "ERROR: can't find file=%s\n", fnam);
 
419
   assert(fp);
 
420
   for (i=0; i != NTIM; i++)
 
421
   {
 
422
      assert(fscanf(fp, "%lf", &mflop[i]) == 1);
 
423
   }
 
424
   fclose(fp);
 
425
 
 
426
   t0 = GetAvg(NTIM, TOLERANCE, mflop);
 
427
   if (t0 == -1.0)
 
428
   {
 
429
      fprintf(stderr, 
 
430
      "case=%s: rerun with higher reps; variation exceeds tolerence\n", fnam);
 
431
      sprintf(ln, "rm -f %s\n", fnam);
 
432
      system(ln);
 
433
      exit(-1);
 
434
   }
 
435
   fprintf(stdout, 
 
436
"\n   pre=%c, loopO=%s, ta=%c tb=%c, mb=%d, nb=%d, kb=%d, lda=%d, ldb=%d, ldc=%d\n",
 
437
           pre, loopO, ta, tb, mb, nb, kb, lda, ldb, ldc);
 
438
  fprintf(stdout, "   mu=%d, nu=%d, ku=%d, muladd=%d, lat=%d ====> mflop=%f\n",
 
439
          mu, nu, ku, muladd, lat, t0);
 
440
   return(t0);
 
441
}
 
442
 
 
443
double mmucase(int ifile, char pre, int nb, int muladd, int lat, 
 
444
               int mu, int nu, int ku, char *fnam)
 
445
{
 
446
   char fout[64];
 
447
   int iff;
 
448
 
 
449
   sprintf(fout, "res/%cuser%d", pre, ifile);
 
450
   if (mu == 1 && nu == 1) iff = 1;
 
451
   else iff = mu + nu;
 
452
   return(mmcase0(fout, pre, "JIK", 'T', 'N', nb, nb, nb, nb, nb, nb, 
 
453
                  nb, nb, 0, mu, nu, ku, muladd, lat, 1, 1, 1, 2, 0, iff, 1,
 
454
                  fnam));
 
455
}
 
456
 
 
457
enum CW {CleanM=0, CleanN=1, CleanK=2, CleanNot=3};
 
458
double mmclean(char pre, enum CW which, char *loopO, char ta, char tb, 
 
459
               int M, int N, int K, int mb, int nb, int kb, 
 
460
               int lda, int ldb, int ldc, int mu, int nu, int ku, 
 
461
               int muladd, int lat, int beta, int csA, int csB, int csC, 
 
462
               int FFetch, int ifetch, int nfetch)
 
463
{
 
464
   char nam[128];
 
465
   char cwh[3] = {'M', 'N', 'K'};
 
466
   sprintf(nam, "res/%cClean%c_%dx%dx%d", pre, cwh[which], M, N, K);
 
467
   return(mmcase0(nam, pre, loopO, ta, tb, M, N, K, mb, nb, kb, lda, ldb, ldc,
 
468
                  mu, nu, ku, muladd, lat, beta, csA, csB, csC, 
 
469
                  FFetch, ifetch, nfetch, NULL));
 
470
}
 
471
 
 
472
double mmcase(char *nam, char pre, char *loopO, char ta, char tb, 
 
473
              int M, int N, int K, int mb, int nb, int kb, 
 
474
              int lda, int ldb, int ldc, int mu, int nu, int ku, 
 
475
              int muladd, int lat, int beta, int csA, int csB, int csC, 
 
476
              int FFetch, int ifetch, int nfetch)
 
477
{
 
478
   return(mmcase0(nam, pre, loopO, ta, tb, M, N, K, mb, nb, kb, lda, ldb, ldc,
 
479
                  mu, nu, ku, muladd, lat, beta, csA, csB, csC, 
 
480
                  FFetch, ifetch, nfetch, NULL));
 
481
}
 
482
 
 
483
int GetGoodLat(int MULADD, int kb, int mu, int nu, int ku, int lat)
 
484
{
 
485
   int slat, blat, i, ii = mu*nu*ku;
 
486
   if (MULADD) return(lat);
 
487
   if ( (lat > 1) && (kb > ku) && ((ii/lat)*lat != ii) )  /* lat won't work */
 
488
   {
 
489
      for (i=lat; i; i--) if ( (ii/i) * i == ii ) break;
 
490
      slat = i;
 
491
      for (i=lat; i < MAXLAT; i++) if ( (ii/i) * i == ii ) break;
 
492
      blat = i;
 
493
      if ( (ii/blat)*blat != ii ) blat = slat;
 
494
      if (slat < 2) lat = blat;
 
495
      else if (lat-slat < blat-lat) lat = slat;
 
496
      else lat = blat;
 
497
   }
 
498
   return(lat);
 
499
}
 
500
 
 
501
void FindMUNU(int muladd, int lat, int nr, int *MU, int *NU)
 
502
/*
 
503
 * Find near-square muxnu using nr registers or less
 
504
 */
 
505
{
 
506
   int j, mu, nu;
 
507
 
 
508
   if (nr < 1)
 
509
   {
 
510
      *MU = lat;
 
511
      *NU = 1;
 
512
      return;
 
513
   }
 
514
   if (muladd) j = nr;
 
515
   else j = nr - lat;
 
516
   if (j < 3) mu = nu = 1;
 
517
   else
 
518
   {
 
519
      mu = j + 1;
 
520
      for (nu=1; nu*nu < mu; nu++);
 
521
      if (nu*nu > mu) nu -= 2;
 
522
      else nu--;
 
523
      if (nu < 1) mu = nu = 1;
 
524
      else
 
525
      {
 
526
         mu = (nr-nu) / (1+nu);
 
527
         if (mu < 1) mu = 1;
 
528
      }
 
529
      if (mu < nu)
 
530
      {
 
531
         j = mu;
 
532
         mu = nu;
 
533
         nu = j;
 
534
      }
 
535
   }
 
536
   *MU = mu;
 
537
   *NU = nu;
 
538
}
 
539
 
 
540
void PutInstLogLine(FILE *fp, int muladd, int lat, int nb, 
 
541
                    int mu, int nu, int ku, int ForceFetch, 
 
542
                    int ifetch, int nfetch, double mflop)
 
543
{
 
544
   fprintf(fp, "%6d  %3d %3d %3d %3d %3d  %5d  %5d  %5d  %7.2lf\n",
 
545
           muladd, lat, nb, mu, nu, ku, ForceFetch, ifetch, nfetch, mflop);
 
546
}
 
547
void PutInstLogFile(FILE *fp, int muladd, int lat, int nb, 
 
548
                    int mu, int nu, int ku, int ForceFetch, 
 
549
                    int ifetch, int nfetch, double mflop)
 
550
{
 
551
   fprintf(fp, "MULADD  LAT  NB  MU  NU  KU  FFTCH  IFTCH  NFTCH    MFLOP\n");
 
552
   PutInstLogLine(fp, muladd, lat, nb, mu, nu, ku, ForceFetch, 
 
553
                  ifetch, nfetch, mflop);
 
554
}
 
555
void PutInstLogFile1(char *fnam, char pre, int muladd, int lat, int nb, 
 
556
                    int mu, int nu, int ku, int ForceFetch, 
 
557
                    int ifetch, int nfetch, double mflop)
 
558
{
 
559
   FILE *fp;
 
560
 
 
561
   fp = fopen(fnam, "w");
 
562
   assert(fp);
 
563
   PutInstLogFile(fp, muladd, lat, nb, mu, nu, ku, ForceFetch, ifetch, nfetch, 
 
564
                  mflop);
 
565
   fclose(fp);
 
566
}
 
567
 
 
568
void GetInstLogLine(FILE *fp, int *muladd, int *lat, int *nb, 
 
569
                    int *mu, int *nu, int *ku, int *ForceFetch,
 
570
                    int *ifetch, int *nfetch, double *mflop)
 
571
{
 
572
   assert(fscanf(fp, " %d %d %d %d %d %d %d %d %d %lf\n",
 
573
                 muladd, lat, nb, mu, nu, ku, ForceFetch, 
 
574
                 ifetch, nfetch, mflop) == 10);
 
575
}
 
576
 
 
577
void GetInstLogFile(char *nam, char pre, int *muladd, int *lat, int *nb, 
 
578
                    int *mu, int *nu, int *ku, int *ForceFetch,
 
579
                    int *ifetch, int *nfetch, double *mflop)
 
580
{
 
581
   char ln[128];
 
582
   FILE *fp;
 
583
 
 
584
   fp = fopen(nam, "r");
 
585
   if (fp == NULL) fprintf(stderr, "file %s not found!!\n\n", nam);
 
586
   assert(fp);
 
587
   fgets(ln, 128, fp);
 
588
   GetInstLogLine(fp, muladd, lat, nb, mu, nu, ku, ForceFetch, 
 
589
                  ifetch, nfetch, mflop);
 
590
   fclose(fp);
 
591
}
 
592
 
 
593
 
 
594
 
 
595
void CreateFinalSumm(char pre, int muladd, int lat, int nb, int mu, int nu,
 
596
                     int ku, int Ff, int If, int Nf, double gmf)
 
597
{
 
598
   char ln[64], auth[65];
 
599
   FILE *fp, *fp0;
 
600
   int icase, unb;
 
601
   double umf;
 
602
 
 
603
   sprintf(ln, "res/%cMMRES", pre);
 
604
   fp = fopen(ln, "w");
 
605
   PutInstLogFile(fp, muladd, lat, nb, mu, nu, ku, Ff, If, Nf, gmf);
 
606
   sprintf(ln, "res/%cuMMRES", pre);
 
607
   fp0 = fopen(ln, "r");
 
608
   assert(fp0);
 
609
   assert(fgets(ln, 64, fp0));
 
610
   assert(fscanf(fp0, " %d %d %lf \"%[^\"]\" \"%[^\"]", &icase, &unb, &umf,
 
611
                 ln, auth) == 5);
 
612
   fclose(fp0);
 
613
   fprintf(fp, "\nICASE  NB    MFLOP  ROUT  AUTHOR\n");
 
614
   fprintf(fp, "%5d %3d %8.2f  \"%.63s\" \"%.63s\"\n", icase, unb, umf,
 
615
           ln, auth);
 
616
   fclose(fp);
 
617
}
 
618
 
 
619
 
 
620
void FindFetch(char ta, char tb, char pre, int mb, int nb, int kb, 
 
621
               int mu, int nu, int ku, int muladd, int lat,
 
622
               int *FFetch0, int *ifetch0, int *nfetch0)
 
623
/*
 
624
 * See what fetch patterns are appropriate
 
625
 */
 
626
{
 
627
   char fnam[128];
 
628
   const int nelts = mu+nu;
 
629
   int csA=1, csB=1, csC=1, nleft, i, j;
 
630
   int ifetch = mu+nu, nfetch = 1;
 
631
   double mf, mf0;
 
632
 
 
633
   if (pre == 'c' || pre == 'z') csC = 2;
 
634
 
 
635
   mf0 = mmcase(NULL, pre, "JIK", ta,  tb, mb, nb, kb, mb, nb, kb, 
 
636
                kb, kb, 0, mu, nu, ku, muladd, lat, 0, csA, csB, csC, 
 
637
                0, ifetch, nfetch);
 
638
 
 
639
   for (i=2; i < nelts; i++)
 
640
   {
 
641
      nleft = nelts - i;
 
642
      for (j=1; j <= nleft; j++)
 
643
      {
 
644
         sprintf(fnam, "res/%cMMfetch%d_%d", pre, i, j);
 
645
         mf = mmcase(fnam, pre, "JIK", ta,  tb, mb, nb, kb, mb, nb, kb, 
 
646
                     kb, kb, 0, mu, nu, ku, muladd, lat, 0, csA, csB, csC, 
 
647
                     0, i, j);
 
648
         if (mf > mf0)
 
649
         {
 
650
            mf = mf0;
 
651
            ifetch = i;
 
652
            nfetch = j;
 
653
         }
 
654
      }
 
655
   }
 
656
/*
 
657
 * See if prefetching good idea for beta=0 case
 
658
 */
 
659
   sprintf(fnam, "res/%cMM_b0", pre);
 
660
   mf0 = mmcase(fnam, pre, "JIK", ta,  tb, mb, nb, kb, mb, nb, kb, 
 
661
                kb, kb, 0, mu, nu, ku, muladd, lat, 0, csA, csB, csC, 
 
662
                0, ifetch, nfetch);
 
663
 
 
664
   sprintf(fnam, "res/%cMM_b0_pref", pre);
 
665
   mf = mmcase(fnam, pre, "JIK", ta,  tb, mb, nb, kb, mb, nb, kb, 
 
666
               kb, kb, 0, mu, nu, ku, muladd, lat, 0, csA, csB, csC, 
 
667
               1, ifetch, nfetch);
 
668
 
 
669
   *FFetch0 = (mf > mf0);
 
670
   *ifetch0 = ifetch;
 
671
   *nfetch0 = nfetch;
 
672
   fprintf(stdout, "\n\nFORCEFETCH=%d, IFETCH = %d, NFETCH = %d\n\n",
 
673
           *FFetch0, *ifetch0, *nfetch0);
 
674
}
 
675
 
 
676
 
 
677
void searchmu_nu(char pre, int nb, int maxreg, int Fku, int muladd, int LAT,
 
678
                 int NO1D, double *mfB, int *nbB, int *muB, int *nuB, int *kuB,
 
679
                 int *latB)
 
680
{
 
681
   int i, j, lat, ku, nr2, nreg=Mmin(nb, maxreg);
 
682
   double mf;
 
683
 
 
684
   for (i=1; i <= nreg; i++)
 
685
   {
 
686
      nr2 = maxreg / i;
 
687
      if (nr2 > nb) nr2 = nb;
 
688
      for (j=1; j <= nreg; j++)
 
689
      {
 
690
         if ( (((i==1) && (j > 4)) || ((j==1) && (i > 4))) && NO1D) continue;
 
691
         if (Fku == -1 || (!Fku) ) ku = nb;
 
692
         else if (Fku) ku = Fku;
 
693
         if (ku != nb) lat = GetGoodLat(muladd, nb, i, j, ku, LAT);
 
694
         else lat = LAT;
 
695
         if (j*i+j+i+(!muladd)*lat > maxreg) continue;  /* not enough regs */
 
696
         mf = mms_case(pre, muladd, nb, i, j, ku, lat);
 
697
         if (mf > *mfB)
 
698
         {
 
699
            *mfB = mf;
 
700
            *nbB = nb;
 
701
            *muB = i;
 
702
            *nuB = j;
 
703
            *kuB = ku;
 
704
            *latB = LAT;
 
705
         }
 
706
         if (!Fku)
 
707
         {
 
708
            lat = GetGoodLat(muladd, nb, i, j, 1, LAT);
 
709
            mf = mms_case(pre, muladd, nb, i, j, 1, lat);
 
710
            if (mf > *mfB)
 
711
            {
 
712
               *mfB = mf;
 
713
               *nbB = nb;
 
714
               *muB = i;
 
715
               *nuB = j;
 
716
               *kuB = 1;
 
717
               *latB = lat;
 
718
            }
 
719
         }
 
720
      }
 
721
   }
 
722
}
 
723
 
 
724
void FindKU(char pre, int muladd, int LAT, int nb, int mu, int nu,
 
725
            double *mfB, int *kuB, int *latB)
 
726
/*
 
727
 * For best case, try various ku's
 
728
 */
 
729
{
 
730
   int k, lat;
 
731
   double mf;
 
732
 
 
733
   fprintf(stderr, "Confirming K-loop unrollings for chosen NB:\n");
 
734
   mf = mms_case(pre, muladd, nb, mu, nu, nb, LAT);
 
735
   if (mf > *mfB)
 
736
   {
 
737
      *kuB = nb;
 
738
      *mfB = mf;
 
739
      *latB = LAT;
 
740
   }
 
741
   for (k=1; k < nb; k += 4)
 
742
   {
 
743
      if (k == 5) k = 4;
 
744
      if (k > nb/2) k = nb;
 
745
      lat = GetGoodLat(muladd, nb, mu, nu, k, *latB);
 
746
      mf = mms_case(pre, muladd, nb, mu, nu, k, lat);
 
747
      if (mf > *mfB)
 
748
      {
 
749
         *latB = lat;
 
750
         *kuB = k;
 
751
         *mfB = mf;
 
752
      }
 
753
   }
 
754
}
 
755
 
 
756
void FindLAT(char pre, int maxlat, int nb, int muladd, int mu, int nu, int ku,
 
757
             double *mfB, int *latB)
 
758
 
 
759
{
 
760
   int i, lat;
 
761
   double mf;
 
762
 
 
763
   fprintf(stderr, "\nConfirming latency factors for chosen parameters:\n");
 
764
   for (i=1; i <= maxlat; i++)
 
765
   {
 
766
      lat = GetGoodLat(muladd, nb, mu, nu, ku, i);
 
767
      if (lat == i)
 
768
      {
 
769
         mf = mms_case(pre, muladd, nb, mu, nu, ku, lat);
 
770
         if (mf > *mfB)
 
771
         {
 
772
            *mfB = mf;
 
773
            *latB = i;
 
774
         }
 
775
      }
 
776
   }
 
777
   fprintf(stderr, "\n\n   Best latency factor=%d\n\n", *latB);
 
778
}
 
779
 
 
780
int CheckUser(char pre, double adv, double gmf, int gnb, double *umf)
 
781
/*
 
782
 * Checks if user case is better than generated, and if so, return umb
 
783
 */
 
784
{
 
785
   FILE *fp;
 
786
   char fnam[128];
 
787
   int i, unb;
 
788
   double umflop;
 
789
   sprintf(fnam, "res/%cuMMRES", pre);
 
790
   if (!FileExists(fnam))  /* need to run user search */
 
791
   {
 
792
      sprintf(fnam, "make RunUMMSearch pre=%c nb=%d\n", pre, gnb);
 
793
      assert(system(fnam) == 0);
 
794
      sprintf(fnam, "res/%cuMMRES", pre);
 
795
   }
 
796
   fp = fopen(fnam, "r");
 
797
   assert(fp);
 
798
   assert(fgets(fnam, 128, fp));
 
799
   assert(fgets(fnam, 128, fp));
 
800
   fclose(fp);
 
801
   sscanf(fnam, " %d %d %lf", &i, &unb, &umflop);
 
802
   if (i >= 0 && umflop < 0.0)  /* need to retime */
 
803
   {
 
804
      sprintf(fnam, "make RunUMMSearch pre=%c nb=0\n", pre);
 
805
      assert(system(fnam) == 0);
 
806
      sprintf(fnam, "res/%cuMMRES", pre);
 
807
      fp = fopen(fnam, "r");
 
808
      assert(fp);
 
809
      assert(fgets(fnam, 128, fp));
 
810
      assert(fgets(fnam, 128, fp));
 
811
      fclose(fp);
 
812
      sscanf(fnam, " %d %d %lf", &i, &unb, &umflop);
 
813
   }
 
814
   fprintf(stdout, "\nBEST USER CASE: NB=%d, MFLOP=%.2f\n", unb, umflop);
 
815
   if (umf) *umf = umflop;
 
816
   if (adv*gmf > umflop) return(gnb);
 
817
   else return(unb);
 
818
}
 
819
 
 
820
int GetNO1D(char pre, int nreg, int nb, int MULADD, int LAT)
 
821
{
 
822
   int lat, NO1D=0;
 
823
   double mf0, mf1, mf;
 
824
 
 
825
   if (pre == 'z') pre = 'd';
 
826
   else if (pre == 'c') pre = 's';
 
827
 
 
828
   lat = GetGoodLat(MULADD, nb, 3, 3, 1, LAT);
 
829
   if (nreg >= 15+(!MULADD)*Mmax(LAT,lat))
 
830
   {
 
831
      mf0 = mms_case(pre, MULADD, nb, 3, 3, 1, lat);
 
832
      mf1 = mms_case(pre, MULADD, nb, 3, 3, nb, LAT);
 
833
      mf = Mmax(mf1, mf0);
 
834
      mf0 = mms_case(pre, MULADD, nb, 9, 1, 1, lat);
 
835
      if (mf0 > mf) NO1D = 0;
 
836
      else if (mms_case(pre, MULADD, nb, 9, 1, nb, LAT) > mf) NO1D = 0;
 
837
      else if (mms_case(pre, MULADD, nb, 1, 9, nb, LAT) > mf) NO1D = 0;
 
838
      else if (mms_case(pre, MULADD, nb, 1, 9, 1, lat) > mf) NO1D = 0;
 
839
      else NO1D = 1;
 
840
   }
 
841
   return(NO1D);
 
842
}
 
843
 
 
844
void gmmsearch(char pre, int MULADD, int Fku, int nNBs, int *NBs, int nreg,
 
845
               int LAT, int Fnb)
 
846
/*
 
847
 * Does real generated mmsearch
 
848
 */
 
849
{
 
850
   int latB, muB, nuB, kuB, nbB;
 
851
   int i, j, k, NB, TEST_MU, TEST_NU, ku, nb, lat=LAT, nNB=nNBs, NO1D=0;
 
852
   int FFetch, ifetch, nfetch, muladd;
 
853
   double mf, mfB;
 
854
   char ln[32];
 
855
   FILE *fp;
 
856
 
 
857
   sprintf(ln, "res/%cgMMRES", pre);
 
858
   if (FileExists(ln)) /* already have needed result */
 
859
   {
 
860
      GetInstLogFile(ln, pre, &muladd, &lat, &nb, &muB, &nuB, &kuB, &FFetch,
 
861
                     &ifetch, &nfetch, &mf);
 
862
      if (mf <= 0.0)
 
863
      {
 
864
         mf = mmcase(NULL, pre, "JIK", 'T', 'N', nb, nb, nb, nb, nb, nb,
 
865
                     nb, nb, 0, muB, nuB, kuB, muladd, lat, 1, 1, 1, 2,
 
866
                     FFetch, ifetch, nfetch);
 
867
         PutInstLogFile1(ln, pre, muladd, lat, nb, muB, nuB, kuB, FFetch,
 
868
                         ifetch, nfetch, mf);
 
869
      }
 
870
      return;
 
871
   }
 
872
/*
 
873
 * Try not to tempt fate by using all registers
 
874
 */
 
875
   if (nreg > 16) i = nreg-2;
 
876
   else i = nreg;
 
877
   FindMUNU(MULADD, lat, i, &TEST_MU, &TEST_NU);
 
878
/*
 
879
 * First, find a good NB
 
880
 */
 
881
   mfB = 0.0;
 
882
   fprintf(stderr, "Doing initial NB search:\n");
 
883
   i = 0;
 
884
   for (k=0; k != nNBs; k++)
 
885
   {
 
886
      NB = NBs[k];
 
887
      ku = NB;
 
888
      mf = mms_case(pre, MULADD, NB, TEST_MU, TEST_NU, ku, lat);
 
889
      if (mf > mfB)
 
890
      {
 
891
         mfB = mf;
 
892
         nbB = NB;
 
893
         muB = TEST_MU;
 
894
         nuB = TEST_NU;
 
895
         kuB = ku;
 
896
         latB = lat;
 
897
         i = k;
 
898
      }
 
899
      if (Fku == 0)  /* try no K-loop unrolling */
 
900
      {
 
901
         lat = GetGoodLat(MULADD, NB, TEST_MU, TEST_NU, 1, LAT);
 
902
         mf = mms_case(pre, MULADD, NB, TEST_MU, TEST_NU, 1, lat);
 
903
         if (mf > mfB)
 
904
         {
 
905
            mfB = mf;
 
906
            nbB = NB;
 
907
            muB = TEST_MU;
 
908
            nuB = TEST_NU;
 
909
            kuB = 1;
 
910
            latB = lat;
 
911
            i = k;
 
912
         }
 
913
      }
 
914
      if (i)
 
915
      {
 
916
         j = NBs[i];
 
917
         NBs[i] = NBs[0];
 
918
         NBs[0] = j;
 
919
      }
 
920
      fprintf(stderr, "NB=%d selected:\n", NBs[0]);
 
921
   }
 
922
 
 
923
   if (!Fnb) nNB = 1;
 
924
   if (MULADD)
 
925
      fprintf(stderr, "\nCombined multiply add, latency factor=%d, NB=%d ku=%d, chosen; initial MFLOP=%f.  Beginning unroll search:\n", latB, NBs[0], kuB, mfB);
 
926
   else
 
927
      fprintf(stderr, "\nSeparate multiply and add, latency factor=%d, NB=%d ku=%d, chosen; initial MFLOP=%f.  Beginning unroll search:\n", latB, NBs[0], kuB, mfB);
 
928
 
 
929
   NO1D = GetNO1D(pre, nreg, NBs[0], MULADD, LAT);
 
930
   if (NO1D) fprintf(stderr, "\n\nSkipping most 1D cases\n\n");
 
931
   else fprintf(stderr, "\n\nTiming 1D cases\n\n");
 
932
   for (k=0; k != nNB; k++)
 
933
   {
 
934
      NB = NBs[k];
 
935
      searchmu_nu(pre, NB, nreg, Fku, MULADD, LAT, NO1D,
 
936
                  &mfB, &nbB, &muB, &nuB, &kuB, &latB);
 
937
   }
 
938
   fprintf(stderr, "\n\nBest case so far: nb=%d, mu=%d, nu=%d, ku=%d, lat=%d; MFLOPS=%f.\n",
 
939
           nbB, muB, nuB, kuB, latB, mfB);
 
940
   fprintf(stderr, "Trying various other NB and KU settings:\n\n");
 
941
/*
 
942
 * If we haven't checked all permutations, try other blocking factors
 
943
 */
 
944
   nb = nbB;
 
945
   if (!Fnb)
 
946
   {
 
947
      if (nNBs > 1) fprintf(stderr, "Trying various blocking factors:\n");
 
948
      mf = mms_case(pre, MULADD, NBs[0], muB, nuB, kuB, latB);
 
949
      for (k=0; k < nNBs; k++)
 
950
      {
 
951
         NB = NBs[k];
 
952
         if (Fku == -1) ku = NB;
 
953
         else if (Fku) ku = Fku;
 
954
         else if (kuB == nbB) ku = NB;
 
955
         else ku = kuB;
 
956
         if (ku != NB) lat = GetGoodLat(MULADD, NB, muB, nuB, ku, latB);
 
957
         else lat = latB;
 
958
         mf = mms_case(pre, MULADD, NB, muB, nuB, ku, lat);
 
959
         if (mf > mfB)
 
960
         {
 
961
            kuB = ku;
 
962
            mfB = mf;
 
963
            nbB = NB;
 
964
            latB = lat;
 
965
         }
 
966
      }
 
967
   }
 
968
   if (nb != nbB) fprintf(stderr, "\nNew block factor of %d chosen!!\n\n", nbB);
 
969
   NB = nbB;
 
970
 
 
971
/*
 
972
 * Try all ku's, and then valid latencies
 
973
 */
 
974
   FindKU(pre, MULADD, LAT, nbB, muB, nuB, &mfB, &kuB, &latB);
 
975
   FindLAT(pre, MAXLAT, nbB, MULADD, muB, nuB, kuB, &mfB, &latB);
 
976
 
 
977
/*
 
978
 * Make sure MULADD is correct
 
979
 */
 
980
   lat = GetGoodLat(!MULADD, nbB, muB, nuB, kuB, latB);
 
981
   mf = mms_case(pre, !MULADD, nbB, muB, nuB, kuB, lat);
 
982
   if (mf > mfB)
 
983
   {
 
984
      fprintf(stderr, "\n\nMULADD MAY BE WRONG!!, old=%f, new=%f\n", mfB, mf);
 
985
   }
 
986
/*
 
987
 * Try various fetch patterns
 
988
 */
 
989
   FindFetch('T', 'N', pre, nbB, nbB, nbB, muB, nuB, kuB, MULADD, latB,
 
990
             &FFetch, &ifetch, &nfetch);
 
991
   fprintf(stdout, 
 
992
   "BEST GENERATED CASE: nb=%d, ma=%d, lat=%d mu=%d, nu=%d, ku=%d -- %.2f\n",
 
993
           nbB, MULADD, latB, muB, nuB, kuB, mfB);
 
994
   sprintf(ln, "res/%cgMMRES", pre);
 
995
   PutInstLogFile1(ln, pre, MULADD, latB, nbB, muB, nuB, kuB, 
 
996
                   FFetch, ifetch, nfetch, mfB);
 
997
}
 
998
 
 
999
void mmsearch(char pre, int MULADD, int Fku, int nNBs, int *NBs, int nreg,
 
1000
              int LAT, int Fnb)
 
1001
{
 
1002
   int latB, muB, nuB, kuB, nbB;
 
1003
   int muladd, nb, ifetch, nfetch, FFetch;
 
1004
   int i, j, k, NB;
 
1005
   int NO1D;
 
1006
   int umb, unb, ukb, ma;  
 
1007
   double mfB, gmf;
 
1008
   char fnam[128];
 
1009
   FILE *fp;
 
1010
 
 
1011
   sprintf(fnam, "res/%cMMRES", pre);
 
1012
   if (FileExists(fnam)) /* already have result */
 
1013
   {
 
1014
      GetInstLogFile(fnam, pre, &muladd, &latB, &nb, &muB, &nuB, &kuB, &FFetch,
 
1015
                     &ifetch, &nfetch, &mfB);
 
1016
      if (mfB <= 0.0)
 
1017
      {
 
1018
         mfB = mmcase(NULL, pre, "JIK", 'T', 'N', nb, nb, nb, nb, nb, nb,
 
1019
                      nb, nb, 0, muB, nuB, kuB, muladd, latB, 1, 1, 1, 2,
 
1020
                      FFetch, ifetch, nfetch);
 
1021
         gmmsearch(pre, muladd, Fku, nNBs, NBs, nreg, latB, Fnb);
 
1022
         nb = CheckUser(pre, 1.02, mfB, nb, NULL);
 
1023
         CreateFinalSumm(pre, muladd, latB, nb, muB, nuB, kuB, FFetch, ifetch, 
 
1024
                         nfetch, mfB);
 
1025
      }
 
1026
      sprintf(fnam, "res/%cNB", pre);
 
1027
      fp = fopen(fnam, "w");
 
1028
      fprintf(fp, "%d\n%d\n", 1, nbB);
 
1029
      fclose(fp);
 
1030
      return;
 
1031
   }
 
1032
   gmmsearch(pre, MULADD, Fku, nNBs, NBs, nreg, LAT, Fnb);
 
1033
   sprintf(fnam, "res/%cgMMRES", pre);
 
1034
   GetInstLogFile(fnam, pre, &muladd, &latB, &nbB, &muB, &nuB, &kuB, &FFetch,
 
1035
                  &ifetch, &nfetch, &mfB);
 
1036
   gmf = mfB;
 
1037
   nb = CheckUser(pre, 1.02, mfB, nbB, NULL);
 
1038
   if (nb != nbB)
 
1039
   {
 
1040
      if (kuB == nbB) kuB = nb;
 
1041
      nbB = nb;
 
1042
      if (nb % muB || nb % nuB)
 
1043
      {
 
1044
         NO1D = GetNO1D(pre, nreg, nb, MULADD, LAT);
 
1045
         searchmu_nu(pre, nb, nreg, Fku, MULADD, LAT, NO1D,
 
1046
                     &mfB, &nb, &muB, &nuB, &kuB, &latB);
 
1047
      }
 
1048
      FindKU(pre, MULADD, LAT, nbB, muB, nuB, &mfB, &kuB, &latB);
 
1049
      FindLAT(pre, MAXLAT, nbB, MULADD, muB, nuB, kuB, &mfB, &latB);
 
1050
      FindFetch('T', 'N', pre, nbB, nbB, nbB, muB, nuB, kuB, MULADD, latB,
 
1051
                &FFetch, &ifetch, &nfetch);
 
1052
   }
 
1053
/*
 
1054
 * Save NB we've found 
 
1055
 */
 
1056
   sprintf(fnam, "res/%cNB", pre);
 
1057
   fp = fopen(fnam, "w");
 
1058
   fprintf(fp, "%d\n%d\n", 1, nbB);
 
1059
   fclose(fp);
 
1060
/*
 
1061
 * Save best case parameters we have found
 
1062
 */
 
1063
   CreateFinalSumm(pre, MULADD, latB, nbB, muB, nuB, kuB, FFetch, ifetch,
 
1064
                   nfetch, mfB);
 
1065
}
 
1066
 
 
1067
void FindNC_0(char ta, char tb, char pre, int N, int mb, int nb, int kb, 
 
1068
              int mu, int nu, int ku, int muladd, int lat,
 
1069
              int FFetch, int ifetch, int nfetch)
 
1070
{
 
1071
   int kuB=ku, latB=lat, lat0=lat, kb0=kb;
 
1072
   int i, j, k, csA=1, csB=1, csC=1, kmax;
 
1073
   double mf0, mf;
 
1074
   char fnam[128];
 
1075
   FILE *fp;
 
1076
 
 
1077
   sprintf(fnam, "res/%cbest%c%c_%dx%dx%d", pre, ta, tb, mb, nb, kb);
 
1078
   if (FileExists(fnam)) /* default already exists */
 
1079
   {
 
1080
      GetInstLogFile(fnam, pre, &muladd, &lat, &nb, &mu, &nu, &ku,
 
1081
                     &FFetch, &ifetch, &nfetch, &mf);
 
1082
      if (mf < 0.0) /* need to retime */
 
1083
      {
 
1084
         mf = mmcase(NULL, pre, "JIK", ta, tb, nb, nb, nb,
 
1085
                     nb, nb, nb, 0, 0, 0, mu, nu, ku, muladd, lat, 1,
 
1086
                     1, 1, csC, FFetch, ifetch, nfetch);
 
1087
         PutInstLogFile1(fnam, pre, muladd, lat, nb, mu, nu, ku,
 
1088
                         FFetch, ifetch, nfetch, mf);
 
1089
      }
 
1090
      return;
 
1091
   }
 
1092
   if (pre == 'c' || pre == 'z') csA = csB = csC = 2;
 
1093
   assert(N > 0);
 
1094
   if (kb == 0)
 
1095
   {
 
1096
      kb0 = 100000;
 
1097
      if ((mb*nb)/lat != lat) lat0 = GetGoodLat(muladd, kb0, mu, nu, 1, lat);
 
1098
   }
 
1099
   k = 1024 / (mu*nu);
 
1100
   for (kmax=4; kmax*kmax < k; kmax += 4);
 
1101
   if (pre == 'd' || pre == 's') kmax *= 2;
 
1102
   if (kmax >= N) kmax = N;
 
1103
   else if (kmax > N/2) kmax = N/2;
 
1104
   if (kb == 0) kuB = k = Mmin(ku,kmax);
 
1105
   else k = ku;
 
1106
/*
 
1107
 * Find best non-cleanup case
 
1108
 */
 
1109
   mf0 = mmcase(NULL, pre, "JIK", ta, tb, N, N, N, mb, nb, kb, 0, 0, 0, 
 
1110
                mu, nu, k, muladd, lat0, 1, csA, csB, csC, 
 
1111
                FFetch, ifetch, nfetch);
 
1112
   latB = lat0;
 
1113
/*
 
1114
 * If kb is not known, try all available K unrollings; for large mu*nu*N
 
1115
 * combinations, don't try maximal unrollings in order to avoid having
 
1116
 * the compiler run out of space trying to optimize
 
1117
 */
 
1118
   if (kb == 0)
 
1119
   {
 
1120
      for (k=1; k < kmax; k += 4)
 
1121
      {
 
1122
         if (k == 5) k = 4;
 
1123
         if (k > N/2) k = kmax;
 
1124
         j = k;
 
1125
         if (kb == 0) j = 1;
 
1126
         i = GetGoodLat(muladd, kb0, mu, nu, j, lat);
 
1127
         mf = mmcase(NULL, pre, "JIK", ta, tb, N, N, N, mb, nb, kb, 0, 0, 0, 
 
1128
                     mu, nu, k, muladd, i, 1, csA, csB, csC, 
 
1129
                     FFetch, ifetch, nfetch);
 
1130
         if (mf > mf0) 
 
1131
         {
 
1132
            mf0 = mf;
 
1133
            kuB = k;
 
1134
            latB = i;
 
1135
         }
 
1136
      }
 
1137
   }
 
1138
/*
 
1139
 * If K is known, try only the most common unrollings
 
1140
 */
 
1141
   else
 
1142
   {
 
1143
      i = GetGoodLat(muladd, kb0, mu, nu, 1, lat);
 
1144
      mf = mmcase(NULL, pre, "JIK", ta, tb, N, N, N, mb, nb, kb, 0, 0, 0, 
 
1145
                  mu, nu, 1, muladd, i, 1, csA, csB, csC, 
 
1146
                  FFetch, ifetch, nfetch);
 
1147
      if (mf > mf0) 
 
1148
      {
 
1149
         mf0 = mf;
 
1150
         kuB = 1;
 
1151
         latB = i;
 
1152
      }
 
1153
      i = GetGoodLat(muladd, kb0, mu, nu, 4, lat);
 
1154
      mf = mmcase(NULL, pre, "JIK", ta, tb, N, N, N, mb, nb, kb, 0, 0, 0, 
 
1155
                  mu, nu, 4, muladd, i, 1, csA, csB, csC,
 
1156
                  FFetch, ifetch, nfetch);
 
1157
      if (mf > mf0) 
 
1158
      {
 
1159
         mf0 = mf;
 
1160
         kuB = 4;
 
1161
         latB = i;
 
1162
      }
 
1163
      mf = mmcase(NULL, pre, "JIK", ta, tb, N, N, N, mb, nb, kb, 0, 0, 0, 
 
1164
                  mu, nu, kb, muladd, lat, 1, csA, csB, csC,
 
1165
                  FFetch, ifetch, nfetch);
 
1166
      if (mf > mf0) 
 
1167
      {
 
1168
         mf0 = mf;
 
1169
         kuB = kb;
 
1170
         latB = lat;
 
1171
      }
 
1172
   }
 
1173
/*
 
1174
 * Try various latencies
 
1175
 */
 
1176
   if (kb) i = kuB;
 
1177
   else i = 1;
 
1178
   for (k=2; k < 9; k++)
 
1179
   {
 
1180
      if (((mu*nu*i)/k)*k == mu*nu*i)
 
1181
      {
 
1182
         mf = mmcase(NULL, pre, "JIK", ta, tb, N, N, N, mb, nb, kb, 0, 0, 0, 
 
1183
                     mu, nu, kuB, muladd, k, 1, csA, csB, csC,
 
1184
                     FFetch, ifetch, nfetch);
 
1185
         if (mf > mf0)
 
1186
         {
 
1187
            mf0 = mf;
 
1188
            latB = k;
 
1189
         }
 
1190
      }
 
1191
   }
 
1192
   fprintf(stdout, "BEST for %c%c_%dx%dx%d: mflop=%.2f\n", 
 
1193
           ta, tb, mb, nb, kb, mf0);
 
1194
   fprintf(stdout, 
 
1195
           "pre=%c ta=%c tb=%c nb=%d mu=%d nu=%d ku=%d muladd=%d lat=%d\n",
 
1196
           pre, ta, tb, nb, mu, nu, kuB, muladd, latB);
 
1197
   sprintf(fnam, "res/%cbest%c%c_%dx%dx%d", pre, ta, tb, mb, nb, kb);
 
1198
   fp = fopen(fnam, "w");
 
1199
   assert(fp);
 
1200
   PutInstLogFile(fp,muladd, latB, N, mu, nu, kuB, FFetch, ifetch, nfetch, mf0);
 
1201
   fclose(fp);
 
1202
}
 
1203
 
 
1204
void FindNC0(char ta, char tb, char pre, int nb, int mu, int nu, int ku, 
 
1205
             int muladd, int lat, int FFetch, int ifetch, int nfetch)
 
1206
{
 
1207
   FindNC_0(ta, tb, pre, nb, nb, nb, nb, mu, nu, ku, muladd, lat, FFetch, 
 
1208
            ifetch, nfetch);
 
1209
   FindNC_0(ta, tb, pre, nb, 0, 0, nb, mu, nu, ku, muladd, lat, FFetch,
 
1210
            ifetch, nfetch);
 
1211
   FindNC_0(ta, tb, pre, nb, 0, 0, 0, mu, nu, ku, muladd, lat, FFetch,
 
1212
            ifetch, nfetch);
 
1213
}
 
1214
 
 
1215
double NCcase(char pre, int nb, int mu, int nu, int ku, int ma, int lat,
 
1216
              int ffetch, int ifetch, int nfetch)
 
1217
{
 
1218
   double mf;
 
1219
   int ld=Mmax(1000,nb), cs=1;
 
1220
   char fnam[128];
 
1221
 
 
1222
   if (pre == 'c' || pre == 'z') cs = 2;
 
1223
   do
 
1224
   {
 
1225
      sprintf(fnam, "res/%cNCNB%d_%d", pre, nb, ld);
 
1226
      mf = mmcase(fnam, pre, "JIK", 'N', 'N', nb, nb, nb, nb, nb, nb, 
 
1227
                  -ld, nb, nb, mu, nu, ku, ma, lat, 1, cs, cs, cs, 
 
1228
                  ffetch, ifetch, nfetch);
 
1229
      ld -= 10;
 
1230
   }
 
1231
   while (mf <= 0.0 && ld >= nb);
 
1232
   assert(mf > 0.0);
 
1233
   return(mf);
 
1234
}
 
1235
 
 
1236
int FindNoCopyNB(char pre, int nb, int mu, int nu, int ku0, int muladd, int lat,
 
1237
                 int FFetch, int ifetch, int nfetch)
 
1238
/*
 
1239
 * See if a smaller blocking factor is needed for no-copy
 
1240
 */
 
1241
{
 
1242
   char fnam[128];
 
1243
   int i, ku, nbB=nb, csA=2, csB=2, csC=2;
 
1244
   double mf, mfB, mf0;
 
1245
   const double dmul = 1.02;
 
1246
   FILE *fp;
 
1247
   sprintf(fnam, "res/%cNCNB", pre);
 
1248
   if (!FileExists(fnam))
 
1249
   {
 
1250
      mfB = NCcase(pre, nb, mu, nu, ku0, muladd, lat, FFetch, ifetch, nfetch);
 
1251
      mfB *= dmul;
 
1252
      mf0 = mfB;
 
1253
      for (i=nb-4; i >= 16; i -= 4)
 
1254
      {
 
1255
         ku = Mmin(i, ku0);
 
1256
         mf = NCcase(pre, i, mu, nu, ku, muladd, lat, FFetch, ifetch, nfetch);
 
1257
         if (1.2*mf < mfB) break; /* stop search after 20% slowdown */
 
1258
         if (nb%i == 0) mf *= dmul; /* give modest bonus to mults of nb */
 
1259
         if (mf > mfB)
 
1260
         {
 
1261
            mfB = mf;
 
1262
            nbB = i;
 
1263
         }
 
1264
      }
 
1265
      fp = fopen(fnam, "w");
 
1266
      assert(fp);
 
1267
      fprintf(fp, "%d\n", nbB);
 
1268
   }
 
1269
   else
 
1270
   {
 
1271
      fp = fopen(fnam, "r");
 
1272
      mf0 = mfB = -1.0;
 
1273
      fscanf(fp, "%d\n", &nbB);
 
1274
   }
 
1275
   fclose(fp);
 
1276
   fprintf(stdout, "\n%cNB = %d (%.2f), No copy %cNB = %d (%.2f)\n\n", 
 
1277
           pre, nb, mf0, pre, nbB, mfB);
 
1278
   return(nbB);
 
1279
}
 
1280
 
 
1281
void FindNoCopy(char pre)
 
1282
{
 
1283
   char ln[128];
 
1284
   int nb, mu, nu, ku, muladd, lat, FFetch, ifetch, nfetch, i;
 
1285
   double mf;
 
1286
   FILE *fp;
 
1287
 
 
1288
   sprintf(ln, "res/%cMMRES", pre);
 
1289
   GetInstLogFile(ln, pre, &muladd, &lat, &nb, &mu, &nu, &ku,
 
1290
                  &FFetch, &ifetch, &nfetch, &mf);
 
1291
   sprintf(ln, "res/%cgMMRES", pre);
 
1292
   GetInstLogFile(ln, pre, &muladd, &lat, &i, &mu, &nu, &ku,
 
1293
                  &FFetch, &ifetch, &nfetch, &mf);
 
1294
   nb = FindNoCopyNB(pre, nb, mu, nu, ku, muladd, lat, FFetch, ifetch, nfetch);
 
1295
   ku = Mmin(ku, nb);
 
1296
   FindNC0('N', 'N', pre, nb, mu, nu, ku, muladd, lat, FFetch, ifetch, nfetch);
 
1297
   FindNC0('N', 'T', pre, nb, mu, nu, ku, muladd, lat, FFetch, ifetch, nfetch);
 
1298
   FindNC0('T', 'N', pre, nb, mu, nu, ku, muladd, lat, FFetch, ifetch, nfetch);
 
1299
   FindNC0('T', 'T', pre, nb, mu, nu, ku, muladd, lat, FFetch, ifetch, nfetch);
 
1300
}
 
1301
 
 
1302
void FindCleanupK(char pre, int nb, int mu, int nu, int ku0, int muladd, 
 
1303
                  int lat0, int FFetch, int ifetch, int nfetch)
 
1304
{
 
1305
   char fnam[256];
 
1306
   int genlat, genku, speclat, ku, kumax;
 
1307
   int kb, beta, csC;
 
1308
   double mf, genmf, specmf;
 
1309
   int i, TimeIt=0;
 
1310
   FILE *fp;
 
1311
 
 
1312
   i = 1024 / (mu*nu);
 
1313
   for (kumax=4; kumax*kumax < i; kumax += 4);
 
1314
   if (pre == 'd' || pre == 's') kumax *= 2;
 
1315
   if (kumax >= nb) kumax = nb;
 
1316
   else if (kumax > nb/2) kumax = nb/2;
 
1317
   if (ifetch == -1 || nfetch == -1) { ifetch = mu+nu; nfetch = 1; }
 
1318
   if (pre == 's' || pre == 'd')
 
1319
   {
 
1320
      csC = 1;
 
1321
      beta = 1;
 
1322
   }
 
1323
   else
 
1324
   {
 
1325
      csC = 2;
 
1326
      beta = 8;
 
1327
   }
 
1328
   sprintf(fnam, "res/%cCleanK", pre);
 
1329
   if (FileExists(fnam)) /* file already there */
 
1330
   {
 
1331
      fp = fopen(fnam, "r");
 
1332
      assert(fgets(fnam, 256, fp));
 
1333
      assert(fscanf(fp, " %d", &kb) == 1);
 
1334
      fclose(fp);
 
1335
      if (kb > 0 && kb != nb) TimeIt = 1;
 
1336
      sprintf(fnam, "res/%cCleanK", pre);
 
1337
   }
 
1338
   else TimeIt = 1;
 
1339
   if (TimeIt)
 
1340
   {
 
1341
      fp = fopen(fnam, "w");
 
1342
      assert(fp);
 
1343
      fprintf(fp, " KB  MULADD  LAT  NB  MU  NU  KU  FFTCH  IFTCH  NFTCH  GEN-MFLOP  SPC-MFLOP\n");
 
1344
 
 
1345
      for (kb = nb; kb; kb--)
 
1346
      {
 
1347
         ku = Mmin(ku0, kb);
 
1348
         sprintf(fnam, "res/%cKB_%d", pre, kb);
 
1349
         speclat = GetGoodLat(muladd, kb, mu, nu, ku, lat0);
 
1350
         specmf = mmcase(fnam, pre, "JIK", 'T', 'N', nb, nb, kb, 0, 0, 
 
1351
                         kb, kb, kb, 0, mu, nu, ku, muladd, speclat, beta, 
 
1352
                         1, 1, csC, FFetch, ifetch, nfetch);
 
1353
 
 
1354
         sprintf(fnam, "res/%cKB_0_%d", pre, ku);
 
1355
         genlat = GetGoodLat(muladd, 8000, mu, nu, 1, lat0);
 
1356
         genku = Mmin(kumax, ku);
 
1357
         genmf = mmcase(fnam,pre, "JIK", 'T', 'N', nb, nb, kb, 0, 0, 0, 0, 0, 0,
 
1358
                        mu, nu, genku, muladd, genlat, beta, 1, 1, csC,
 
1359
                        FFetch, ifetch, nfetch);
 
1360
         if (ku != 1)  /* always try ku == 1 for general case */
 
1361
         {
 
1362
            sprintf(fnam, "res/%cKB_0_1", pre);
 
1363
            mf = mmcase(fnam,pre, "JIK", 'T', 'N', nb, nb, kb, 0, 0, 0, 0, 0, 0,
 
1364
                        mu, nu, 1, muladd, genlat, beta, 1, 1, csC,
 
1365
                        FFetch, ifetch, nfetch);
 
1366
            if (mf > genmf) { genku = 1; genmf = mf; }
 
1367
         }
 
1368
         if (1.01 * genmf > specmf) break;
 
1369
         fprintf(fp, 
 
1370
            "%3d  %6d  %3d %3d %3d %3d %3d  %5d  %5d  %5d  %9.2lf  %9.2lf\n",
 
1371
                 kb, muladd, speclat, nb, mu, nu, ku, FFetch, ifetch, nfetch, 
 
1372
                 specmf, genmf);
 
1373
         fflush(fp);
 
1374
      }
 
1375
      fprintf(fp, 
 
1376
              "%3d  %6d  %3d %3d %3d %3d %3d  %5d  %5d  %5d  %9.2lf  %9.2lf\n",
 
1377
              0, muladd, genlat, nb, mu, nu, genku, FFetch, ifetch, nfetch, 
 
1378
              specmf, genmf);
 
1379
      fclose(fp);
 
1380
   }
 
1381
}
 
1382
 
 
1383
FindCleanupMN(char pre, char cwh, int nb, int mu, int nu, int ku,
 
1384
              int muladd, int lat, int FFetch, int ifetch, int nfetch)
 
1385
{
 
1386
   char fnam[128];
 
1387
   int nnb=nb, beta=1, csC=1, TimeIt=0;
 
1388
   int Mb=nb, Nb=nb;
 
1389
   int mu0, nu0, ku0, ma0, lat0, ff0, if0, nf0;
 
1390
   double mf;
 
1391
   FILE *fp;
 
1392
 
 
1393
   if (cwh == 'M') Mb = 0;
 
1394
   else Nb = 0;
 
1395
   if (ifetch == -1 || nfetch == -1) { ifetch = mu+nu; nfetch = 1; }
 
1396
   if (pre == 'c' || pre == 'z')
 
1397
   {
 
1398
      beta = 8;
 
1399
      csC = 2;
 
1400
   }
 
1401
   sprintf(fnam, "res/%cClean%c", pre, cwh);
 
1402
   if (FileExists(fnam))
 
1403
   {
 
1404
      GetInstLogFile(fnam, pre, &ma0, &lat0, &nnb, &mu0, &nu0, &ku0, &ff0,
 
1405
                     &if0, &nf0, &mf);
 
1406
      if (nnb != nb || mf <= 0.0) TimeIt = 1;
 
1407
   }
 
1408
   else TimeIt = 1;
 
1409
   if (TimeIt)
 
1410
   {
 
1411
      mf = mmcase(NULL, pre, "JIK", 'T', 'N', nb, nb, nb, Mb, Nb, nb, nb, nb, 0,
 
1412
                  mu, nu, ku, muladd, lat, beta, 1, 1, csC, 
 
1413
                  FFetch, ifetch, nfetch);
 
1414
      fp = fopen(fnam, "w");
 
1415
      assert(fp);
 
1416
      PutInstLogFile(fp, muladd, lat, nb, mu, nu, ku,
 
1417
                     FFetch, ifetch, nfetch, mf);
 
1418
      fclose(fp);
 
1419
   }
 
1420
}
 
1421
 
 
1422
typedef struct CleanCase CLEANCASE;
 
1423
struct CleanCase
 
1424
{
 
1425
   double mflop;
 
1426
   CLEANCASE *next;
 
1427
   int imult, icase, fixed, nb, nb0, nb1, nb2;
 
1428
};
 
1429
 
 
1430
void PrintCleanCases(CLEANCASE *cp)
 
1431
{
 
1432
   for (; cp; cp = cp->next)
 
1433
   {
 
1434
      fprintf(stdout, 
 
1435
              "imult=%d, icase=%d, fixed=%d, nb=%d, %d,%d,%d, mflop=%.2f\n",
 
1436
              cp->imult, cp->icase, cp->fixed, cp->nb, cp->nb0, cp->nb1,
 
1437
              cp->nb2, cp->mflop);
 
1438
   }
 
1439
   fprintf(stdout, "\n");
 
1440
}
 
1441
CLEANCASE *GetUserCleanup(char pre, int nb, enum CW which)
 
1442
/*
 
1443
 * Read in user clean file
 
1444
 */
 
1445
{
 
1446
   FILE *fp;
 
1447
   CLEANCASE *cp, *cp0;
 
1448
   int i, n;
 
1449
   char cwh[3] = {'M', 'N', 'K'};
 
1450
   char ln[128];
 
1451
 
 
1452
   sprintf(ln, "res/%cuClean%c", pre, cwh[which]);
 
1453
   if (!FileExists(ln))
 
1454
   {
 
1455
      sprintf(ln, "make RunUMMClean pre=%c nb=%d which=%c\n",
 
1456
              pre, nb, tolower(cwh[which]));
 
1457
      assert(system(ln) == 0);
 
1458
      sprintf(ln, "res/%cuClean%c", pre, cwh[which]);
 
1459
   }
 
1460
   fp = fopen(ln, "r");
 
1461
   assert(fp);
 
1462
   assert(fgets(ln, 128, fp));
 
1463
   assert(fgets(ln, 128, fp));
 
1464
   sscanf(ln, " %d", &n);
 
1465
   if (n < 1) return(NULL);
 
1466
   cp0 = cp = malloc(sizeof(CLEANCASE));
 
1467
   assert(cp0);
 
1468
   for (i=0; i < n; i++)
 
1469
   {
 
1470
      assert(fgets(ln, 128, fp));
 
1471
      sscanf(ln, " %d %d %d %d %d %d %d %lf", &cp->imult, &cp->icase,&cp->fixed,
 
1472
             &cp->nb, &cp->nb0, &cp->nb1, &cp->nb2, &cp->mflop);
 
1473
      if (i != n-1)
 
1474
      {
 
1475
         cp->next = malloc(sizeof(CLEANCASE));
 
1476
         assert(cp->next);
 
1477
         cp = cp->next;
 
1478
      }
 
1479
      else cp->next = NULL;
 
1480
   }
 
1481
   fclose(fp);
 
1482
   return(cp0);
 
1483
}
 
1484
 
 
1485
int *GetKBs(char pre, int nb)
 
1486
/*
 
1487
 * returns nb+1 length vector, KB[i] is KB & lda of KB Cleanup; 0 means var
 
1488
 */
 
1489
{
 
1490
   FILE *fp;
 
1491
   int k, *KB;
 
1492
   char ln[128];
 
1493
 
 
1494
   sprintf(ln, "res/%cCleanK", pre);
 
1495
   fp = fopen(ln, "r");
 
1496
   assert(fp);
 
1497
   assert(fgets(ln, 128, fp));  /* skip titles */
 
1498
   KB = malloc((nb+1)*sizeof(int));
 
1499
   assert(KB);
 
1500
   for (k=nb; k; k--)
 
1501
   {
 
1502
      if (fgets(ln, 128, fp)) { assert(sscanf(ln, " %d", KB+k)==1); }
 
1503
      else break;
 
1504
   }
 
1505
   for(; k; k--) KB[k] = 0;
 
1506
   return(KB);
 
1507
}
 
1508
 
 
1509
double RebuttUserKCase(char pre, int nb, int mu, int nu, int ku, int ma,
 
1510
                       int lat, int FF, int iff, int nf, int *KBs, int *NBs)
 
1511
{
 
1512
   double mf, mf0=0.0;
 
1513
   int K, csC, i, ld, iku, ilat;
 
1514
 
 
1515
   if (pre == 'c' || pre == 'z') csC = 2;
 
1516
   else csC = 1;
 
1517
 
 
1518
   for(i=0; i < 3 && NBs[i]; i++)
 
1519
   {
 
1520
      K = NBs[i];
 
1521
      ld = KBs[K];
 
1522
      iku = Mmin(ku, K);
 
1523
      ilat = GetGoodLat(ma, K, mu, nu, 1, lat);
 
1524
      mf = mmclean(pre, CleanK, "JIK", 'T', 'N', nb, nb, K,
 
1525
                   nb, nb, ld, ld, ld, 0,
 
1526
                   mu, nu, iku, ma, ilat, 1, 1, 1, csC, FF, iff, nf);
 
1527
      fprintf(stdout, "   CleanK: %dx%dx%d : %.2f\n", nb, nb, K, mf);
 
1528
      assert(mf > 0.0);
 
1529
      mf0 += mf;
 
1530
   }
 
1531
   return(mf0 / i);
 
1532
}
 
1533
 
 
1534
CLEANCASE *RebuttUserKClean(char pre, int nb, int mu, int nu, int ku,
 
1535
                            int muladd, int lat, int FF, int iff, int nf)
 
1536
{
 
1537
   double gmf, umf;
 
1538
   int NB[3], *KBs;
 
1539
   CLEANCASE *cp0, *cp;
 
1540
 
 
1541
   KBs = GetKBs(pre, nb);
 
1542
 
 
1543
   cp0 = GetUserCleanup(pre, nb, CleanK);
 
1544
   for (cp=cp0; cp; cp = cp->next)
 
1545
   {
 
1546
      NB[0] = cp->nb0; NB[1] = cp->nb1; NB[2] = cp->nb2;
 
1547
      gmf = RebuttUserKCase(pre, nb, mu, nu, ku, muladd, lat, FF, iff, nf,
 
1548
                            KBs, NB);
 
1549
      fprintf(stdout, "   pKBmm_%d: user=%.2f  generated=%.2f\n", 
 
1550
              cp->imult, cp->mflop, gmf);
 
1551
      if (1.02*gmf > cp->mflop) cp->icase = -1;
 
1552
   }
 
1553
   free(KBs);
 
1554
   return(cp0);
 
1555
}
 
1556
 
 
1557
double RebuttUserCase(char pre, int nb, enum CW which, int mu, int nu, int ku,
 
1558
                      int ma, int lat, int FF, int iff, int nf, int *NBs)
 
1559
{
 
1560
   double mf, mf0=0.0;
 
1561
   int NB[3], M[3], NU[3], csC, i, j, NUmax, ilat;
 
1562
   char cwh[3] = {'M', 'N', 'K'};
 
1563
 
 
1564
   if (pre == 'c' || pre == 'z') csC = 2;
 
1565
   else csC = 1;
 
1566
   NB[0] = NB[1] = NB[2] = M[0] = M[1] = M[2] = nb;
 
1567
   NB[which] = 0;
 
1568
   NU[0] = mu; NU[1] = nu; NU[2] = ku;
 
1569
 
 
1570
   NUmax = NU[which];
 
1571
   for(i=0; i < 3 && NBs[i]; i++)
 
1572
   {
 
1573
      j = M[which] = NBs[i];
 
1574
      NU[which] = Mmin(j, NUmax);
 
1575
      ilat = GetGoodLat(ma, M[2], NU[0], NU[1], NU[2], lat);
 
1576
      mf = mmclean(pre, which, "JIK", 'T', 'N', M[0], M[1], M[2],
 
1577
                   NB[0], NB[1], NB[2], nb, nb, 0,
 
1578
                   mu, nu, ku, ma, lat, 1, 1, 1, csC, FF, iff, nf);
 
1579
      fprintf(stdout, "   Clean%c: %dx%dx%d : %.2f\n", cwh[which],
 
1580
              M[0], M[1], M[2], mf);
 
1581
      assert(mf > 0.0);
 
1582
      mf0 += mf;
 
1583
   }
 
1584
   return(mf0 / i);
 
1585
}
 
1586
 
 
1587
CLEANCASE *RebuttUserCases(char pre, int nb, enum CW which,
 
1588
                           int mu, int nu, int ku, int muladd, int lat,
 
1589
                           int FF, int iff, int nf)
 
1590
{
 
1591
   double gmf, umf;
 
1592
   int NB[3];
 
1593
   CLEANCASE *cp0, *cp;
 
1594
   char cwh[3] = {'M', 'N', 'K'};
 
1595
 
 
1596
   if (which == CleanK)
 
1597
      return(RebuttUserKClean(pre, nb, mu, nu, ku, muladd, lat, FF, iff, nf));
 
1598
   cp0 = GetUserCleanup(pre, nb, which);
 
1599
   for (cp=cp0; cp; cp = cp->next)
 
1600
   {
 
1601
      NB[0] = cp->nb0; NB[1] = cp->nb1; NB[2] = cp->nb2;
 
1602
      gmf = RebuttUserCase(pre, nb, which, mu, nu, ku, muladd, lat,
 
1603
                           FF, iff, nf, NB);
 
1604
      fprintf(stdout, "   p%cBmm_%d: user=%.2f  generated=%.2f\n", 
 
1605
              cwh[which], cp->imult, cp->mflop, gmf);
 
1606
      if (1.02*gmf > cp->mflop) cp->icase = -1;
 
1607
   }
 
1608
   return(cp0);
 
1609
}
 
1610
 
 
1611
CLEANCASE *WeedOutLosers(CLEANCASE *cp0)
 
1612
{
 
1613
   CLEANCASE *cp, *cp1;
 
1614
 
 
1615
   while(cp0 && cp0->icase == -1)
 
1616
   {
 
1617
      cp = cp0->next;
 
1618
      free(cp0);
 
1619
      cp0 = cp;
 
1620
   }
 
1621
   if (cp0 && cp0->next)
 
1622
   {
 
1623
      for (cp=cp0; cp->next; cp = cp->next)
 
1624
      {
 
1625
         cp1 = cp->next;
 
1626
         if (cp1->icase == -1)
 
1627
         {
 
1628
            cp->next = cp1->next;
 
1629
            free(cp1);
 
1630
            if (cp->next == NULL) break;
 
1631
         }
 
1632
      }
 
1633
   }
 
1634
   return(cp0);
 
1635
}
 
1636
 
 
1637
void KillAllCleans(CLEANCASE *cp)
 
1638
{
 
1639
   CLEANCASE *cp1;
 
1640
   while (cp)
 
1641
   {
 
1642
      cp1 = cp->next;
 
1643
      free(cp);
 
1644
      cp = cp1;
 
1645
   }
 
1646
}
 
1647
 
 
1648
int NumUserCleans(CLEANCASE *cp)
 
1649
{
 
1650
   int i;
 
1651
   for (i=0; cp; cp = cp->next) if (cp->icase != -1) i++;
 
1652
   return(i);
 
1653
}
 
1654
 
 
1655
void FindUserCleanup(char pre, int nb, enum CW which, int mu, int nu, int ku,
 
1656
                     int ma, int lat, int FF, int iff, int nf)
 
1657
{
 
1658
   CLEANCASE *cp, *cp0;
 
1659
   FILE *fp;
 
1660
   char ln[128];
 
1661
   char cwh[3] = {'M', 'N', 'K'};
 
1662
 
 
1663
   sprintf(ln, "res/%cuClean%cF", pre, cwh[which]);
 
1664
   if (FileExists(ln)) return;/* already done */
 
1665
   cp = RebuttUserCases(pre, nb, which, mu, nu, ku, ma, lat, FF, iff, nf);
 
1666
   cp = WeedOutLosers(cp);
 
1667
   fp = fopen (ln, "w");
 
1668
   assert(fp);
 
1669
   fprintf(fp, "MULT  ICASE  FIXED  NB\n");
 
1670
   fprintf(fp, "%d\n", NumUserCleans(cp));
 
1671
   for(cp0=cp; cp; cp = cp->next)
 
1672
      fprintf(fp, "%4d  %5d  %5d %3d\n", 
 
1673
              cp->imult, cp->icase, cp->fixed, cp->nb);
 
1674
   fclose(fp);
 
1675
   KillAllCleans(cp0);
 
1676
}
 
1677
 
 
1678
void FindAllUserClean(char pre, int nb, int mu, int nu, int ku,
 
1679
                      int ma, int lat, int FF, int iff, int nf)
 
1680
{
 
1681
   FindUserCleanup(pre, nb, CleanM, mu, nu, ku, ma, lat, FF, iff, nf);
 
1682
   FindUserCleanup(pre, nb, CleanN, mu, nu, ku, ma, lat, FF, iff, nf);
 
1683
   FindUserCleanup(pre, nb, CleanK, mu, nu, ku, ma, lat, FF, iff, nf);
 
1684
}
 
1685
 
 
1686
void FindAllUserClean0(char pre)
 
1687
{
 
1688
   double mf;
 
1689
   int nb, mu, nu, ku, muladd, lat, FF, iff, nf;
 
1690
   char ln[64];
 
1691
 
 
1692
   sprintf(ln, "res/%cMMRES", pre);
 
1693
   GetInstLogFile(ln, pre, &muladd, &lat, &nb, &mu, &nu, &ku, &FF,
 
1694
                     &iff, &nf, &mf);
 
1695
   FindAllUserClean(pre, nb, mu, nu, ku, muladd, lat, FF, iff, nf);
 
1696
}
 
1697
 
 
1698
void FindCleanup(char pre, int nb, int mu, int nu, int ku, int muladd, int lat,
 
1699
                 int FFetch, int ifetch, int nfetch)
 
1700
{
 
1701
   FindCleanupMN(pre, 'M', nb, mu, nu, ku, muladd, lat, FFetch, ifetch, nfetch);
 
1702
   FindCleanupMN(pre, 'N', nb, mu, nu, ku, muladd, lat, FFetch, ifetch, nfetch);
 
1703
   FindCleanupK(pre, nb, mu, nu, ku, muladd, lat, FFetch, ifetch, nfetch);
 
1704
   FindAllUserClean(pre, nb, mu, nu, ku, muladd, lat, FFetch, ifetch, nfetch);
 
1705
}
 
1706
void FindAllClean(char pre)
 
1707
{
 
1708
   double mf;
 
1709
   int nb, mu, nu, ku, muladd, lat, FF, iff, nf;
 
1710
   char ln[64];
 
1711
 
 
1712
   sprintf(ln, "res/%cMMRES", pre);
 
1713
   fprintf(stderr, "\n\nSTARTING CLEANUP SEARCH\n\n");
 
1714
   GetInstLogFile(ln, pre, &muladd, &lat, &nb, &mu, &nu, &ku, &FF,
 
1715
                     &iff, &nf, &mf);
 
1716
   FindCleanup(pre, nb, mu, nu, ku, muladd, lat, FF, iff, nf);
 
1717
   fprintf(stderr, "\n\nDONE CLEANUP SEARCH\n\n");
 
1718
}
 
1719
 
 
1720
int GetNumRegs0(char pre, int muladd, int nb, int lat, 
 
1721
                int nr0, int nrN, int incN)
 
1722
{
 
1723
   int n, nr, i, imax, nu, mu;
 
1724
   double *rates, mf, mmf=0.0;
 
1725
 
 
1726
   n = 0;
 
1727
   i = nr0;
 
1728
   while (i <= nrN)
 
1729
   {
 
1730
      if (incN == -2) i <<= 1;
 
1731
      else i += incN;
 
1732
      n++;
 
1733
   }
 
1734
   rates = malloc(n * sizeof(double));
 
1735
   nr = nr0;
 
1736
   for (i=0; i < n; i++)
 
1737
   {
 
1738
      FindMUNU(muladd, lat, nr, &mu, &nu);
 
1739
      mf = rates[i] = mms_case(pre, muladd, nb, mu, nu, nb, lat);
 
1740
      if (1.09*mf > mmf)
 
1741
      {
 
1742
         if (mf > mmf) mmf = mf;
 
1743
         imax = i;
 
1744
      }
 
1745
      if (incN == -2) nr <<= 1;
 
1746
      else nr += incN;
 
1747
   }
 
1748
   if (imax < n)
 
1749
   {
 
1750
      for (i=imax+1; i < n && 1.10*rates[i] < mmf; i++);
 
1751
      if (i != n) i = -1;
 
1752
      else if (incN == -2) i = (nr0 << imax);
 
1753
      else i = nr0 + imax*incN;
 
1754
   }
 
1755
   else i = nrN;
 
1756
   free(rates);
 
1757
   return(i);
 
1758
}
 
1759
 
 
1760
int RefineNumRegs(char pre, int muladd, int nb, int lat, int nr0, int nrN)
 
1761
/*
 
1762
 * recursively halves gap until true number is found
 
1763
 */
 
1764
{
 
1765
   int i, nr;
 
1766
 
 
1767
   i = (nrN - nr0) / 2;
 
1768
   if (i < 1) return(nr0);
 
1769
   nr = GetNumRegs0(pre, muladd, nb, lat, nr0, nr0+i, i);
 
1770
   if (nr != nr0) /* positive or no difference in two points, so go larger */
 
1771
      nr0 += i;
 
1772
   else          /* difference, point is between */
 
1773
      nrN = nr0 + i;
 
1774
   return(RefineNumRegs(pre, muladd, nb, lat, nr0, nrN));
 
1775
}
 
1776
 
 
1777
int GetNumRegs00(char pre, int muladd, int nb, int lat, int maxnr)
 
1778
{
 
1779
   int nr, i;
 
1780
 
 
1781
   fprintf(stderr, "\n\nFINDING ROUGHLY HOW MANY REGISTERS TO USE:\n\n");
 
1782
 
 
1783
   nr = GetNumRegs0(pre, muladd, nb, lat, 4, maxnr, -2);
 
1784
/*
 
1785
 * Refine number of regs
 
1786
 */
 
1787
   if (nr != -1) i = RefineNumRegs(pre, muladd, nb, lat, nr, nr<<1);
 
1788
   else i = nr;
 
1789
   fprintf(stderr, "\n\nAPPROXIMATE NUMBER OF USABLE REGISTERS=%d\n\n", i);
 
1790
   return(i);
 
1791
}
 
1792
 
 
1793
int GetNumRegs(char pre, int MaxL1, int maxnreg)
 
1794
{
 
1795
   FILE *fp;
 
1796
   int nreg, muladd, lat;
 
1797
   char nam[32];
 
1798
   void GetMulAdd(char pre, int *MULADD, int *lat);
 
1799
 
 
1800
   if (pre == 'z') pre = 'd';
 
1801
   else if (pre == 'c') pre = 's';
 
1802
 
 
1803
   sprintf(nam, "res/%cnreg", pre);
 
1804
   if (!FileExists(nam))
 
1805
   {
 
1806
      GetMulAdd(pre, &muladd, &lat);
 
1807
      nreg = GetNumRegs00(pre, muladd, GetSafeNB(pre, MaxL1), lat, maxnreg);
 
1808
      fp = fopen(nam, "w");
 
1809
      fprintf(fp, "%d\n", nreg);
 
1810
   }
 
1811
   else
 
1812
   {
 
1813
      fp = fopen(nam, "r");
 
1814
      fscanf(fp, " %d", &nreg);
 
1815
   }
 
1816
   fclose(fp);
 
1817
   fprintf(stdout, "mmnreg = %d\n", nreg);
 
1818
   return(nreg);
 
1819
}
 
1820
 
 
1821
void RunTimes(char pre)
 
1822
{
 
1823
   const char TR[2] = {'N', 'T'};
 
1824
   char fnam[128], fnam2[128], ln[128];
 
1825
   const int COMPLEX = (pre == 'c' || pre == 'z');
 
1826
   int csC = (COMPLEX ? 2 : 1);
 
1827
   int NB, muladd, lat, nb, mu, nu, ku, ffetch, ifetch, nfetch, ia, ib;
 
1828
   int uma, ulat, unb=0, umu, unu, uku, uff, uif, unf;
 
1829
   int maxreg;
 
1830
   double mf, umf;
 
1831
   FILE *fp;
 
1832
 
 
1833
   fprintf(stderr, "\n\nStart RunTimes\n");
 
1834
   sprintf(fnam, "res/%cgMMRES", pre);
 
1835
   fp = fopen(fnam, "r");
 
1836
   assert(fp);
 
1837
   fgets(ln, 128, fp);
 
1838
   GetInstLogLine(fp, &muladd, &lat, &nb, &mu, &nu, &ku, &ffetch,
 
1839
                  &ifetch, &nfetch, &mf);
 
1840
   fclose(fp);
 
1841
   if (mf < 0.0) /* need to retime */
 
1842
   {
 
1843
      sprintf(ln, "make RunUMMSearch pre=%c nb=-1\n", pre);
 
1844
      assert(system(ln) == 0);
 
1845
      mf = mmcase(NULL, pre, "JIK", 'T', 'N', nb, nb, nb, nb, nb, nb, 
 
1846
                  nb, nb, 0, mu, nu, ku, muladd, lat, 1, 1, 1, csC, 
 
1847
                  ffetch, ifetch, nfetch);
 
1848
      PutInstLogFile1(fnam, pre, muladd, lat, nb, mu, nu, ku, 
 
1849
                      ffetch, ifetch, nfetch, mf);
 
1850
      sprintf(fnam, "res/%cMMRES", pre);
 
1851
      if (!FileExists(fnam))
 
1852
      {
 
1853
         sprintf(ln, "make res/%cMMRES pre=%c\n", pre, pre);
 
1854
         assert(system(ln) == 0);
 
1855
      }
 
1856
      else
 
1857
      {
 
1858
         GetInstLogFile(fnam, pre, &muladd, &lat, &nb, &mu, &nu, &ku, &ffetch,
 
1859
                        &ifetch, &nfetch, &mf);
 
1860
         mf = mmcase(NULL, pre, "JIK", 'T', 'N', nb, nb, nb, nb, nb, nb, 
 
1861
                     nb, nb, 0, mu, nu, ku, muladd, lat, 1, 1, 1, csC, 
 
1862
                     ffetch, ifetch, nfetch);
 
1863
         CreateFinalSumm(pre, muladd, lat, nb, mu, nu, ku, ffetch, ifetch,
 
1864
                         nfetch, mf);
 
1865
      }
 
1866
   }
 
1867
   sprintf(fnam, "res/%cNCNB", pre);
 
1868
   if (!FileExists(fnam)) return;
 
1869
   fp = fopen(fnam, "r");
 
1870
   assert(fp);
 
1871
   assert(fscanf(fp, " %d", &NB) == 1);
 
1872
   fclose(fp);
 
1873
 
 
1874
   for (ia=0; ia < 2; ia++)
 
1875
   {
 
1876
      for (ib=0; ib < 2; ib++)
 
1877
      {
 
1878
         sprintf(fnam, "res/%cbest%c%c_%dx%dx%d", pre, TR[ia], TR[ib], 
 
1879
                 NB, NB, NB);
 
1880
         if (FileExists(fnam))
 
1881
         {
 
1882
            GetInstLogFile(fnam, pre, &muladd, &lat, &nb, &mu, &nu, &ku,
 
1883
                           &ffetch, &ifetch, &nfetch, &mf);
 
1884
            if (mf < 0.0) /* need to retime */
 
1885
            {
 
1886
               mf = mmcase(NULL, pre, "JIK", TR[ia], TR[ib], nb, nb, nb, 
 
1887
                           nb, nb, nb, 0, 0, 0, mu, nu, ku, muladd, lat, 1, 
 
1888
                           1, 1, csC, ffetch, ifetch, nfetch);
 
1889
               PutInstLogFile1(fnam, pre, muladd, lat, nb, mu, nu, ku,
 
1890
                              ffetch, ifetch, nfetch, mf);
 
1891
            }
 
1892
         }
 
1893
         sprintf(fnam, "res/%cbest%c%c_%dx%dx%d", pre, TR[ia], TR[ib], 
 
1894
                 0, 0, NB);
 
1895
         if (FileExists(fnam))
 
1896
         {
 
1897
            GetInstLogFile(fnam, pre, &muladd, &lat, &nb, &mu, &nu, &ku,
 
1898
                           &ffetch, &ifetch, &nfetch, &mf);
 
1899
            if (mf < 0.0) /* need to retime */
 
1900
            {
 
1901
               mf = mmcase(NULL, pre, "JIK", TR[ia], TR[ib], nb, nb, nb, 
 
1902
                           0, 0, nb, 0, 0, 0, mu, nu, ku, muladd, lat, 1, 
 
1903
                           1, 1, csC, ffetch, ifetch, nfetch);
 
1904
               PutInstLogFile1(fnam, pre, muladd, lat, nb, mu, nu, ku,
 
1905
                              ffetch, ifetch, nfetch, mf);
 
1906
            }
 
1907
         }
 
1908
         sprintf(fnam, "res/%cbest%c%c_%dx%dx%d", pre, TR[ia], TR[ib], 
 
1909
                 0, 0, 0);
 
1910
         if (FileExists(fnam))
 
1911
         {
 
1912
            GetInstLogFile(fnam, pre, &muladd, &lat, &nb, &mu, &nu, &ku,
 
1913
                           &ffetch, &ifetch, &nfetch, &mf);
 
1914
            if (mf < 0.0) /* need to retime */
 
1915
            {
 
1916
               mf = mmcase(NULL, pre, "JIK", TR[ia], TR[ib], nb, nb, nb, 
 
1917
                           0, 0, 0, 0, 0, 0, mu, nu, ku, muladd, lat, 1, 
 
1918
                           1, 1, csC, ffetch, ifetch, nfetch);
 
1919
               PutInstLogFile1(fnam, pre, muladd, lat, nb, mu, nu, ku,
 
1920
                              ffetch, ifetch, nfetch, mf);
 
1921
            }
 
1922
         }
 
1923
      }
 
1924
   }
 
1925
   fprintf(stderr, "\nDone  RunTimes\n\n");
 
1926
}
 
1927
 
 
1928
void cmmsearch(char pre, int MULADD, int Fku, int nNBs, int *NBs, int nreg,
 
1929
               int LAT, int Fnb)
 
1930
/*
 
1931
 * With all other parameters set by real search, find good complex NB
 
1932
 */
 
1933
{
 
1934
   char *typ, ln[64], upre;
 
1935
   int i, k, mnb=0, muladd, lat, nb, mu, nu, ku, ffetch, ifetch, nfetch;
 
1936
   int KUisNB, NO1D;
 
1937
   double mf, mmf=0.0, umf;
 
1938
   FILE *fp;
 
1939
 
 
1940
   if (pre == 'c') upre = 's';
 
1941
   else upre = 'd';
 
1942
 
 
1943
   sprintf(ln, "res/%cMMRES", pre);
 
1944
   if (FileExists(ln)) /* already have result */
 
1945
   {
 
1946
      GetInstLogFile(ln, pre, &muladd, &lat, &nb, &mu, &nu, &ku, &ffetch,
 
1947
                     &ifetch, &nfetch, &mf);
 
1948
      if (mf <= 0.0)
 
1949
      {
 
1950
         mf = mmcase(NULL, pre, "JIK", 'T', 'N', nb, nb, nb, nb, nb, nb,
 
1951
                     nb, nb, 0, mu, nu, ku, muladd, lat, 1, 1, 1, 2,
 
1952
                     ffetch, ifetch, nfetch);
 
1953
         gmmsearch(upre, muladd, Fku, nNBs, NBs, nreg, lat, Fnb);
 
1954
         nb = CheckUser(pre, 1.02, mf, nb, NULL);
 
1955
         CreateFinalSumm(pre, muladd, lat, nb, mu, nu, ku, ffetch, ifetch, 
 
1956
                         nfetch, mf);
 
1957
      }
 
1958
      sprintf(ln, "res/%cNB", pre);
 
1959
      fp = fopen(ln, "w");
 
1960
      fprintf(fp, "%d\n%d\n", 1, nb);
 
1961
      fclose(fp);
 
1962
      return;
 
1963
   }
 
1964
   gmmsearch(upre, MULADD, Fku, nNBs, NBs, nreg, LAT, Fnb);
 
1965
   sprintf(ln, "res/%cgMMRES", upre);
 
1966
   GetInstLogFile(ln, upre, &muladd, &lat, &nb, &mu, &nu, &ku, &ffetch,
 
1967
                  &ifetch, &nfetch, &mf);
 
1968
   KUisNB = (nb <= ku);
 
1969
 
 
1970
   for (i=0; i < nNBs; i++)
 
1971
   {
 
1972
      if (KUisNB) k = NBs[i];
 
1973
      else k = Mmin(ku, NBs[i]);
 
1974
      mf = mms_case(pre, muladd, NBs[i], mu, nu, k, lat);
 
1975
      if (mf > mmf)
 
1976
      {
 
1977
         mmf = mf;
 
1978
         mnb = NBs[i];
 
1979
      }
 
1980
   }
 
1981
   if (KUisNB) ku = mnb;
 
1982
   else ku = Mmin(ku, mnb);
 
1983
   sprintf(ln, "res/%cgMMRES", pre);
 
1984
   PutInstLogFile1(ln, pre, muladd, lat, mnb, mu, nu, ku, 
 
1985
                   ffetch, ifetch, nfetch, mmf);
 
1986
 
 
1987
   nb = CheckUser(pre, 1.02, mmf, mnb, &umf);
 
1988
   if (nb != mnb)
 
1989
   {
 
1990
      if (ku == mnb) ku = nb;
 
1991
      mnb = nb;
 
1992
      if (nb % mu || nb % nu)
 
1993
      {
 
1994
         NO1D = GetNO1D(upre, nreg, nb, MULADD, LAT);
 
1995
         searchmu_nu(upre, nb, nreg, Fku, MULADD, LAT, NO1D,
 
1996
                     &mmf, &nb, &mu, &nu, &ku, &lat);
 
1997
      }
 
1998
      FindKU(upre, muladd, LAT, nb, mu, nu, &mmf, &ku, &lat);
 
1999
      FindLAT(upre, MAXLAT, nb, muladd, mu, nu, ku, &mmf, &lat);
 
2000
      FindFetch('T', 'N', upre, nb, nb, nb, mu, nu, ku, muladd, lat,
 
2001
                &ffetch, &ifetch, &nfetch);
 
2002
   }
 
2003
/*
 
2004
 * Save NB we've found 
 
2005
 */
 
2006
   sprintf(ln, "res/%cNB", pre);
 
2007
   fp = fopen(ln, "w");
 
2008
   fprintf(fp, "%d\n%d\n", 1, mnb);
 
2009
   fclose(fp);
 
2010
   CreateFinalSumm(pre, muladd, lat, mnb, mu, nu, ku,
 
2011
                   ffetch, ifetch, nfetch, mf);
 
2012
}
 
2013
void GetMulAdd(char pre, int *MULADD, int *lat)
 
2014
{
 
2015
   char nam[64], ln[128];
 
2016
   FILE *fp;
 
2017
 
 
2018
   sprintf(nam, "res/%cMULADD", pre);
 
2019
   if (!FileExists(nam))
 
2020
   {
 
2021
      sprintf(ln, "make RunMulAdd pre=%c maxlat=%d mflop=%d\n", pre, 6, 200);
 
2022
      assert(system(ln) == 0);
 
2023
   }
 
2024
   fp = fopen(nam, "r");
 
2025
   assert(fp != NULL);
 
2026
   fscanf(fp, "%d", MULADD);
 
2027
   fscanf(fp, "%d", lat);
 
2028
   fclose(fp);
 
2029
}
 
2030
 
 
2031
int GetNumRegsMM(char pre, int MaxL1Size, int MAX_NREG)
 
2032
{
 
2033
   int nreg;
 
2034
   nreg = GetNumRegs(pre, MaxL1Size, MAX_NREG);
 
2035
   if (nreg == -1)
 
2036
   {
 
2037
      fprintf(stderr, 
 
2038
         "\nUNABLE TO FIND NUMBER OF REGISTERS, ASSUMMING 32.\n\n");
 
2039
      nreg = 32;
 
2040
   }
 
2041
   if (nreg > 128)
 
2042
   {
 
2043
      fprintf(stderr, "FOUND NUMBER OF REGISTERS TO BE %d; THIS WOULD TAKE TOO LONG TO SEARCH, SO SETTING TO 128.\n", nreg);
 
2044
      nreg = 128;
 
2045
   }
 
2046
   if (nreg < 8)
 
2047
   {
 
2048
      fprintf(stderr, 
 
2049
              "FOUND # OF REGISTERS TO BE %d; TRYING 8 FOR SAFETY.\n", nreg);
 
2050
      nreg = 8;
 
2051
   }
 
2052
   else if (nreg < 16)
 
2053
   {
 
2054
      fprintf(stderr, 
 
2055
              "FOUND # OF REGISTERS TO BE %d; TRYING 16 FOR SAFETY.\n", nreg);
 
2056
      nreg = 16;
 
2057
   }
 
2058
   return(nreg);
 
2059
}
 
2060
 
 
2061
void GetMMRES(char pre, int nreg, int MaxL1Size, int ForceLat)
 
2062
{
 
2063
   char upre;
 
2064
   char ln[128];
 
2065
   int i, nNBs, muladd, lat;
 
2066
   int *NBs;
 
2067
   FILE *fp;
 
2068
 
 
2069
   if (pre == 'c') upre = 's';
 
2070
   else if (pre == 'z') upre = 'd';
 
2071
   else upre = pre;
 
2072
 
 
2073
   sprintf(ln, "res/%cNB", pre);
 
2074
   if (!FileExists(ln)) findNBs(upre, ln, MaxL1Size);
 
2075
   assert( (fp = fopen(ln, "r")) != NULL );
 
2076
   fscanf(fp, "%d", &nNBs);
 
2077
   fprintf(stdout, "\nNB's to try: ");
 
2078
   NBs = malloc(nNBs*sizeof(int));
 
2079
   for (i=0; i != nNBs; i++)
 
2080
   {
 
2081
      fscanf(fp, "%d", NBs+i);
 
2082
      fprintf(stdout, "%d   ",NBs[i]);
 
2083
   }
 
2084
   fprintf(stdout, "\n\n");
 
2085
 
 
2086
   GetMulAdd(upre, &muladd, &lat);
 
2087
   if (ForceLat != -1) lat = ForceLat;
 
2088
 
 
2089
 
 
2090
   if (pre == 'c' || pre == 'z')
 
2091
      cmmsearch(pre, muladd, 0, nNBs, NBs, nreg, lat, 0);
 
2092
   else mmsearch(pre, muladd, 0, nNBs, NBs, nreg, lat, 0);
 
2093
   free(NBs);
 
2094
}
 
2095
#ifndef ATL_MAXNREG
 
2096
   #define ATL_MAXNREG 64
 
2097
#endif
 
2098
main(int nargs, char *args[])
 
2099
{
 
2100
   char prec, upre, lang;
 
2101
   int MULADD, MaxL1Size, ForceLat, i, nreg, ROUT, FRC;
 
2102
   int muladd, lat, nb, mu, nu, ku, ffetch, ifetch, nfetch;
 
2103
   int unb, icase;
 
2104
   double mf, umf;
 
2105
   FILE *fp;
 
2106
   char ln[128], auth[65];
 
2107
 
 
2108
   GetSettings(nargs, args, &prec, &lang, &ku, &ForceLat, &FRC, &nreg, 
 
2109
               &MaxL1Size, &ROUT);
 
2110
   assert(FRC == 0 && ku == 0); /* obsolete flags */
 
2111
   LANG = lang;
 
2112
 
 
2113
   if (prec == 'z') upre = 'd';
 
2114
   else if (prec == 'c') upre = 's';
 
2115
   else upre = prec;
 
2116
   if (ROUT == -3)
 
2117
   {
 
2118
      FindAllClean(prec);
 
2119
      exit(0);
 
2120
   }
 
2121
   else if (ROUT == -4)
 
2122
   {
 
2123
      FindAllUserClean0(prec);
 
2124
      exit(0);
 
2125
   }
 
2126
   else if (ROUT == -5) /* produce ATL_mmnreg for sysinfo */
 
2127
   {
 
2128
      GetNumRegs(prec, MaxL1Size, ATL_MAXNREG);
 
2129
      exit(0);
 
2130
   }
 
2131
   fprintf(stderr, "Precision='%c', FORCE=%d, LAT=%d, nreg=%d, MaxL1=%d\n",
 
2132
           prec, FRC, ForceLat, nreg, MaxL1Size);
 
2133
 
 
2134
   if (nreg == -1) nreg = GetNumRegsMM(upre, MaxL1Size, ATL_MAXNREG);
 
2135
   GetMMRES(prec, nreg, MaxL1Size, ForceLat);
 
2136
   FindNoCopy(prec);
 
2137
   FindAllClean(prec);
 
2138
 
 
2139
   sprintf(ln, "res/%cMMRES", prec);
 
2140
   fp = fopen(ln, "r");
 
2141
   assert(fp);
 
2142
   assert( fgets(ln, 128, fp) != NULL );
 
2143
   GetInstLogLine(fp, &muladd, &lat, &nb, &mu, &nu, &ku, &ffetch,
 
2144
                     &ifetch, &nfetch, &mf);
 
2145
   assert( fgets(ln, 128, fp) != NULL );
 
2146
   assert(fscanf(fp, " %d %d %lf \"%[^\"]\" \"%[^\"]", &icase, &unb, &umf, 
 
2147
                 ln, auth) == 5);
 
2148
   fclose(fp);
 
2149
   if (mf >= umf)
 
2150
   {
 
2151
      fprintf(stdout, "\n\nFor this run, the best parameters found were MULADD=%d, lat=%d, NB=%d, MU=%d, NU=%d, KU=%d\n",
 
2152
              muladd, lat, nb, mu, nu, ku);
 
2153
   }
 
2154
   else
 
2155
   {
 
2156
       mf = umf;
 
2157
       fprintf(stdout, 
 
2158
               "\n\nFor this run, the best case found was NB=%d user case %d\n",
 
2159
               unb, icase);
 
2160
       fprintf(stdout, "written by %s.\n", auth);
 
2161
   }
 
2162
   fprintf(stdout, "This gave a performance = %f MFLOP.\n", mf);
 
2163
   fprintf(stdout, 
 
2164
"The necessary files have been created.  If you are happy with\n");
 
2165
   fprintf(stdout, 
 
2166
"the above mflops for your system, type 'make %cinstall'.\n", prec);
 
2167
   fprintf(stdout, 
 
2168
"Otherwise, try the xmmsearch with different parameters, or hand\n");
 
2169
   fprintf(stdout, "tweak the code.\n");
 
2170
   exit(0);
 
2171
}