gemvtune.c
来自「基于Blas CLapck的.用过的人知道是干啥的」· C语言 代码 · 共 438 行
C
438 行
/* * Automatically Tuned Linear Algebra Software v3.8.0 * (C) Copyright 1999 R. Clint Whaley * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions, and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the ATLAS group or the names of its contributers may * not be used to endorse or promote products derived from this * software without specific written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ATLAS GROUP OR ITS CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */#include "atlas_misc.h"#include "atlas_lvl2.h"#include "atlas_fopen.h"int FAx=0, MAx=0, FAy=0, MAy=0, FAa=0, MAa=0;#include <stdio.h>#include <stdlib.h>#include <assert.h>struct FA_allocs{ void *mem, *memA; struct FA_allocs *next;} *allocQ=NULL;struct FA_allocs *NewAlloc(size_t size, struct FA_allocs *next, int align, int misalign)/* * Allocates size allocation that is aligned to [align], but not aligned * to [misalign]. Therefore, misalign > align. Align must minimally be sizeof * while misalign may be 0 if we don't need to avoid a particular alignment. */{ void *vp; char *cp; struct FA_allocs *ap; int n, i; const int malign = align >= misalign ? align : misalign; n = size + align + malign; i = (n >> 3)<<3; if (n != i) n += n - i; cp = malloc(n + sizeof(struct FA_allocs)); assert(cp); ap = (struct FA_allocs *) (cp + n); ap->mem = cp;/* * Align to min alignment */ ap->memA = align ? (void*) ((((size_t) cp)/align)*align + align) : cp;/* * Misalign to misalign */ if (misalign) { if (((size_t)ap->memA)%misalign == 0) ap->memA = ((char*)ap->memA) + align; } ap->next = next; return(ap);}/* * no-align malloc free retaining system default behavior */void *NA_malloc(size_t size){ return(malloc(size));}void *NA_calloc(size_t n, size_t size){ return(calloc(n, size));}void NA_free(void *ptr){ free(ptr);}/* * malloc/free pair that aligns data to align, but not to misalign */void *FA_malloc(size_t size, int align, int misalign){ if ((!misalign && align <= 8) || !size) return(malloc(size)); else { allocQ = NewAlloc(size, allocQ, align, misalign); return(allocQ->memA); }}void *FA_calloc(size_t n, size_t size, int align, int misalign){ char *cp; int *ip; double *dp; size_t i; size_t tsize; tsize = n * size; cp = FA_malloc(tsize, align, misalign); if (size == sizeof(int)) for (ip=(int*)cp,i=0; i < n; i++) ip[i] = 0; else if (size == sizeof(double)) for (dp=(double*)cp,i=0; i < n; i++) dp[i] = 0.0; else for (i=0; i < tsize; i++) cp[i] = 0; return(cp);}void FA_free(void *ptr, int align, int misalign)/* * Part of malloc/free pair that aligns data to FALIGN */{ struct FA_allocs *ap, *prev; if (ptr) { if ((!misalign && align <= 8)) free(ptr); else { for (ap=allocQ; ap && ap->memA != ptr; ap = ap->next) prev = ap; if (!ap) { fprintf(stderr, "Couldn't find mem=%ld\nmemQ=\n", ptr); for (ap=allocQ; ap; ap = ap->next) fprintf(stderr, " %ld, %ld\n", ap->memA, ap->mem); } assert(ap); if (ap == allocQ) allocQ = allocQ->next; else prev->next = ap->next; free(ap->mem); } }}#define ATL_MVNoBlock(iflag_) ( ((iflag_) | 32) == (iflag_) )double time00();double gemvcase(const int MFLOP, const enum ATLAS_TRANS TA, const int l2size, const int M, const int N, const SCALAR alpha, const int lda, const SCALAR beta){ unsigned long reps; int i, lx, ly, la; #ifdef TREAL const double flops = 2.0 * M * N; #else const double flops = 8.0 * M * N; #endif double ttest, mftest, t0; const int aincY=1, aincX=1, incY=1, incX=1; const int inca = (TA == AtlasNoTrans) ? lda * (N SHIFT) : lda * (M SHIFT); const int incx = N*incX SHIFT, incy = M*incY SHIFT; TYPE *a, *A, *stA, *A0, *x, *X, *X0, *stX, *y, *Y, *Y0, *stY; #ifdef TREAL const TYPE nbeta = -beta; TYPE bet = beta; #else const TYPE *bet = beta; TYPE nbeta[2]; nbeta[0] = -beta[0]; nbeta[1] = -beta[1]; #endif i = (ATL_DivBySize(l2size)+N-1)/N; if (i < 1) i = 1; lx = i * N * aincX; X0 = X = x = FA_malloc(ATL_MulBySize(lx), FAx, MAx); if (x == NULL) return(-1); i = (ATL_DivBySize(l2size)+M-1)/M; if (i < 1) i = 1; ly = i * M * aincY; Y0 = Y = y = FA_malloc(ATL_MulBySize(ly), FAy, MAy); if (y == NULL) { FA_free(x, FAx, MAx); return(-1); } i = (ATL_DivBySize(l2size)+M*N)/(M*N); la = i * inca; A0 = A = a = FA_malloc(ATL_MulBySize(la), FAa, MAa); if (a == NULL) { FA_free(x, FAx, MAx); FA_free(y, FAy, MAy); return(-1); } if (incX < 1) { stX = x; x = X = x + (lx SHIFT); } else stX = x + (lx SHIFT); if (incY < 1) { stY = y; y = Y = y + (ly SHIFT); } else stY = y + (ly SHIFT); stA = a + (la SHIFT); reps = (MFLOP * 1000000.0) / flops; if (reps < 1) reps = 1; Mjoin(PATL,gegen)(ly, 1, Y0, ly, M*incY); Mjoin(PATL,gegen)(lx, 1, X0, lx, N*incY+127*50+77); Mjoin(PATL,gegen)(la, 1, A0, la, N*M+513*7+90); t0 = time00(); for (i=reps; i; i--) { #ifdef SYMM_ Mjoin(PATL,symv)(AtlasLower, N, alpha, a, lda, x, incX, beta, y, incY); #else Mjoin(PATL,gemv)(TA, M, N, alpha, a, lda, x, incX, beta, y, incY); #endif x += incx; y += incy; a += inca; if (x == stX) x = X; if (y == stY) { y = Y; if (bet == beta) bet = nbeta; else bet = beta; } if (a == stA) a = A; } ttest = time00() - t0; if (ttest > 0.0) mftest = (reps * flops) / (1000000.0 * ttest); else mftest = 0.0; FA_free(A0, FAa, MAa); FA_free(X0, FAx, MAx); FA_free(Y0, FAy, MAy); return(mftest);}void PrintUsage(char *nam){ fprintf(stderr, "USAGE: %s -C <case #> -l <l1mul> -F <mflop> -A <t/n> -m <M> -n <N> -L <lda> -b <beta> -o <output filename> -2 <flush size (kbytes)>\n\n", nam); exit(-1);}void GetFlags(int nargs, char **args, char *pre, int *l2size, int *MFLOP, char *cta, int *M, int *N, TYPE *alpha, int *lda, TYPE *beta, char *outnam){ char ctmp, ch; int i, k, cas=0, iflag=0; int l1mul=75; *cta = 'N'; outnam[0] = '\0'; *l2size = L2SIZE; #if defined(DREAL) *pre = 'd'; #elif defined(SREAL) *pre = 's'; #elif defined(SCPLX) *pre = 'c'; #elif defined(DCPLX) *pre = 'z'; #endif #ifdef ATL_nkflop *MFLOP = (ATL_nkflop) / 1000.0; if (*MFLOP < 1) *MFLOP = 1; #else *MFLOP = 100; #endif *lda = *M = *N = 1000; *beta = *alpha = ATL_rone; #ifdef TCPLX beta[1] = alpha[1] = ATL_rzero; #endif for (i=1; i < nargs; i++) { if (args[i][0] != '-') PrintUsage(args[0]); switch(args[i][1]) { case 'C': /* case */ cas = atoi(args[++i]); break; case 'F': /* mflops */ ch = args[i][2]; k = atoi(args[++i]); if (ch == 'a') { if (k < 0) MAa = -k; else FAa = k; } else if (ch == 'y') { if (k < 0) MAy = -k; else FAy = k; } else if (ch == 'x') { if (k < 0) MAx = -k; else FAx = k; } else *MFLOP = k; break; case '2': *l2size = atoi(args[++i])*1024; break; case 'f': /* iflag */ iflag = atoi(args[++i]); break; case 'L': *lda = atoi(args[++i]); break; case 'l': /* mflops */ l1mul = atoi(args[++i]); break; case 'A': /* trans */ i++; ctmp = toupper(args[i][0]); if (ctmp == 'n') ctmp = 'N'; else if (ctmp == 't') ctmp = 'T'; else if (ctmp != 'N' && ctmp != 'T') PrintUsage(args[0]); *cta = ctmp; break; case 'm': *M = atoi(args[++i]); break; case 'n': *N = atoi(args[++i]); break; case 'b': *beta = atof(args[++i]); #ifdef TCPLX beta[1] = atof(args[++i]); #endif break; case 'o': strcpy(outnam, args[++i]); break; default: PrintUsage(args[0]); } } #ifdef SYMM_ if (*M > *N) *N = *M; else if (*N > *M) *M = *N; #endif if (*cta == 'N') { ATL_assert(*lda >= Mmax(1,*M)); } else { ATL_assert(*lda >= Mmax(1,*N)); } if (outnam[0] == '\0') { #ifdef SYMM_ if (ATL_MVNoBlock(iflag)) sprintf(outnam, "res/%csymv%c_%d_0", *pre,*cta, cas); else sprintf(outnam, "res/%csymv%c_%d_%d", *pre,*cta, cas, l1mul); #else if (ATL_MVNoBlock(iflag)) sprintf(outnam, "res/%cgemv%c_%d_0", *pre,*cta, cas); else sprintf(outnam, "res/%cgemv%c_%d_%d", *pre,*cta, cas, l1mul); #endif }}main(int nargs, char **args){ char pre, fnam[128], cta; enum ATLAS_TRANS TA; int MFLOP, M, N, lda, i, l2size; double mf, mfs[3]; #ifdef TREAL TYPE alpha, beta; #else TYPE alpha[2], beta[2]; #endif FILE *fp; GetFlags(nargs, args, &pre, &l2size, &MFLOP, &cta, &M, &N, SADD alpha, &lda, SADD beta, fnam); if (cta == 'N' || cta == 'n') TA = AtlasNoTrans; else TA = AtlasTrans; if (!FileExists(fnam)) { fp = fopen(fnam, "w"); ATL_assert(fp); for (i=0; i < 3; i++) { mf = gemvcase(MFLOP, TA, l2size, M, N, alpha, lda, beta); fprintf(stdout, " %s : %f MFLOPS\n", fnam, mf); fprintf(fp, "%lf\n", mf); mfs[i] = mf; } } else { fp = fopen(fnam, "r"); for (i=0; i < 3; i++) ATL_assert(fscanf(fp, " %lf", &mfs[i]) == 1); } fclose(fp); mf = (mfs[0] + mfs[1] + mfs[2]) / 3.0; fprintf(stdout, " %s : %.2f MFLOPS\n", fnam, mf); exit(0);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?