Checked in tuning code. Cleaned up tar file list.
authorJianzhong Xu <a0869574@ti.com>
Wed, 25 Mar 2015 20:28:35 +0000 (16:28 -0400)
committerJianzhong Xu <a0869574@ti.com>
Wed, 25 Mar 2015 20:28:35 +0000 (16:28 -0400)
27 files changed:
Makefile
build/tar_files_list.txt
build/version.txt
debian/changelog
examples/eig/main.c
examples/ludinv/main.c
examples/matmpy/main.c
examples/tuning/Makefile [new file with mode: 0644]
examples/tuning/cgemm_test/Makefile [new file with mode: 0644]
examples/tuning/cgemm_test/cgemm_test.c [new file with mode: 0644]
examples/tuning/cgemm_tune/Makefile [new file with mode: 0644]
examples/tuning/cgemm_tune/cgemm_tune.c [new file with mode: 0644]
examples/tuning/dgemm_test/Makefile [new file with mode: 0644]
examples/tuning/dgemm_test/dgemm_tbl.m [new file with mode: 0644]
examples/tuning/dgemm_test/dgemm_test.c [new file with mode: 0644]
examples/tuning/dgemm_test/log2_int.m [new file with mode: 0644]
examples/tuning/dgemm_test/tbl_lookup.m [new file with mode: 0644]
examples/tuning/dgemm_test/time_ana.m [new file with mode: 0644]
examples/tuning/dgemm_tune/Makefile [new file with mode: 0644]
examples/tuning/dgemm_tune/dgemm_tune.c [new file with mode: 0644]
examples/tuning/make.inc [new file with mode: 0644]
examples/tuning/sgemm_test/Makefile [new file with mode: 0644]
examples/tuning/sgemm_test/sgemm_test.c [new file with mode: 0644]
examples/tuning/sgemm_tune/Makefile [new file with mode: 0644]
examples/tuning/sgemm_tune/sgemm_tune.c [new file with mode: 0644]
examples/tuning/zgemm_tune/Makefile [new file with mode: 0644]
examples/tuning/zgemm_tune/zgemm_tune.c [new file with mode: 0644]

index 8663e831823a80db3dcde5b81cd12115b9b5f8fb..cc2276c65f0914f9b71a05d16d0774b9c46a17e5 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -28,7 +28,8 @@ cleanall:
        cd ../$(LINALG_BLIS_DIR); ./configure -p install/c66x c66x; make clean; \
        ./configure -p install/arm cortex-a15; make clean; \
        cd ../$(LINALG_BLISACC_DIR); make clean; \
-       cd ../$(LINALG_BLIS_DIR)/testsuite; make clean
+       cd ../$(LINALG_BLIS_DIR)/testsuite; make clean; \
+       cd ../../clapack; make clean
 
 DSPonly:
        cd $(LINALG_CBLAS_DIR); make arch=C66 alllib; \
index 4dacec4318140cfdb50ce95bf91dfcf6f0c71b9b..9c9d021208af10b353d2c5fa2e221c89de32311e 100644 (file)
@@ -13,24 +13,19 @@ blis/config
 blis/configure
 blis/CREDITS
 blis/frame
-blis/install
 blis/INSTALL
 blis/kernels
-blis/lib
 blis/LICENSE
 blis/Makefile
-blis/mpi_test
 blis/README
+blis/testsuite
 blasblisacc/Makefile
 blasblisacc/src
-cblas/examples
 cblas/include
-cblas/lib
 cblas/Makefile
 cblas/Makefile.ARM
-cblas/Makefile.C66
 cblas/Makefile.in
 cblas/README
 cblas/README.TI
 cblas/src
-clapack
\ No newline at end of file
+clapack
index 1da00ae45d867d013dc426780e7931c344b85576..9551b0db7d787d931cd26d9c2fcf6a6df5f34be5 100644 (file)
@@ -1 +1 @@
-0.3.0.0
+0.4.0.0
index c88640d25d3033475769f2a5bd7ac3252ec8c849..a8b263c19c9aacec79805aab0907ee5d98f93aee 100644 (file)
@@ -1,4 +1,4 @@
-ti-linalg (00.03.00.00-0ubuntu0~ppa1) trusty; urgency=medium
+ti-linalg (00.04.00.00-0ubuntu0~ppa1) trusty; urgency=medium
 
   * Initial release with BLIS based BLAS and LAPACK.
 
index 34034e03b65e33bc5b85328e01e323538dc2a3d0..bac05431883c6dfdc9745a5dabdfe9dd09cb35d8 100644 (file)
@@ -1,3 +1,31 @@
+/******************************************************************************
+ * Copyright (c) 2013-2015, Texas Instruments Incorporated - http://www.ti.com/
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions are met:
+ *       * Redistributions of source code must retain the above copyright
+ *         notice, this list of conditions and the following disclaimer.
+ *       * 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.
+ *       * Neither the name of Texas Instruments Incorporated nor the
+ *         names of its contributors may be used to endorse or promote products
+ *         derived from this software without specific prior 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 COPYRIGHT OWNER OR 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 <stdlib.h>
 #include <stdio.h>
 #include <string.h>
@@ -397,7 +425,7 @@ void print_complex_matrix(char* desc, double complex *mat, int m, int n, int ldv
             printf( " %10.5f + %10.5fi", real, imag);
          }
          else {
-            printf( " %10.5f - %10.5fi", real, abs(imag));
+            printf( " %10.5f - %10.5fi", real, fabs(imag));
          }
       }
       printf( "\n" );
index 2ef8d955274d1f1443421156ea23296370c939f9..9dbbd2b99942c1b777e6b98341aaa5a9ef6542ca 100644 (file)
@@ -1,3 +1,31 @@
+/******************************************************************************
+ * Copyright (c) 2013-2015, Texas Instruments Incorporated - http://www.ti.com/
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions are met:
+ *       * Redistributions of source code must retain the above copyright
+ *         notice, this list of conditions and the following disclaimer.
+ *       * 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.
+ *       * Neither the name of Texas Instruments Incorporated nor the
+ *         names of its contributors may be used to endorse or promote products
+ *         derived from this software without specific prior 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 COPYRIGHT OWNER OR 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 <stdlib.h>
 #include <stdio.h>
 #include <string.h>
index c6266e272ef413d34a6b416bdaa70550dce0c09e..6e83e451b1b91451adf78a4a3c07c9b504a9e3be 100644 (file)
@@ -1,3 +1,31 @@
+/******************************************************************************
+ * Copyright (c) 2013-2015, Texas Instruments Incorporated - http://www.ti.com/
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions are met:
+ *       * Redistributions of source code must retain the above copyright
+ *         notice, this list of conditions and the following disclaimer.
+ *       * 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.
+ *       * Neither the name of Texas Instruments Incorporated nor the
+ *         names of its contributors may be used to endorse or promote products
+ *         derived from this software without specific prior 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 COPYRIGHT OWNER OR 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 <stdio.h>
 #include <stdlib.h>
 #include <math.h>
diff --git a/examples/tuning/Makefile b/examples/tuning/Makefile
new file mode 100644 (file)
index 0000000..18d54c3
--- /dev/null
@@ -0,0 +1,28 @@
+.SILENT:
+
+MFS  = $(wildcard */Makefile)
+DIRS = $(patsubst %/Makefile,%,$(MFS))
+
+all:
+       for dir in $(DIRS); do \
+         echo "=============== " $$dir " =================" ; \
+         $(MAKE) -C $$dir; \
+       done
+
+run:
+       for dir in $(DIRS); do \
+         echo "=============== " $$dir " =================" ; \
+          $(MAKE tune) -C $$dir \
+        done
+
+cross:
+       for dir in $(DIRS); do \
+         echo "=============== " $$dir " =================" ; \
+          $(MAKE) -C $$dir cross; \
+        done
+
+clean:
+       for dir in $(DIRS); do \
+         $(MAKE) -C $$dir clean; \
+       done
+
diff --git a/examples/tuning/cgemm_test/Makefile b/examples/tuning/cgemm_test/Makefile
new file mode 100644 (file)
index 0000000..076de03
--- /dev/null
@@ -0,0 +1,10 @@
+
+EXE = cgemm_test
+
+include ../make.inc
+
+$(EXE): cgemm_test.o
+       $(CC) $(CFLAGS) cgemm_test.o $(BLASLIB) -o $@
+
+tune: $(EXE)
+       ./$(EXE);
\ No newline at end of file
diff --git a/examples/tuning/cgemm_test/cgemm_test.c b/examples/tuning/cgemm_test/cgemm_test.c
new file mode 100644 (file)
index 0000000..2c8846f
--- /dev/null
@@ -0,0 +1,235 @@
+/******************************************************************************
+ * Copyright (c) 2013-2014, Texas Instruments Incorporated - http://www.ti.com/
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions are met:
+ *       * Redistributions of source code must retain the above copyright
+ *         notice, this list of conditions and the following disclaimer.
+ *       * 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.
+ *       * Neither the name of Texas Instruments Incorporated nor the
+ *         names of its contributors may be used to endorse or promote products
+ *         derived from this software without specific prior 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 COPYRIGHT OWNER OR 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 <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include <time.h>
+#include <complex.h>
+
+#include "cblas.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include "cblas.h"
+#ifdef __cplusplus
+}
+#endif
+
+#define TUNING_START_SIZE_SQUARE_MATRIX 16
+#define TUNING_START_SIZE_RECTAN_MATRIX 8
+#define NUM_MATRIX_SIZE_TO_BENCHMARK 16
+#define HAS_MEMORY   1
+#define NO_MEMORY    0
+#define OFFLOAD      1
+#define NO_OFFLOAD   0
+
+#define NUM_TEST_RUN 5
+
+/*-----------------------------------------------------------------------------
+* Timing Setup
+*----------------------------------------------------------------------------*/
+struct timespec t0,t1;
+#define tick()  clock_gettime(CLOCK_MONOTONIC, &t0);
+#define tock() (clock_gettime(CLOCK_MONOTONIC, &t1), \
+                        t1.tv_sec - t0.tv_sec + (t1.tv_nsec - t0.tv_nsec) / 1e9)
+
+/*-----------------------------------------------------------------------------
+* Global Variables
+*----------------------------------------------------------------------------*/
+float complex alpha = 0.7 - 0.3*I; 
+float complex beta  = 0.4 + 0.6*I;
+enum CBLAS_ORDER     order  = CblasColMajor; 
+enum CBLAS_TRANSPOSE transA = CblasNoTrans;
+enum CBLAS_TRANSPOSE transB = CblasNoTrans;
+
+extern int TI_CBLAS_L3_OFFLOAD;
+
+/*-----------------------------------------------------------------------------
+* Prototypes
+*----------------------------------------------------------------------------*/
+int check_results(const float complex *C1, const float complex *C2, int M, int N);
+int run_cgemm(int M, int K, int N, float *time, float *gflops);
+
+/*-----------------------------------------------------------------------------
+* MAIN
+*----------------------------------------------------------------------------*/
+int main()
+{
+    int num_size, cgemm_err;
+    int M, N, K, m, n, k;
+    float time_secs, gflops;
+    FILE *fp_time;  
+  
+    fp_time = fopen("cgemm_time_ARMvsDSP.dat","w");
+    
+    srand(12345);
+    
+    /* sweep M, K, and N */    
+    for (M=TUNING_START_SIZE_RECTAN_MATRIX,m=0; m<NUM_MATRIX_SIZE_TO_BENCHMARK; m++,M*=2) 
+    {
+        for (N=TUNING_START_SIZE_RECTAN_MATRIX,n=0; n<NUM_MATRIX_SIZE_TO_BENCHMARK; n++,N*=2) 
+        {
+            for (K=TUNING_START_SIZE_RECTAN_MATRIX,k=0; k<NUM_MATRIX_SIZE_TO_BENCHMARK; k++,K*=2) 
+            {
+                printf("Running CGEMM for (M,N,K)=(%d,%d,%d), (m,n,k)=(%d,%d,%d).\n", M,N,K,m,n,k);
+                cgemm_err = run_cgemm(M, N, K, &time_secs, &gflops);
+          
+                if(cgemm_err == -1) {  /* out of memory for DSP offloading */
+                    printf("Out of memory, skipping next point.\n");
+                }
+                else {
+                    if (cgemm_err == 0){
+                        fprintf(fp_time, "%6d,%6d,%6d\t%10.8e\n", M, N, K, time_secs);
+                    }
+                    else {
+                        printf("Error in CGEMM tuning for (M,N,K)=(%d,%d,%d)!\n", M,N,K);
+                        exit(0);
+                    }
+                }
+            }
+        }
+    }
+        
+    fclose(fp_time);
+    
+    return 0;
+}
+
+
+int run_cgemm(int M, int N, int K, float *time, float *gflops)
+{
+    long long i;
+    int   iter;
+    float time_secs, total_time;
+    float gflops_ARM, gflops_DSP;
+    float operation_count = 2.0*(float)M*(float)N*(float)K;
+    float total_GFLOPS = 0.0f;
+    int   err_code = 0;
+    
+    total_time = 0.0;
+    for (iter = 0; iter < NUM_TEST_RUN; iter++)
+    {      
+      /*-------------------------------------------------------------------------
+      * Allocate space for the matrices.  The matrices that will be passed to 
+      * the DSP are allocated using device memory.  The Carm array is not passed
+      * to the dsp and so can use system memory.
+      *------------------------------------------------------------------------*/
+      float complex *A    = (float complex*) __malloc_ddr(M*K*sizeof(float complex));
+      float complex *B    = (float complex*) __malloc_ddr(K*N*sizeof(float complex));
+      float complex *Cdsp = (float complex*) __malloc_ddr(M*N*sizeof(float complex));
+      float complex *Carm = (float complex*) malloc      (M*N*sizeof(float complex));
+  
+      if (!A || !B || !Cdsp || !Carm)
+      {
+          printf("Could not allocate enough space for the arrays!");
+          if(A) __free_ddr(A);
+          if(B) __free_ddr(B);
+          if(Cdsp) __free_ddr(Cdsp);
+          if(Carm) free(Carm);
+          
+          return (-1);
+      }
+  
+      /*-------------------------------------------------------------------------
+      * Initialize matrices and print if small enough.
+      *------------------------------------------------------------------------*/
+      for (i = 0; i < M*K; ++i) 
+      {
+          A[i] = (float)rand()/RAND_MAX + (float)rand()/RAND_MAX * I;
+      }
+      for (i = 0; i < K*N; ++i)
+      {
+          B[i] = (float)rand()/RAND_MAX + (float)rand()/RAND_MAX * I;
+      }
+      for (i = 0; i < M*N; ++i)
+      {
+          Carm[i] = Cdsp[i] = (float)rand()/RAND_MAX + (float)rand()/RAND_MAX * I;
+      }  
+  
+      int lda = ((order == CblasColMajor && transA == CblasNoTrans) ||
+              (order == CblasRowMajor && transA == CblasTrans)) ? M : K;
+  
+      int ldb = ((order == CblasColMajor && transB == CblasNoTrans) ||
+              (order == CblasRowMajor && transB == CblasTrans)) ? K : N;
+  
+      int ldc = (order == CblasColMajor) ? M : N;
+    
+      /*------------------------------------------------------------------------
+      * Run and time cgemm
+      *-----------------------------------------------------------------------*/     
+      tick();
+      cblas_cgemm(order,transA,transB,M,N,K,&alpha,A,lda,B,ldb,&beta,Cdsp,ldc);
+      time_secs = tock();
+      total_time += time_secs;
+      total_GFLOPS += operation_count/time_secs*1e-9;
+         
+      __free_ddr(A);
+      __free_ddr(B);
+      __free_ddr(Cdsp);
+      free(Carm);
+    }
+    
+    *gflops = total_GFLOPS / (float)NUM_TEST_RUN;
+    *time   = total_time / (float)NUM_TEST_RUN;
+
+    return err_code;
+}
+
+/*-----------------------------------------------------------------------------
+* check_results
+*----------------------------------------------------------------------------*/
+int check_results(const float complex *C1, const float complex *C2, int M, int N)
+{
+    int i;
+    const float EPISILON = 1e-5;
+    //const float EPISILON = 1e-200;
+    const int NERRORS  = 5;
+    int       num_errors = 0;
+
+    for (i=0; i<M*N; i++)
+    {
+        float delta = cabs(C1[i]) - cabs(C2[i]);
+
+        if (delta > EPISILON*cabs(C1[i]))
+            if ((num_errors += 1) < NERRORS)
+                printf("Error [elem:%d]: %f <==> %f\n", i, cabs(C1[i]), cabs(C2[i]));
+    }
+
+    if (num_errors > 0)
+    {
+         printf("FAIL with %d errors!\n", num_errors);
+         return -1;
+    }
+    else 
+    {
+        //printf("PASS!\n");
+        return 0;
+    }
+}
+
+
diff --git a/examples/tuning/cgemm_tune/Makefile b/examples/tuning/cgemm_tune/Makefile
new file mode 100644 (file)
index 0000000..8ab318b
--- /dev/null
@@ -0,0 +1,10 @@
+
+EXE = cgemm_tune
+
+include ../make.inc
+
+$(EXE): cgemm_tune.o
+       $(CC) $(CFLAGS) cgemm_tune.o $(BLASLIB) -o $@
+
+tune: $(EXE)
+       ./$(EXE);
\ No newline at end of file
diff --git a/examples/tuning/cgemm_tune/cgemm_tune.c b/examples/tuning/cgemm_tune/cgemm_tune.c
new file mode 100644 (file)
index 0000000..489979a
--- /dev/null
@@ -0,0 +1,326 @@
+/******************************************************************************
+ * Copyright (c) 2013-2014, Texas Instruments Incorporated - http://www.ti.com/
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions are met:
+ *       * Redistributions of source code must retain the above copyright
+ *         notice, this list of conditions and the following disclaimer.
+ *       * 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.
+ *       * Neither the name of Texas Instruments Incorporated nor the
+ *         names of its contributors may be used to endorse or promote products
+ *         derived from this software without specific prior 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 COPYRIGHT OWNER OR 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 <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include <time.h>
+#include <complex.h>
+
+#include "cblas.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include "cblas.h"
+#ifdef __cplusplus
+}
+#endif
+
+#define TUNING_START_SIZE_SQUARE_MATRIX 16
+#define TUNING_START_SIZE_RECTAN_MATRIX 8
+#define NUM_MATRIX_SIZE_TO_BENCHMARK 16
+#define HAS_MEMORY   1
+#define NO_MEMORY    0
+#define OFFLOAD      1
+#define NO_OFFLOAD   0
+
+#define NUM_TEST_RUN 5
+
+/*-----------------------------------------------------------------------------
+* Timing Setup
+*----------------------------------------------------------------------------*/
+struct timespec t0,t1;
+#define tick()  clock_gettime(CLOCK_MONOTONIC, &t0);
+#define tock() (clock_gettime(CLOCK_MONOTONIC, &t1), \
+                        t1.tv_sec - t0.tv_sec + (t1.tv_nsec - t0.tv_nsec) / 1e9)
+
+/*-----------------------------------------------------------------------------
+* Global Variables
+*----------------------------------------------------------------------------*/
+float complex alpha = 0.7 - 0.3*I; 
+float complex beta  = 0.4 + 0.6*I;
+enum CBLAS_ORDER     order  = CblasColMajor; 
+enum CBLAS_TRANSPOSE transA = CblasNoTrans;
+enum CBLAS_TRANSPOSE transB = CblasNoTrans;
+
+extern int TI_CBLAS_L3_OFFLOAD;
+
+/*-----------------------------------------------------------------------------
+* Prototypes
+*----------------------------------------------------------------------------*/
+int check_results(const float complex *C1, const float complex *C2, int M, int N);
+int run_cgemm_dsp_and_arm(int M, int K, int N, float *time_dsp, float *time_arm, 
+                          float *gflops_dsp, float *gflops_arm);
+
+/*-----------------------------------------------------------------------------
+* MAIN
+*----------------------------------------------------------------------------*/
+int main()
+{
+    int num_size, cgemm_err;
+    int M, N, K, m, n, k;
+    int M_pre, N_pre, K_pre, M_start_size, N_start_size;
+    int offload_threshold_1, offload_threshold_2;
+    float total_GFLOPS_DSP, total_GFLOPS_ARM;
+    float time_DSP, time_ARM, t_dsp, t_arm;
+    char ofld_flag[NUM_MATRIX_SIZE_TO_BENCHMARK][NUM_MATRIX_SIZE_TO_BENCHMARK][NUM_MATRIX_SIZE_TO_BENCHMARK];
+    char mem_flag[NUM_MATRIX_SIZE_TO_BENCHMARK][NUM_MATRIX_SIZE_TO_BENCHMARK][NUM_MATRIX_SIZE_TO_BENCHMARK];
+    int skip_next_point;
+    float diff_tmp, diff_pre;
+    FILE *fp_flag, *fp_time, *fp_tbl;  
+  
+    fp_flag = fopen("ofld_flag_cgemm.dat","w");
+    fp_tbl  = fopen("ofld_tbl_cgemm.c","w");
+    fp_time = fopen("cgemm_time_ARMvsDSP.dat","w");
+
+    fprintf(fp_tbl, "char ofld_tbl_cgemm[TI_L3_OFFLOAD_TBL_SIZE] = {\n");
+    
+    srand(12345);
+
+    /* sweep M, K, and N */    
+    for (M=TUNING_START_SIZE_RECTAN_MATRIX,m=0; m<NUM_MATRIX_SIZE_TO_BENCHMARK; m++,M*=2) 
+    {
+        for (N=TUNING_START_SIZE_RECTAN_MATRIX,n=0; n<NUM_MATRIX_SIZE_TO_BENCHMARK; n++,N*=2) 
+        {
+            for (K=TUNING_START_SIZE_RECTAN_MATRIX,k=0; k<NUM_MATRIX_SIZE_TO_BENCHMARK; k++,K*=2) 
+            {
+                if(  (m>0 && ofld_flag[m-1][n][k]==OFFLOAD)
+                   ||(n>0 && ofld_flag[m][n-1][k]==OFFLOAD)
+                   ||(k>0 && ofld_flag[m][n][k-1]==OFFLOAD) ) {
+                    ofld_flag[m][n][k] = OFFLOAD;
+                    mem_flag[m][n][k]  = HAS_MEMORY;  // to avoid error
+                    time_DSP = -1.0;
+                    time_ARM = -1.0;
+                    printf("Offloading. Skipping (M,N,K)=(%d,%d,%d), (m,n,k)=(%d,%d,%d).\n", M,N,K,m,n,k);
+                }
+                else if(  (m>0 && (mem_flag[m-1][n][k]==NO_MEMORY))
+                        ||(n>0 && (mem_flag[m][n-1][k]==NO_MEMORY))
+                        ||(k>0 && (mem_flag[m][n][k-1]==NO_MEMORY))) {
+                    ofld_flag[m][n][k] = NO_OFFLOAD;
+                    mem_flag[m][n][k]  = NO_MEMORY;
+                    time_DSP = -2.0;
+                    time_ARM = -2.0;
+                    printf("Out of memory. Skipping (M,N,K)=(%d,%d,%d), (m,n,k)=(%d,%d,%d).\n", M,N,K,m,n,k);
+                }
+                else {                    
+                    printf("Measuring DSP and ARM GFLOPS for (M,N,K)=(%d,%d,%d), (m,n,k)=(%d,%d,%d).\n", M,N,K,m,n,k);
+                    cgemm_err = run_cgemm_dsp_and_arm(M, N, K, &t_dsp, &t_arm, &total_GFLOPS_DSP, &total_GFLOPS_ARM);
+                    //dsym_err  = run_dsymm_dsp_and_arm();
+              
+                    if(cgemm_err == -1) {  /* out of memory for DSP offloading */
+                        ofld_flag[m][n][k] = NO_OFFLOAD;
+                        mem_flag[m][n][k] = NO_MEMORY;
+                        time_DSP = -2.0;
+                        time_ARM = -2.0;
+                        printf("Out of memory, skipping next point.\n");
+                    }
+                    else {
+                        mem_flag[m][n][k] = HAS_MEMORY;                    
+                        time_DSP = t_dsp;
+                        time_ARM = t_arm;
+                        if (cgemm_err == 0){
+                            //if(total_GFLOPS_DSP - total_GFLOPS_ARM > 1.0) {
+                            if(t_dsp < t_arm) {
+                                ofld_flag[m][n][k] = OFFLOAD;
+                                printf("Offloading to DSP for this point. Skipping next point.\n");
+                            }
+                            else {
+                                ofld_flag[m][n][k] = NO_OFFLOAD;
+                            }
+                        }
+                        else {
+                            printf("Error in CGEMM tuning for (M,N,K)=(%d,%d,%d)!\n", M,N,K);
+                            exit(0);
+                        }
+                    }
+                }
+                
+                fprintf(fp_flag, "%d\t%d\n", (int)mem_flag[m][n][k], (int)ofld_flag[m][n][k]);
+                fprintf(fp_time, "%6d,%6d,%6d\t%10.8e\t%10.8e\n", M, N, K, time_ARM, time_DSP);
+
+                if(   (m==(NUM_MATRIX_SIZE_TO_BENCHMARK-1))
+                   && (n==(NUM_MATRIX_SIZE_TO_BENCHMARK-1))
+                   && (k==(NUM_MATRIX_SIZE_TO_BENCHMARK-1))) {
+                  fprintf(fp_tbl, "%d};", (int)ofld_flag[m][n][k]);
+                } else {
+                  fprintf(fp_tbl, "%d,", (int)ofld_flag[m][n][k]);
+                }
+            }
+            fprintf(fp_tbl, "\n");
+        }
+    }
+        
+    fclose(fp_flag);
+    fclose(fp_time);
+    fclose(fp_tbl);
+    
+    return 0;
+}
+
+
+int run_cgemm_dsp_and_arm(int M, int K, int N, float *time_dsp, float *time_arm, 
+                          float *gflops_dsp, float *gflops_arm)
+{
+    int    iter;
+    long long i;
+    float time_secs, total_time_dsp, total_time_arm;
+    float gflops_ARM, gflops_DSP;
+    float operation_count = 2.0*(float)M*(float)N*(float)K;
+    float total_GFLOPS_DSP = 0.0f;
+    float total_GFLOPS_ARM = 0.0f;
+    int    err_code = 0;
+    
+    total_time_dsp = 0.0;
+    total_time_arm = 0.0;
+    for (iter = 0; iter < NUM_TEST_RUN; iter++)
+    {      
+      /*-------------------------------------------------------------------------
+      * Allocate space for the matrices.  The matrices that will be passed to 
+      * the DSP are allocated using device memory.  The Carm array is not passed
+      * to the dsp and so can use system memory.
+      *------------------------------------------------------------------------*/
+      float complex *A    = (float complex*) __malloc_ddr(M*K*sizeof(float complex));
+      float complex *B    = (float complex*) __malloc_ddr(K*N*sizeof(float complex));
+      float complex *Cdsp = (float complex*) __malloc_ddr(M*N*sizeof(float complex));
+      float complex *Carm = (float complex*) malloc      (M*N*sizeof(float complex));
+  
+      if (!A || !B || !Cdsp || !Carm)
+      {
+          printf("Could not allocate enough space for the arrays!");
+          if(A) __free_ddr(A);
+          if(B) __free_ddr(B);
+          if(Cdsp) __free_ddr(Cdsp);
+          if(Carm) free(Carm);
+          
+          return (-1);
+      }
+  
+      /*-------------------------------------------------------------------------
+      * Initialize matrices and print if small enough.
+      *------------------------------------------------------------------------*/
+      for (i = 0; i < M*K; ++i) 
+      {
+          A[i] = (float)rand()/RAND_MAX + (float)rand()/RAND_MAX * I;
+      }
+      for (i = 0; i < K*N; ++i)
+      {
+          B[i] = (float)rand()/RAND_MAX + (float)rand()/RAND_MAX * I;
+      }
+      for (i = 0; i < M*N; ++i)
+      {
+          Carm[i] = Cdsp[i] = (float)rand()/RAND_MAX + (float)rand()/RAND_MAX * I;
+      }  
+  
+      int lda = ((order == CblasColMajor && transA == CblasNoTrans) ||
+              (order == CblasRowMajor && transA == CblasTrans)) ? M : K;
+  
+      int ldb = ((order == CblasColMajor && transB == CblasNoTrans) ||
+              (order == CblasRowMajor && transB == CblasTrans)) ? K : N;
+  
+      int ldc = (order == CblasColMajor) ? M : N;
+    
+      /*============ BLAS tuning: running on DSP and then on ARM =============*/
+      /*------------------------------------------------------------------------
+      * Time DSP cgemm
+      *-----------------------------------------------------------------------*/
+      //ti_cblas_offload_config("001");  /* force offloading level 3 to DSP */
+      TI_CBLAS_L3_OFFLOAD = 1;
+      
+      tick();
+      cblas_cgemm(order,transA,transB,M,N,K,&alpha,A,lda,B,ldb,&beta,Cdsp,ldc);
+      time_secs = tock();
+      total_time_dsp += time_secs;
+      gflops_DSP = operation_count/time_secs*1e-9;
+      total_GFLOPS_DSP += gflops_DSP;
+      
+      /*-------------------------------------------------------------------------
+      * Time ARM cgemm
+      *------------------------------------------------------------------------*/
+      //ti_cblas_offload_config("000");  /* force no offloading */
+      TI_CBLAS_L3_OFFLOAD = 0;
+      
+      tick();
+      cblas_cgemm(order,transA,transB,M,N,K,&alpha,A,lda,B,ldb,&beta,Carm,ldc);
+      time_secs = tock();
+      total_time_arm += time_secs;
+      gflops_ARM = operation_count/time_secs*1e-9;
+      total_GFLOPS_ARM += gflops_ARM;
+      //printf(" %6.3f  %6.3f  %9.6fs %9.6fs\n", gflops_DSP, gflops_ARM, time_dsp, time_arm);
+  
+      /*-------------------------------------------------------------------------
+      * Verify Results
+      *------------------------------------------------------------------------*/
+      //return check_results(Cdsp, Carm, M, N);
+      err_code += check_results(Cdsp, Carm, M, N);
+  
+      __free_ddr(A);
+      __free_ddr(B);
+      __free_ddr(Cdsp);
+      free(Carm);
+    }
+    
+    *gflops_dsp = total_GFLOPS_DSP;
+    *gflops_arm = total_GFLOPS_ARM;
+    *time_dsp   = total_time_dsp / (float)NUM_TEST_RUN;
+    *time_arm   = total_time_arm / (float)NUM_TEST_RUN;
+
+    return err_code;
+}
+
+/*-----------------------------------------------------------------------------
+* check_results
+*----------------------------------------------------------------------------*/
+int check_results(const float complex *C1, const float complex *C2, int M, int N)
+{
+    int i;
+    const float EPISILON = 1e-5;
+    //const float EPISILON = 1e-200;
+    const int NERRORS  = 5;
+    int       num_errors = 0;
+
+    for (i=0; i<M*N; i++)
+    {
+        float delta = cabs(C1[i]) - cabs(C2[i]);
+
+        if (delta > EPISILON*cabs(C1[i]))
+            if ((num_errors += 1) < NERRORS)
+                printf("Error [elem:%d]: %f <==> %f\n", i, cabs(C1[i]), cabs(C2[i]));
+    }
+
+    if (num_errors > 0)
+    {
+         printf("FAIL with %d errors!\n", num_errors);
+         return -1;
+    }
+    else 
+    {
+        //printf("PASS!\n");
+        return 0;
+    }
+}
+
+
diff --git a/examples/tuning/dgemm_test/Makefile b/examples/tuning/dgemm_test/Makefile
new file mode 100644 (file)
index 0000000..b7c5492
--- /dev/null
@@ -0,0 +1,8 @@
+
+EXE = dgemm_test
+
+include ../make.inc
+
+$(EXE): dgemm_test.o
+       $(CC) $(CFLAGS) dgemm_test.o $(BLASLIB) -o $@
+
diff --git a/examples/tuning/dgemm_test/dgemm_tbl.m b/examples/tuning/dgemm_test/dgemm_tbl.m
new file mode 100644 (file)
index 0000000..64e99a6
--- /dev/null
@@ -0,0 +1,256 @@
+tbl_dgemm=[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 
+0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 
+0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 
+0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 
+0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 
+0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 
+0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 
+0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 
+0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 
+0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 
+0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 
+0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 
+0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 
+0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 
+0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 
+0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 
+0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 
+0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 
+0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 
+0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 
+0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 
+0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 
+0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 
+0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 
+0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 
+0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 
+0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 
+0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 
+0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 
+0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 
+0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 
+0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 
+0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 
+0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 
+0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 
+0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 
+0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 
+0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 
+0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 
+0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 
+0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 
+0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 
+0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 
+0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 
+0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 
+0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 
+0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 
+0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 
+0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 
+0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 
+0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 
+0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 
+0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 
+0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 
+0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 
+0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 
+0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 
+0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 
+0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 
+0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1];
\ No newline at end of file
diff --git a/examples/tuning/dgemm_test/dgemm_test.c b/examples/tuning/dgemm_test/dgemm_test.c
new file mode 100644 (file)
index 0000000..6520abe
--- /dev/null
@@ -0,0 +1,208 @@
+/******************************************************************************
+ * Copyright (c) 2013-2014, Texas Instruments Incorporated - http://www.ti.com/
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions are met:
+ *       * Redistributions of source code must retain the above copyright
+ *         notice, this list of conditions and the following disclaimer.
+ *       * 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.
+ *       * Neither the name of Texas Instruments Incorporated nor the
+ *         names of its contributors may be used to endorse or promote products
+ *         derived from this software without specific prior 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 COPYRIGHT OWNER OR 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 <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include <time.h>
+
+#include "cblas.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include "cblas.h"
+#ifdef __cplusplus
+}
+#endif
+
+#define TUNING_START_SIZE_RECTAN_MATRIX 50
+#define NUM_MATRIX_SIZE_TO_BENCHMARK 6
+#define HAS_MEMORY   1
+#define NO_MEMORY    0
+#define OFFLOAD      1
+#define NO_OFFLOAD   0
+
+#define NUM_TEST_RUN 1
+
+
+/*-----------------------------------------------------------------------------
+* Timing Setup
+*----------------------------------------------------------------------------*/
+struct timespec t0,t1;
+#define tick()  clock_gettime(CLOCK_MONOTONIC, &t0);
+#define tock() (clock_gettime(CLOCK_MONOTONIC, &t1), \
+                        t1.tv_sec - t0.tv_sec + (t1.tv_nsec - t0.tv_nsec) / 1e9)
+
+/*-----------------------------------------------------------------------------
+* Global Variables
+*----------------------------------------------------------------------------*/
+double alpha           = 0.7; 
+double beta            = 0.3;
+enum CBLAS_ORDER     order  = CblasColMajor; 
+//enum CBLAS_ORDER     order  = CblasRowMajor;
+enum CBLAS_TRANSPOSE transA = CblasNoTrans;
+enum CBLAS_TRANSPOSE transB = CblasNoTrans;
+
+extern int TI_CBLAS_L3_OFFLOAD;
+/*-----------------------------------------------------------------------------
+* Prototypes
+*----------------------------------------------------------------------------*/
+int run_dgemm(int M, int N, int K, float *time, float *gflops);
+
+/*-----------------------------------------------------------------------------
+* MAIN
+*----------------------------------------------------------------------------*/
+int main()
+{
+    int num_size, dgemm_err;
+    int M, N, K, m, n, k;
+    int M_pre, N_pre, K_pre, M_start_size, N_start_size;
+    float time_secs_arm, gflops_arm, time_secs_dsp, gflops_dsp, time_secs_opt, gflops_opt;
+    FILE *fp_time, *fp_flops;  
+  
+    fp_time = fopen("dgemm_time.dat","w");
+    fp_flops = fopen("dgemm_flops.dat","w");
+
+    srand(12345);
+    
+       /* setting up TI CBLAS during first call */
+       run_dgemm(100, 100, 100, &time_secs_arm, &gflops_arm);
+       
+    /* sweep M, K, and N */    
+    for (M=TUNING_START_SIZE_RECTAN_MATRIX,m=0; m<NUM_MATRIX_SIZE_TO_BENCHMARK; m++,M*=2) 
+    {
+        for (N=TUNING_START_SIZE_RECTAN_MATRIX,n=0; n<NUM_MATRIX_SIZE_TO_BENCHMARK; n++,N*=2) 
+        {
+            for (K=TUNING_START_SIZE_RECTAN_MATRIX,k=0; k<NUM_MATRIX_SIZE_TO_BENCHMARK; k++,K*=2) 
+            {
+                printf("Running DGEMM for (M,N,K) = (%d,%d,%d).\n", M,N,K);
+                               
+                               TI_CBLAS_L3_OFFLOAD = 0;
+                dgemm_err = run_dgemm(M, N, K, &time_secs_arm, &gflops_arm);
+          
+                if(dgemm_err == -1) {  /* out of memory for DSP offloading */
+                    printf("Out of memory for (M,N,K) = (%d,%d,%d).\n", M,N,K);
+                }
+                else {
+                               TI_CBLAS_L3_OFFLOAD = 1;
+                    dgemm_err = run_dgemm(M, N, K, &time_secs_dsp, &gflops_dsp);
+    
+                               TI_CBLAS_L3_OFFLOAD = 2;
+                    dgemm_err = run_dgemm(M, N, K, &time_secs_opt, &gflops_opt);
+
+                    fprintf(fp_time, "%6d\t%6d\t%6d\t%10.8e\t%10.8e\t%10.8e\n", 
+                                               M, N, K, time_secs_arm, time_secs_dsp, time_secs_opt);
+                    fprintf(fp_flops, "%6d\t%6d\t%6d\t%10.8e\t%10.8e\t%10.8e\n", 
+                            M, N, K, gflops_arm, gflops_dsp, gflops_opt);
+                }
+            }
+        }
+    }
+        
+    fclose(fp_time);
+    fclose(fp_flops);
+    
+    return 0;
+}
+
+
+int run_dgemm(int M, int N, int K, float *time, float *gflops)
+{
+    int    iter;
+    long long i;
+    double time_secs, total_time;
+    double operation_count = 2.0*(double)M*(double)N*(double)K;
+    double total_GFLOPS = 0.0f;
+    int    err_code = 0;
+    
+    total_time = 0.0;
+    for (iter = 0; iter < NUM_TEST_RUN; iter++)
+    {      
+      /*-------------------------------------------------------------------------
+      * Allocate space for the matrices.  
+      *------------------------------------------------------------------------*/
+      double *A = (double *) __malloc_ddr((long long)M*(long long)K*(long long)sizeof(double));
+      double *B = (double *) __malloc_ddr((long long)K*(long long)N*(long long)sizeof(double));
+      double *C = (double *) __malloc_ddr((long long)M*(long long)N*(long long)sizeof(double));
+  
+      if (!A || !B || !C)
+      {
+          printf("Could not allocate enough space for the arrays!");
+          if(A) __free_ddr(A);
+          if(B) __free_ddr(B);
+          if(C) __free_ddr(C);
+          
+          return (-1);
+      }
+  
+      /*-------------------------------------------------------------------------
+      * Initialize matrices 
+      *------------------------------------------------------------------------*/
+      for (i = 0; i < (long long)M*K; ++i) A[i] = (double)rand()/RAND_MAX;// (double)(rand() % 5 + 1);
+      for (i = 0; i < (long long)K*N; ++i) B[i] = (double)rand()/RAND_MAX;// (double)(rand() % 5 + 1);
+      for (i = 0; i < (long long)M*N; ++i) C[i] = 0;
+  
+      int lda = ((order == CblasColMajor && transA == CblasNoTrans) ||
+              (order == CblasRowMajor && transA == CblasTrans)) ? M : K;
+  
+      int ldb = ((order == CblasColMajor && transB == CblasNoTrans) ||
+              (order == CblasRowMajor && transB == CblasTrans)) ? K : N;
+  
+      int ldc = (order == CblasColMajor) ? M : N;
+  
+      fflush(stdout);
+  
+      /*------------------------------------------------------------------------
+      * Run and time dgemm
+      *-----------------------------------------------------------------------*/
+      tick();
+      cblas_dgemm(order,transA,transB,M,N,K,alpha,A,lda,B,ldb,beta,C,ldc);
+      time_secs = tock();
+      total_time += time_secs;
+      total_GFLOPS += operation_count/time_secs*1e-9;
+/*      
+      if(M==4096 && K==256 && N==16) {
+          FILE *file_a = fopen("mat_a.dat","w");
+          FILE *file_b = fopen("mat_b.dat","w");
+          FILE *file_c = fopen("mat_c.dat","w");
+          
+          for(i=0; i < M*K; ++i) fprintf(file_a, "%1.10e\n",A[i]);
+          for(i=0; i < K*N; ++i) fprintf(file_b, "%1.10e\n",B[i]);
+          for(i=0; i < M*N; ++i) fprintf(file_c, "%1.10e\n",C[i]);
+      }
+*/      
+  
+      __free_ddr(A);
+      __free_ddr(B);
+      __free_ddr(C);
+    }
+    
+    *gflops = total_GFLOPS / (double)NUM_TEST_RUN;
+    *time   = total_time / (double)NUM_TEST_RUN;
+    
+    return err_code;
+}
diff --git a/examples/tuning/dgemm_test/log2_int.m b/examples/tuning/dgemm_test/log2_int.m
new file mode 100644 (file)
index 0000000..15168e0
--- /dev/null
@@ -0,0 +1,11 @@
+function log2_x = log2_int(x)
+    log2_x = 0;
+    x0     = x;
+    while x > 1
+        x = bitsrl(int32(x),1);
+        log2_x = log2_x+1;
+    end
+    if bitand(x0,bitsll(1,log2_x-1)) > 0
+        log2_x = log2_x+1;
+    end
+end
diff --git a/examples/tuning/dgemm_test/tbl_lookup.m b/examples/tuning/dgemm_test/tbl_lookup.m
new file mode 100644 (file)
index 0000000..ae62fb5
--- /dev/null
@@ -0,0 +1,35 @@
+function offload_decision = tbl_lookup(tbl,M,K,N)
+
+size_min=8;
+size_max=262144;
+size_min_log2=3;
+num_pnt=16;
+
+if M>size_max
+    M = size_max;
+end
+if M<size_min
+    M = size_min;
+end
+
+if K>size_max
+    K = size_max;
+end
+if K<size_min
+    K = size_min;
+end
+
+if N>size_max
+    N = size_max;
+end
+if N<size_min
+    N = size_min;
+end
+
+M_log2 = log2_int(int32(M));
+N_log2 = log2_int(int32(N));
+K_log2 = log2_int(int32(K));
+
+offload_decision = tbl((M_log2-size_min_log2)*num_pnt^2+(K_log2-size_min_log2)*num_pnt+N_log2-size_min_log2+1);
+end
+
diff --git a/examples/tuning/dgemm_test/time_ana.m b/examples/tuning/dgemm_test/time_ana.m
new file mode 100644 (file)
index 0000000..3f315c5
--- /dev/null
@@ -0,0 +1,41 @@
+dgemm_tbl;
+x=reshape(tbl_dgemm',256*16,1);
+
+test1=dgemmt;
+test2=dgemm_time;
+
+test1_t0= dgemmt(:,4);
+test1_t1= dgemmt(:,5);
+test1_t2= dgemmt(:,6);
+test1_M = dgemmt(:,1);
+test1_N = dgemmt(:,2);
+test1_K = dgemmt(:,3);
+
+test1_dec = zeros(length(test1_M),1);
+
+for i=1:length(test1_M)
+    test1_dec(i) = tbl_lookup(x,test1_M(i),test1_N(i),test1_K(i));
+end
+
+dec_err = (test1_t1>test1_t0) == test1_dec;
+
+test1_err_abs = (min(test1_t0,test1_t1)-test1_t2) .* dec_err;
+test1_err_rel = (min(test1_t0,test1_t1)-test1_t2) .* dec_err ./ min(test1_t0,test1_t1);
+
+test2_t0= dgemm_time(:,4);
+test2_t1= dgemm_time(:,5);
+test2_t2= dgemm_time(:,6);
+test2_M = dgemm_time(:,1);
+test2_N = dgemm_time(:,2);
+test2_K = dgemm_time(:,3);
+
+test2_dec = zeros(length(test2_M),1);
+
+for i=1:length(test2_M)
+    test2_dec(i) = tbl_lookup(x,test2_M(i),test2_N(i),test2_K(i));
+end
+
+dec_err = (test2_t1>test2_t0) == test2_dec;
+
+test2_err_abs = (min(test2_t0,test2_t1)-test2_t2) .* dec_err;
+test2_err_rel = (min(test2_t0,test2_t1)-test2_t2) .* dec_err ./ min(test2_t0,test2_t1);
diff --git a/examples/tuning/dgemm_tune/Makefile b/examples/tuning/dgemm_tune/Makefile
new file mode 100644 (file)
index 0000000..4887def
--- /dev/null
@@ -0,0 +1,10 @@
+
+EXE = dgemm_tune
+
+include ../make.inc
+
+$(EXE): dgemm_tune.o
+       $(CC) $(CFLAGS) dgemm_tune.o $(BLASLIB) -o $@
+
+tune: $(EXE)
+       ./$(EXE);
\ No newline at end of file
diff --git a/examples/tuning/dgemm_tune/dgemm_tune.c b/examples/tuning/dgemm_tune/dgemm_tune.c
new file mode 100644 (file)
index 0000000..2c27411
--- /dev/null
@@ -0,0 +1,332 @@
+/******************************************************************************
+ * Copyright (c) 2013-2015, Texas Instruments Incorporated - http://www.ti.com/
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions are met:
+ *       * Redistributions of source code must retain the above copyright
+ *         notice, this list of conditions and the following disclaimer.
+ *       * 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.
+ *       * Neither the name of Texas Instruments Incorporated nor the
+ *         names of its contributors may be used to endorse or promote products
+ *         derived from this software without specific prior 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 COPYRIGHT OWNER OR 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 <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include <time.h>
+
+#include "cblas.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include "cblas.h"
+#ifdef __cplusplus
+}
+#endif
+
+#define TUNING_START_SIZE_SQUARE_MATRIX 16
+#define TUNING_START_SIZE_RECTAN_MATRIX 8
+#define NUM_MATRIX_SIZE_TO_BENCHMARK 16
+#define HAS_MEMORY   1
+#define NO_MEMORY    0
+#define OFFLOAD      1
+#define NO_OFFLOAD   0
+
+#define NUM_TEST_RUN 5
+
+
+/*-----------------------------------------------------------------------------
+* Timing Setup
+*----------------------------------------------------------------------------*/
+struct timespec t0,t1;
+#define tick()  clock_gettime(CLOCK_MONOTONIC, &t0);
+#define tock() (clock_gettime(CLOCK_MONOTONIC, &t1), \
+                        t1.tv_sec - t0.tv_sec + (t1.tv_nsec - t0.tv_nsec) / 1e9)
+
+/*-----------------------------------------------------------------------------
+* Global Variables
+*----------------------------------------------------------------------------*/
+double alpha           = 0.7; 
+double beta            = 0.3;
+enum CBLAS_ORDER     order  = CblasColMajor; 
+//enum CBLAS_ORDER     order  = CblasRowMajor;
+enum CBLAS_TRANSPOSE transA = CblasNoTrans;
+enum CBLAS_TRANSPOSE transB = CblasNoTrans;
+
+extern int TI_CBLAS_L3_OFFLOAD;
+/*-----------------------------------------------------------------------------
+* Prototypes
+*----------------------------------------------------------------------------*/
+int check_results(const double *C1, const double *C2, int M, int N);
+int run_dgemm_dsp_and_arm(int M, int N, int K, double *time_dsp, double *time_arm, 
+                          double *gflops_dsp, double *gflops_arm);
+
+/*-----------------------------------------------------------------------------
+* MAIN
+*----------------------------------------------------------------------------*/
+int main()
+{
+    int num_size, dgemm_err;
+    int M, N, K, m, n, k;
+    int M_pre, N_pre, K_pre, M_start_size, N_start_size;
+    int offload_threshold_1, offload_threshold_2;
+    double total_GFLOPS_DSP, total_GFLOPS_ARM;
+    double time_DSP, time_ARM, t_dsp, t_arm;
+    char ofld_flag[NUM_MATRIX_SIZE_TO_BENCHMARK][NUM_MATRIX_SIZE_TO_BENCHMARK][NUM_MATRIX_SIZE_TO_BENCHMARK];
+    char mem_flag[NUM_MATRIX_SIZE_TO_BENCHMARK][NUM_MATRIX_SIZE_TO_BENCHMARK][NUM_MATRIX_SIZE_TO_BENCHMARK];
+    int skip_next_point;
+    float diff_tmp, diff_pre;
+    FILE *fp_flag, *fp_time, *fp_tbl;  
+  
+    fp_flag = fopen("ofld_flag_dgemm.dat","w");
+    fp_tbl  = fopen("ofld_tbl_dgemm.c","w");
+    fp_time = fopen("dgemm_time_ARMvsDSP.dat","w");
+
+    fprintf(fp_tbl, "char ofld_tbl_dgemm[TI_L3_OFFLOAD_TBL_SIZE] = {\n");
+    
+    srand(12345);
+    
+    /* sweep M, K, and N */    
+    for (M=TUNING_START_SIZE_RECTAN_MATRIX,m=0; m<NUM_MATRIX_SIZE_TO_BENCHMARK; m++,M*=2) 
+    {
+        for (N=TUNING_START_SIZE_RECTAN_MATRIX,n=0; n<NUM_MATRIX_SIZE_TO_BENCHMARK; n++,N*=2) 
+        {
+            for (K=TUNING_START_SIZE_RECTAN_MATRIX,k=0; k<NUM_MATRIX_SIZE_TO_BENCHMARK; k++,K*=2) 
+            {
+                if(  (m>0 && ofld_flag[m-1][n][k]==OFFLOAD)
+                   ||(n>0 && ofld_flag[m][n-1][k]==OFFLOAD)
+                   ||(k>0 && ofld_flag[m][n][k-1]==OFFLOAD) ) {
+                    ofld_flag[m][n][k] = OFFLOAD;
+                    mem_flag[m][n][k]  = HAS_MEMORY;  // to avoid error
+                    time_DSP = -1.0;
+                    time_ARM = -1.0;
+                    printf("Offloading. Skipping (M,N,K)=(%d,%d,%d), (m,n,k)=(%d,%d,%d).\n", M,N,K,m,n,k);
+                }
+                else if(  (m>0 && (mem_flag[m-1][n][k]==NO_MEMORY))
+                        ||(n>0 && (mem_flag[m][n-1][k]==NO_MEMORY))
+                        ||(k>0 && (mem_flag[m][n][k-1]==NO_MEMORY))) {
+                    ofld_flag[m][n][k] = NO_OFFLOAD;
+                    mem_flag[m][n][k]  = NO_MEMORY;
+                    time_DSP = -2.0;
+                    time_ARM = -2.0;
+                    printf("Out of memory. Skipping (M,N,K)=(%d,%d,%d), (m,n,k)=(%d,%d,%d).\n", M,N,K,m,n,k);
+                }
+                else {                    
+                    printf("Measuring DSP and ARM GFLOPS for (M,N,K)=(%d,%d,%d), (m,n,k)=(%d,%d,%d).\n", M,N,K,m,n,k);
+                    dgemm_err = run_dgemm_dsp_and_arm(M, N, K, &t_dsp, &t_arm, &total_GFLOPS_DSP, &total_GFLOPS_ARM);
+                    //dsym_err  = run_dsymm_dsp_and_arm();
+              
+                    if(dgemm_err == -1) {  /* out of memory for DSP offloading */
+                        ofld_flag[m][n][k] = NO_OFFLOAD;
+                        mem_flag[m][n][k] = NO_MEMORY;
+                        time_DSP = -2.0;
+                        time_ARM = -2.0;
+                        printf("Out of memory, skipping next point.\n");
+                    }
+                    else {
+                        mem_flag[m][n][k] = HAS_MEMORY;                    
+                        time_DSP = t_dsp;
+                        time_ARM = t_arm;
+                        if (dgemm_err == 0){
+                            //if(total_GFLOPS_DSP - total_GFLOPS_ARM > 1.0) {
+                            if(t_dsp < t_arm) {
+                                ofld_flag[m][n][k] = OFFLOAD;
+                                printf("Offloading to DSP for this point. Skipping next point.\n");
+                            }
+                            else {
+                                ofld_flag[m][n][k] = NO_OFFLOAD;
+                            }
+                        }
+                        else {
+                            printf("Error in DGEMM tuning for (M,N,K)=(%d,%d,%d)!\n", M,N,K);
+                            exit(0);
+                        }
+                    }
+                }
+                
+                fprintf(fp_flag, "%d\t%d\n", (int)mem_flag[m][n][k], (int)ofld_flag[m][n][k]);
+                fprintf(fp_time, "%6d,%6d,%6d\t%10.8e\t%10.8e\n", M, N, K, time_ARM, time_DSP);
+
+                if(   (m==(NUM_MATRIX_SIZE_TO_BENCHMARK-1))
+                   && (n==(NUM_MATRIX_SIZE_TO_BENCHMARK-1))
+                   && (k==(NUM_MATRIX_SIZE_TO_BENCHMARK-1))) {
+                  fprintf(fp_tbl, "%d};", (int)ofld_flag[m][n][k]);
+                } else {
+                  fprintf(fp_tbl, "%d,", (int)ofld_flag[m][n][k]);
+                }
+            }
+            fprintf(fp_tbl, "\n");
+        }
+    }
+        
+    fclose(fp_flag);
+    fclose(fp_time);
+    fclose(fp_tbl);
+    
+    return 0;
+}
+
+
+int run_dgemm_dsp_and_arm(int M, int N, int K, double *time_dsp, double *time_arm, 
+                          double *gflops_dsp, double *gflops_arm)
+{
+    int    iter;
+    long long i;
+    double time_secs, total_time_dsp, total_time_arm;
+    double gflops_ARM, gflops_DSP;
+    double operation_count = 2.0*(double)M*(double)N*(double)K;
+    double total_GFLOPS_DSP = 0.0f;
+    double total_GFLOPS_ARM = 0.0f;
+    int    err_code = 0;
+    
+    total_time_dsp = 0.0;
+    total_time_arm = 0.0;
+    for (iter = 0; iter < NUM_TEST_RUN; iter++)
+    {      
+      /*-------------------------------------------------------------------------
+      * Allocate space for the matrices.  The matrices that will be passed to 
+      * the DSP are allocated using device memory.  The Carm array is not passed
+      * to the dsp and so can use system memory.
+      *------------------------------------------------------------------------*/
+      double *A    = (double *) __malloc_ddr((long long)M*(long long)K*(long long)sizeof(double));
+      double *B    = (double *) __malloc_ddr((long long)K*(long long)N*(long long)sizeof(double));
+      double *Cdsp = (double *) __malloc_ddr((long long)M*(long long)N*(long long)sizeof(double));
+      double *Carm = (double *) malloc      ((long long)M*(long long)N*(long long)sizeof(double));
+  
+      if (!A || !B || !Cdsp || !Carm)
+      {
+          printf("Could not allocate enough space for the arrays!");
+          if(A) __free_ddr(A);
+          if(B) __free_ddr(B);
+          if(Cdsp) __free_ddr(Cdsp);
+          if(Carm) free(Carm);
+          
+          return (-1);
+      }
+  
+      /*-------------------------------------------------------------------------
+      * Initialize matrices 
+      *------------------------------------------------------------------------*/
+      for (i = 0; i < (long long)M*K; ++i) A[i] = (double)rand()/RAND_MAX;// (double)(rand() % 5 + 1);
+      for (i = 0; i < (long long)K*N; ++i) B[i] = (double)rand()/RAND_MAX;// (double)(rand() % 5 + 1);
+      for (i = 0; i < (long long)M*N; ++i) Carm[i] = Cdsp[i] = 0;
+  
+      int lda = ((order == CblasColMajor && transA == CblasNoTrans) ||
+              (order == CblasRowMajor && transA == CblasTrans)) ? M : K;
+  
+      int ldb = ((order == CblasColMajor && transB == CblasNoTrans) ||
+              (order == CblasRowMajor && transB == CblasTrans)) ? K : N;
+  
+      int ldc = (order == CblasColMajor) ? M : N;
+  
+      fflush(stdout);
+  
+      /*============ BLAS tuning: running on DSP and then on ARM =============*/
+      /*------------------------------------------------------------------------
+      * Time DSP dgemm
+      *-----------------------------------------------------------------------*/
+      //ti_cblas_offload_config("001");  /* force offloading level 3 to DSP */
+      //printf("Running on DSP.\n");
+      TI_CBLAS_L3_OFFLOAD = 1;
+      
+      tick();
+      cblas_dgemm(order,transA,transB,M,N,K,alpha,A,lda,B,ldb,beta,Cdsp,ldc);
+      time_secs = tock();
+      total_time_dsp += time_secs;
+      gflops_DSP = operation_count/time_secs*1e-9;
+      total_GFLOPS_DSP += gflops_DSP;
+/*      
+      if(M==4096 && K==256 && N==16) {
+          FILE *file_a = fopen("mat_a.dat","w");
+          FILE *file_b = fopen("mat_b.dat","w");
+          FILE *file_c = fopen("mat_c.dat","w");
+          
+          for(i=0; i < M*K; ++i) fprintf(file_a, "%1.10e\n",A[i]);
+          for(i=0; i < K*N; ++i) fprintf(file_b, "%1.10e\n",B[i]);
+          for(i=0; i < M*N; ++i) fprintf(file_c, "%1.10e\n",Cdsp[i]);
+      }
+*/      
+      /*-------------------------------------------------------------------------
+      * Time ARM dgemm
+      *------------------------------------------------------------------------*/
+      //ti_cblas_offload_config("000");  /* force no offloading */
+      //printf("Running on ARM.\n");
+      TI_CBLAS_L3_OFFLOAD = 0;
+      
+      tick();
+      cblas_dgemm(order,transA,transB,M,N,K,alpha,A,lda,B,ldb,beta,Carm,ldc);
+      time_secs = tock();
+      total_time_arm += time_secs;
+      gflops_ARM = operation_count/time_secs*1e-9;
+      total_GFLOPS_ARM += gflops_ARM;
+      //printf(" %6.3f  %6.3f  %9.6fs %9.6fs\n", gflops_DSP, gflops_ARM, time_dsp, time_arm);
+      fflush(stdout);
+  
+      /*-------------------------------------------------------------------------
+      * Verify Results
+      *------------------------------------------------------------------------*/
+      //return check_results(Cdsp, Carm, M, N);
+      err_code += check_results(Cdsp, Carm, M, N);
+  
+      __free_ddr(A);
+      __free_ddr(B);
+      __free_ddr(Cdsp);
+      free(Carm);
+    }
+    
+    *gflops_dsp = total_GFLOPS_DSP;
+    *gflops_arm = total_GFLOPS_ARM;
+    *time_dsp   = total_time_dsp / (double)NUM_TEST_RUN;
+    *time_arm   = total_time_arm / (double)NUM_TEST_RUN;
+    
+    return err_code;
+}
+
+
+/*-----------------------------------------------------------------------------
+* check_results
+*----------------------------------------------------------------------------*/
+int check_results(const double *C1, const double *C2, int M, int N)
+{
+    int i;
+    const double EPISILON = 1e-10;
+    //const double EPISILON = 1e-200;
+    const int NERRORS  = 5;
+    int       num_errors = 0;
+
+    for (i=0; i<(long)M*N; i++)
+    {
+        double delta = fabs(C1[i] - C2[i]);
+        if (delta > EPISILON*fabs(C1[i]))
+            if ((num_errors += 1) < NERRORS)
+                printf("Error [elem:%d]: %e <==> %e\n", i, C1[i], C2[i]);
+    }
+
+    if (num_errors > 0)
+    {
+         printf("FAIL with %d errors!\n", num_errors);
+         return num_errors;
+    }
+    else 
+    {
+        //printf("PASS!\n");
+        return 0;
+    }
+}
+
+
diff --git a/examples/tuning/make.inc b/examples/tuning/make.inc
new file mode 100644 (file)
index 0000000..0125a07
--- /dev/null
@@ -0,0 +1,24 @@
+
+
+CC = gcc
+CFLAGS = -g -O2 -I/usr/include
+
+BLAS_LIB_DIR = /usr/lib/
+BLASLIB = $(BLAS_LIB_DIR)libcblas_armplusdsp.a $(BLAS_LIB_DIR)libblis.a -lOpenCL -locl_util -lstdc++ -lrt -lm -lgomp
+
+
+%.o: %.c
+       @$(CC) -c $(CFLAGS) $<
+       @echo Compiling $<
+
+$(EXE):
+
+cross: $(EXE)
+
+clean::
+       @rm -f $(EXE) *.o *.obj *.out *.asm *.if *.opt *.bc *.objc *.map *.bin *.dsp_h
+
+test: clean $(EXE)
+       @echo Running   $(EXE)
+       @./$(EXE) >> /dev/null
+       @if [ $$? -ne 0 ] ; then echo "FAILED !!!" ; fi
diff --git a/examples/tuning/sgemm_test/Makefile b/examples/tuning/sgemm_test/Makefile
new file mode 100644 (file)
index 0000000..f45482f
--- /dev/null
@@ -0,0 +1,8 @@
+
+EXE = sgemm_test
+
+include ../make.inc
+
+$(EXE): sgemm_test.o
+       $(CC) $(CFLAGS) sgemm_test.o $(BLASLIB) -o $@
+
diff --git a/examples/tuning/sgemm_test/sgemm_test.c b/examples/tuning/sgemm_test/sgemm_test.c
new file mode 100644 (file)
index 0000000..9a35652
--- /dev/null
@@ -0,0 +1,203 @@
+/******************************************************************************
+ * Copyright (c) 2013-2014, Texas Instruments Incorporated - http://www.ti.com/
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions are met:
+ *       * Redistributions of source code must retain the above copyright
+ *         notice, this list of conditions and the following disclaimer.
+ *       * 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.
+ *       * Neither the name of Texas Instruments Incorporated nor the
+ *         names of its contributors may be used to endorse or promote products
+ *         derived from this software without specific prior 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 COPYRIGHT OWNER OR 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 <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include <time.h>
+
+#include "cblas.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include "cblas.h"
+#ifdef __cplusplus
+}
+#endif
+
+#define TUNING_START_SIZE_SQUARE_MATRIX 16
+#define TUNING_START_SIZE_RECTAN_MATRIX 8
+#define NUM_MATRIX_SIZE_TO_BENCHMARK 16
+#define HAS_MEMORY   1
+#define NO_MEMORY    0
+#define OFFLOAD      1
+#define NO_OFFLOAD   0
+
+#define NUM_TEST_RUN 5
+
+
+/*-----------------------------------------------------------------------------
+* Timing Setup
+*----------------------------------------------------------------------------*/
+struct timespec t0,t1;
+#define tick()  clock_gettime(CLOCK_MONOTONIC, &t0);
+#define tock() (clock_gettime(CLOCK_MONOTONIC, &t1), \
+                        t1.tv_sec - t0.tv_sec + (t1.tv_nsec - t0.tv_nsec) / 1e9)
+
+/*-----------------------------------------------------------------------------
+* Global Variables
+*----------------------------------------------------------------------------*/
+float alpha           = 0.7; 
+float beta            = 0.3;
+enum CBLAS_ORDER     order  = CblasColMajor; 
+//enum CBLAS_ORDER     order  = CblasRowMajor;
+enum CBLAS_TRANSPOSE transA = CblasNoTrans;
+enum CBLAS_TRANSPOSE transB = CblasNoTrans;
+
+extern int TI_CBLAS_L3_OFFLOAD;
+/*-----------------------------------------------------------------------------
+* Prototypes
+*----------------------------------------------------------------------------*/
+int run_sgemm(int M, int N, int K, float *time, float *gflops);
+
+/*-----------------------------------------------------------------------------
+* MAIN
+*----------------------------------------------------------------------------*/
+int main()
+{
+    int num_size, dgemm_err;
+    int M, N, K, m, n, k;
+    int M_pre, N_pre, K_pre, M_start_size, N_start_size;
+    float time_secs, gflops;
+    FILE *fp_time;  
+  
+    fp_time = fopen("dgemm_time.dat","w");
+
+    srand(12345);
+    
+    /* sweep M, K, and N */    
+    for (M=TUNING_START_SIZE_RECTAN_MATRIX,m=0; m<NUM_MATRIX_SIZE_TO_BENCHMARK; m++,M*=2) 
+    {
+        for (N=TUNING_START_SIZE_RECTAN_MATRIX,n=0; n<NUM_MATRIX_SIZE_TO_BENCHMARK; n++,N*=2) 
+        {
+            for (K=TUNING_START_SIZE_RECTAN_MATRIX,k=0; k<NUM_MATRIX_SIZE_TO_BENCHMARK; k++,K*=2) 
+            {
+                dgemm_err = run_sgemm(M, N, K, &time_secs, &gflops);
+          
+                if(dgemm_err == -1) {  /* out of memory for DSP offloading */
+                    printf("Out of memory for (M,N,K) = (%d,%d,%d).\n", M,N,K);
+                }
+                else {
+                    if (dgemm_err == 0){
+                        fprintf(fp_time, "%6d,%6d,%6d\t%10.8e\n", M, N, K, time_secs);
+                    }
+                    else {
+                        printf("Error in DGEMM tuning for (M,N,K)=(%d,%d,%d)!\n", M,N,K);
+                        exit(0);
+                    }
+                }
+            }
+        }
+    }
+        
+    fclose(fp_time);
+    
+    return 0;
+}
+
+
+int run_sgemm(int M, int N, int K, float *time, float *gflops)
+{
+    int    iter;
+    long long i;
+    float time_secs, total_time;
+    float operation_count = 2.0*(float)M*(float)N*(float)K;
+    float total_GFLOPS = 0.0f;
+    int    err_code = 0;
+    
+    total_time = 0.0;
+    for (iter = 0; iter < NUM_TEST_RUN; iter++)
+    {      
+      /*-------------------------------------------------------------------------
+      * Allocate space for the matrices.  The matrices that will be passed to 
+      * the DSP are allocated using device memory.  The Carm array is not passed
+      * to the dsp and so can use system memory.
+      *------------------------------------------------------------------------*/
+      float *A    = (float *) __malloc_ddr((long long)M*(long long)K*(long long)sizeof(float));
+      float *B    = (float *) __malloc_ddr((long long)K*(long long)N*(long long)sizeof(float));
+      float *Cdsp = (float *) __malloc_ddr((long long)M*(long long)N*(long long)sizeof(float));
+      float *Carm = (float *) malloc      ((long long)M*(long long)N*(long long)sizeof(float));
+  
+      if (!A || !B || !Cdsp || !Carm)
+      {
+          printf("Could not allocate enough space for the arrays!");
+          if(A) __free_ddr(A);
+          if(B) __free_ddr(B);
+          if(Cdsp) __free_ddr(Cdsp);
+          if(Carm) free(Carm);
+          
+          return (-1);
+      }
+  
+      /*-------------------------------------------------------------------------
+      * Initialize matrices 
+      *------------------------------------------------------------------------*/
+      for (i = 0; i < (long long)M*K; ++i) A[i] = (float)rand()/RAND_MAX;// (float)(rand() % 5 + 1);
+      for (i = 0; i < (long long)K*N; ++i) B[i] = (float)rand()/RAND_MAX;// (float)(rand() % 5 + 1);
+      for (i = 0; i < (long long)M*N; ++i) Carm[i] = Cdsp[i] = 0;
+  
+      int lda = ((order == CblasColMajor && transA == CblasNoTrans) ||
+              (order == CblasRowMajor && transA == CblasTrans)) ? M : K;
+  
+      int ldb = ((order == CblasColMajor && transB == CblasNoTrans) ||
+              (order == CblasRowMajor && transB == CblasTrans)) ? K : N;
+  
+      int ldc = (order == CblasColMajor) ? M : N;
+  
+      fflush(stdout);
+  
+      /*------------------------------------------------------------------------
+      * Run and time dgemm
+      *-----------------------------------------------------------------------*/
+      tick();
+      cblas_dgemm(order,transA,transB,M,N,K,alpha,A,lda,B,ldb,beta,Cdsp,ldc);
+      time_secs = tock();
+      total_time += time_secs;
+      total_GFLOPS += operation_count/time_secs*1e-9;
+/*      
+      if(M==4096 && K==256 && N==16) {
+          FILE *file_a = fopen("mat_a.dat","w");
+          FILE *file_b = fopen("mat_b.dat","w");
+          FILE *file_c = fopen("mat_c.dat","w");
+          
+          for(i=0; i < M*K; ++i) fprintf(file_a, "%1.10e\n",A[i]);
+          for(i=0; i < K*N; ++i) fprintf(file_b, "%1.10e\n",B[i]);
+          for(i=0; i < M*N; ++i) fprintf(file_c, "%1.10e\n",Cdsp[i]);
+      }
+*/      
+
+      __free_ddr(A);
+      __free_ddr(B);
+      __free_ddr(Cdsp);
+      free(Carm);
+    }
+    
+    *gflops = total_GFLOPS / (float)NUM_TEST_RUN;
+    *time   = total_time / (float)NUM_TEST_RUN;
+    
+    return err_code;
+}
diff --git a/examples/tuning/sgemm_tune/Makefile b/examples/tuning/sgemm_tune/Makefile
new file mode 100644 (file)
index 0000000..569cae6
--- /dev/null
@@ -0,0 +1,10 @@
+
+EXE = sgemm_tune
+
+include ../make.inc
+
+$(EXE): sgemm_tune.o
+       $(CC) $(CFLAGS) sgemm_tune.o $(BLASLIB) -o $@
+
+tune: $(EXE)
+       ./$(EXE);
\ No newline at end of file
diff --git a/examples/tuning/sgemm_tune/sgemm_tune.c b/examples/tuning/sgemm_tune/sgemm_tune.c
new file mode 100644 (file)
index 0000000..16b2828
--- /dev/null
@@ -0,0 +1,331 @@
+/******************************************************************************
+ * Copyright (c) 2013-2014, Texas Instruments Incorporated - http://www.ti.com/
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions are met:
+ *       * Redistributions of source code must retain the above copyright
+ *         notice, this list of conditions and the following disclaimer.
+ *       * 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.
+ *       * Neither the name of Texas Instruments Incorporated nor the
+ *         names of its contributors may be used to endorse or promote products
+ *         derived from this software without specific prior 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 COPYRIGHT OWNER OR 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 <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include <time.h>
+
+#include "cblas.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include "cblas.h"
+#ifdef __cplusplus
+}
+#endif
+
+#define TUNING_START_SIZE_SQUARE_MATRIX 16
+#define TUNING_START_SIZE_RECTAN_MATRIX 8
+#define NUM_MATRIX_SIZE_TO_BENCHMARK 16
+#define HAS_MEMORY   1
+#define NO_MEMORY    0
+#define OFFLOAD      1
+#define NO_OFFLOAD   0
+
+#define NUM_TEST_RUN 5
+
+
+/*-----------------------------------------------------------------------------
+* Timing Setup
+*----------------------------------------------------------------------------*/
+struct timespec t0,t1;
+#define tick()  clock_gettime(CLOCK_MONOTONIC, &t0);
+#define tock() (clock_gettime(CLOCK_MONOTONIC, &t1), \
+                        t1.tv_sec - t0.tv_sec + (t1.tv_nsec - t0.tv_nsec) / 1e9)
+
+/*-----------------------------------------------------------------------------
+* Global Variables
+*----------------------------------------------------------------------------*/
+float alpha           = 0.7; 
+float beta            = 0.3;
+enum CBLAS_ORDER     order  = CblasColMajor; 
+//enum CBLAS_ORDER     order  = CblasRowMajor;
+enum CBLAS_TRANSPOSE transA = CblasNoTrans;
+enum CBLAS_TRANSPOSE transB = CblasNoTrans;
+
+extern int TI_CBLAS_L3_OFFLOAD;
+
+/*-----------------------------------------------------------------------------
+* Prototypes
+*----------------------------------------------------------------------------*/
+int check_results(const float *C1, const float *C2, int M, int N);
+int run_sgemm_dsp_and_arm(int M, int N, int K, float *time_dsp, float *time_arm, 
+                          float *gflops_dsp, float *gflops_arm);
+
+/*-----------------------------------------------------------------------------
+* MAIN
+*----------------------------------------------------------------------------*/
+int main()
+{
+    int num_size, sgemm_err;
+    int M, N, K, m, n, k;
+    int M_pre, N_pre, K_pre, M_start_size, N_start_size;
+    int offload_threshold_1, offload_threshold_2;
+    float total_GFLOPS_DSP, total_GFLOPS_ARM;
+    float time_DSP, time_ARM, t_dsp, t_arm;
+    char ofld_flag[NUM_MATRIX_SIZE_TO_BENCHMARK][NUM_MATRIX_SIZE_TO_BENCHMARK][NUM_MATRIX_SIZE_TO_BENCHMARK];
+    char mem_flag[NUM_MATRIX_SIZE_TO_BENCHMARK][NUM_MATRIX_SIZE_TO_BENCHMARK][NUM_MATRIX_SIZE_TO_BENCHMARK];
+    int skip_next_point;
+    float diff_tmp, diff_pre;
+    FILE *fp_flag, *fp_time, *fp_tbl;  
+  
+    fp_flag = fopen("ofld_flag_sgemm.dat","w");
+    fp_tbl  = fopen("ofld_tbl_sgemm.c","w");
+    fp_time = fopen("sgemm_time_ARMvsDSP.dat","w");
+
+    fprintf(fp_tbl, "char ofld_tbl_sgemm[TI_L3_OFFLOAD_TBL_SIZE] = {\n");
+    
+    srand(12345);
+    
+    /* sweep M, K, and N */    
+    for (M=TUNING_START_SIZE_RECTAN_MATRIX,m=0; m<NUM_MATRIX_SIZE_TO_BENCHMARK; m++,M*=2) 
+    {
+        for (N=TUNING_START_SIZE_RECTAN_MATRIX,n=0; n<NUM_MATRIX_SIZE_TO_BENCHMARK; n++,N*=2) 
+        {    
+            for (K=TUNING_START_SIZE_RECTAN_MATRIX,k=0; k<NUM_MATRIX_SIZE_TO_BENCHMARK; k++,K*=2) 
+            {
+                if(  (m>0 && ofld_flag[m-1][n][k]==OFFLOAD)
+                   ||(n>0 && ofld_flag[m][n-1][k]==OFFLOAD)
+                   ||(k>0 && ofld_flag[m][n][k-1]==OFFLOAD) ) {
+                    ofld_flag[m][n][k] = OFFLOAD;
+                    mem_flag[m][n][k]  = HAS_MEMORY;  // to avoid error
+                    time_DSP = -1.0;
+                    time_ARM = -1.0;
+                    printf("Offloading. Skipping (M,N,K)=(%d,%d,%d), (m,n,k)=(%d,%d,%d).\n", M,N,K,m,n,k);
+                }
+                else if(  (m>0 && (mem_flag[m-1][n][k]==NO_MEMORY))
+                        ||(n>0 && (mem_flag[m][n-1][k]==NO_MEMORY))
+                        ||(k>0 && (mem_flag[m][n][k-1]==NO_MEMORY))) {
+                    ofld_flag[m][n][k] = NO_OFFLOAD;
+                    mem_flag[m][n][k]  = NO_MEMORY;
+                    time_DSP = -2.0;
+                    time_ARM = -2.0;
+                    printf("Out of memory. Skipping (M,N,K)=(%d,%d,%d), (m,n,k)=(%d,%d,%d).\n", M,N,K,m,n,k);
+                }
+                else {                    
+                    printf("Measuring DSP and ARM GFLOPS for (M,N,K)=(%d,%d,%d), (m,n,k)=(%d,%d,%d).\n", M,N,K,m,n,k);
+                    sgemm_err = run_sgemm_dsp_and_arm(M, N, K, &t_dsp, &t_arm, &total_GFLOPS_DSP, &total_GFLOPS_ARM);
+              
+                    if(sgemm_err == -1) {  /* out of memory for DSP offloading */
+                        ofld_flag[m][n][k] = NO_OFFLOAD;
+                        mem_flag[m][n][k] = NO_MEMORY;
+                        time_DSP = -2.0;
+                        time_ARM = -2.0;
+                        printf("Out of memory, skipping next point.\n");
+                    }
+                    else {
+                        mem_flag[m][n][k] = HAS_MEMORY;                    
+                        time_DSP = t_dsp;
+                        time_ARM = t_arm;
+                        if (sgemm_err == 0){
+                            //if(total_GFLOPS_DSP - total_GFLOPS_ARM > 1.0) {
+                            if(t_dsp < t_arm) {
+                                ofld_flag[m][n][k] = OFFLOAD;
+                                printf("Offloading to DSP for this point. Skipping next point.\n");
+                            }
+                            else {
+                                ofld_flag[m][n][k] = NO_OFFLOAD;
+                            }
+                        }
+                        else {
+                            printf("Error in SGEMM tuning for (M,N,K)=(%d,%d,%d)!\n", M,N,K);
+                            exit(0);
+                        }
+                    }
+                }
+                
+                fprintf(fp_flag, "%d\t%d\n", (int)mem_flag[m][n][k], (int)ofld_flag[m][n][k]);
+                fprintf(fp_time, "%6d,%6d,%6d\t%10.8e\t%10.8e\n", M, N, K, time_ARM, time_DSP);
+
+                if(   (m==(NUM_MATRIX_SIZE_TO_BENCHMARK-1))
+                   && (n==(NUM_MATRIX_SIZE_TO_BENCHMARK-1))
+                   && (k==(NUM_MATRIX_SIZE_TO_BENCHMARK-1))) {
+                  fprintf(fp_tbl, "%d};", (int)ofld_flag[m][n][k]);
+                } else {
+                  fprintf(fp_tbl, "%d,", (int)ofld_flag[m][n][k]);
+                }
+            }
+            fprintf(fp_tbl, "\n");
+        }
+    }
+       
+    fclose(fp_flag);
+    fclose(fp_time);
+    fclose(fp_tbl);
+    
+    return 0;
+}
+
+
+int run_sgemm_dsp_and_arm(int M, int N, int K, float *time_dsp, float *time_arm, 
+                          float *gflops_dsp, float *gflops_arm)
+{
+    int    iter;
+    long long i;
+    float time_secs, total_time_dsp, total_time_arm;
+    float gflops_ARM, gflops_DSP;
+    float operation_count = 2.0*(float)M*(float)N*(float)K;
+    float total_GFLOPS_DSP = 0.0f;
+    float total_GFLOPS_ARM = 0.0f;
+    int    err_code = 0;
+    
+    total_time_dsp = 0.0;
+    total_time_arm = 0.0;
+    for (iter = 0; iter < NUM_TEST_RUN; iter++)
+    {      
+      /*-------------------------------------------------------------------------
+      * Allocate space for the matrices.  The matrices that will be passed to 
+      * the DSP are allocated using device memory.  The Carm array is not passed
+      * to the dsp and so can use system memory.
+      *------------------------------------------------------------------------*/
+      float *A    = (float *) __malloc_ddr((long long)M*(long long)K*(long long)sizeof(float));
+      float *B    = (float *) __malloc_ddr((long long)K*(long long)N*(long long)sizeof(float));
+      float *Cdsp = (float *) __malloc_ddr((long long)M*(long long)N*(long long)sizeof(float));
+      float *Carm = (float *) malloc      ((long long)M*(long long)N*(long long)sizeof(float));
+  
+      if (!A || !B || !Cdsp || !Carm)
+      {
+          printf("Could not allocate enough space for the arrays!");
+          if(A) __free_ddr(A);
+          if(B) __free_ddr(B);
+          if(Cdsp) __free_ddr(Cdsp);
+          if(Carm) free(Carm);
+          
+          return (-1);
+      }
+  
+      /*-------------------------------------------------------------------------
+      * Initialize matrices 
+      *------------------------------------------------------------------------*/
+      for (i = 0; i < (long long)M*K; ++i) A[i] = (float)rand()/RAND_MAX;
+      for (i = 0; i < (long long)K*N; ++i) B[i] = (float)rand()/RAND_MAX;
+      for (i = 0; i < (long long)M*N; ++i) Carm[i] = Cdsp[i] = 0;
+  
+      int lda = ((order == CblasColMajor && transA == CblasNoTrans) ||
+              (order == CblasRowMajor && transA == CblasTrans)) ? M : K;
+  
+      int ldb = ((order == CblasColMajor && transB == CblasNoTrans) ||
+              (order == CblasRowMajor && transB == CblasTrans)) ? K : N;
+  
+      int ldc = (order == CblasColMajor) ? M : N;
+    
+      /*============ BLAS tuning: running on DSP and then on ARM =============*/
+      /*------------------------------------------------------------------------
+      * Time DSP sgemm
+      *-----------------------------------------------------------------------*/
+      //ti_cblas_offload_config("001");  /* force offloading level 3 to DSP */
+      //printf("Running on DSP.\n");
+      TI_CBLAS_L3_OFFLOAD = 1;
+      
+      tick();
+      cblas_sgemm(order,transA,transB,M,N,K,alpha,A,lda,B,ldb,beta,Cdsp,ldc);
+      time_secs = tock();
+      total_time_dsp += time_secs;
+      gflops_DSP = operation_count/time_secs*1e-9;
+      total_GFLOPS_DSP += gflops_DSP;
+/*      
+      if(M==4096 && K==256 && N==16) {
+          FILE *file_a = fopen("mat_a.dat","w");
+          FILE *file_b = fopen("mat_b.dat","w");
+          FILE *file_c = fopen("mat_c.dat","w");
+          
+          for(i=0; i < M*K; ++i) fprintf(file_a, "%1.10e\n",A[i]);
+          for(i=0; i < K*N; ++i) fprintf(file_b, "%1.10e\n",B[i]);
+          for(i=0; i < M*N; ++i) fprintf(file_c, "%1.10e\n",Cdsp[i]);
+      }
+*/      
+      /*-------------------------------------------------------------------------
+      * Time ARM sgemm
+      *------------------------------------------------------------------------*/
+      //ti_cblas_offload_config("000");  /* force no offloading */
+      //printf("Running on ARM.\n");
+      TI_CBLAS_L3_OFFLOAD = 0;
+      
+      tick();
+      cblas_sgemm(order,transA,transB,M,N,K,alpha,A,lda,B,ldb,beta,Carm,ldc);
+      time_secs = tock();
+      total_time_arm += time_secs;
+      gflops_ARM = operation_count/time_secs*1e-9;
+      total_GFLOPS_ARM += gflops_ARM;
+      //printf(" %6.3f  %6.3f  %9.6fs %9.6fs\n", gflops_DSP, gflops_ARM, time_dsp, time_arm);
+      fflush(stdout);
+  
+      /*-------------------------------------------------------------------------
+      * Verify Results
+      *------------------------------------------------------------------------*/
+      //return check_results(Cdsp, Carm, M, N);
+      err_code += check_results(Cdsp, Carm, M, N);
+  
+      __free_ddr(A);
+      __free_ddr(B);
+      __free_ddr(Cdsp);
+      free(Carm);
+    }
+    
+    *gflops_dsp = total_GFLOPS_DSP;
+    *gflops_arm = total_GFLOPS_ARM;
+    *time_dsp   = total_time_dsp / (float)NUM_TEST_RUN;
+    *time_arm   = total_time_arm / (float)NUM_TEST_RUN;
+    
+    return err_code;
+}
+
+
+/*-----------------------------------------------------------------------------
+* check_results
+*----------------------------------------------------------------------------*/
+int check_results(const float *C1, const float *C2, int M, int N)
+{
+    int i;
+    const float EPISILON = 1e-5;
+    //const float EPISILON = 1e-200;
+    const int NERRORS  = 5;
+    int       num_errors = 0;
+
+    for (i=0; i<(long)M*N; i++)
+    {
+        float delta = fabs(C1[i] - C2[i]);
+
+        if (delta > EPISILON*fabs(C1[i]))
+            if ((num_errors += 1) < NERRORS)
+                printf("Error [elem:%d]: %e <==> %e\n", i, C1[i], C2[i]);
+    }
+
+    if (num_errors > 0)
+    {
+         printf("FAIL with %d errors!\n", num_errors);
+         return num_errors;
+    }
+    else 
+    {
+        //printf("PASS!\n");
+        return 0;
+    }
+}
+
+
diff --git a/examples/tuning/zgemm_tune/Makefile b/examples/tuning/zgemm_tune/Makefile
new file mode 100644 (file)
index 0000000..ffb2cc4
--- /dev/null
@@ -0,0 +1,10 @@
+
+EXE = zgemm_tune
+
+include ../make.inc
+
+$(EXE): zgemm_tune.o
+       $(CC) $(CFLAGS) zgemm_tune.o $(BLASLIB) -o $@
+
+tune: $(EXE)
+       ./$(EXE);
\ No newline at end of file
diff --git a/examples/tuning/zgemm_tune/zgemm_tune.c b/examples/tuning/zgemm_tune/zgemm_tune.c
new file mode 100644 (file)
index 0000000..31bf097
--- /dev/null
@@ -0,0 +1,325 @@
+/******************************************************************************
+ * Copyright (c) 2013-2014, Texas Instruments Incorporated - http://www.ti.com/
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions are met:
+ *       * Redistributions of source code must retain the above copyright
+ *         notice, this list of conditions and the following disclaimer.
+ *       * 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.
+ *       * Neither the name of Texas Instruments Incorporated nor the
+ *         names of its contributors may be used to endorse or promote products
+ *         derived from this software without specific prior 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 COPYRIGHT OWNER OR 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 <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include <time.h>
+#include <complex.h>
+
+#include "cblas.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include "cblas.h"
+#ifdef __cplusplus
+}
+#endif
+
+#define TUNING_START_SIZE_SQUARE_MATRIX 16
+#define TUNING_START_SIZE_RECTAN_MATRIX 8
+#define NUM_MATRIX_SIZE_TO_BENCHMARK 16
+#define HAS_MEMORY   1
+#define NO_MEMORY    0
+#define OFFLOAD      1
+#define NO_OFFLOAD   0
+
+#define NUM_TEST_RUN 5
+
+/*-----------------------------------------------------------------------------
+* Timing Setup
+*----------------------------------------------------------------------------*/
+struct timespec t0,t1;
+#define tick()  clock_gettime(CLOCK_MONOTONIC, &t0);
+#define tock() (clock_gettime(CLOCK_MONOTONIC, &t1), \
+                        t1.tv_sec - t0.tv_sec + (t1.tv_nsec - t0.tv_nsec) / 1e9)
+
+/*-----------------------------------------------------------------------------
+* Global Variables
+*----------------------------------------------------------------------------*/
+double complex alpha = 0.7 - 0.3*I; 
+double complex beta  = 0.4 + 0.6*I;
+enum CBLAS_ORDER     order  = CblasColMajor; 
+enum CBLAS_TRANSPOSE transA = CblasNoTrans;
+enum CBLAS_TRANSPOSE transB = CblasNoTrans;
+
+extern int TI_CBLAS_L3_OFFLOAD;
+
+/*-----------------------------------------------------------------------------
+* Prototypes
+*----------------------------------------------------------------------------*/
+int check_results(const double complex *C1, const double complex *C2, int M, int N);
+int run_zgemm_dsp_and_arm(int M, int N, int K, float *time_dsp, float *time_arm, 
+                          float *gflops_dsp, float *gflops_arm);
+
+/*-----------------------------------------------------------------------------
+* MAIN
+*----------------------------------------------------------------------------*/
+int main()
+{
+    int num_size, zgemm_err;
+    int M, N, K, m, n, k;
+    int M_pre, N_pre, K_pre, M_start_size, N_start_size;
+    int offload_threshold_1, offload_threshold_2;
+    float total_GFLOPS_DSP, total_GFLOPS_ARM;
+    float time_DSP, time_ARM, t_dsp, t_arm;
+    char ofld_flag[NUM_MATRIX_SIZE_TO_BENCHMARK][NUM_MATRIX_SIZE_TO_BENCHMARK][NUM_MATRIX_SIZE_TO_BENCHMARK];
+    char mem_flag[NUM_MATRIX_SIZE_TO_BENCHMARK][NUM_MATRIX_SIZE_TO_BENCHMARK][NUM_MATRIX_SIZE_TO_BENCHMARK];
+    int skip_next_point;
+    FILE *fp_flag, *fp_time, *fp_tbl;  
+  
+    fp_flag = fopen("ofld_flag_zgemm.dat","w");
+    fp_tbl  = fopen("ofld_tbl_zgemm.c","w");
+    fp_time = fopen("zgemm_time_ARMvsDSP.dat","w");
+
+    fprintf(fp_tbl, "char ofld_tbl_zgemm[TI_L3_OFFLOAD_TBL_SIZE] = {\n");
+    
+    srand(12345);
+    
+    /* sweep M, K, and N */    
+    for (M=TUNING_START_SIZE_RECTAN_MATRIX,m=0; m<NUM_MATRIX_SIZE_TO_BENCHMARK; m++,M*=2) 
+    {
+        for (N=TUNING_START_SIZE_RECTAN_MATRIX,n=0; n<NUM_MATRIX_SIZE_TO_BENCHMARK; n++,N*=2) 
+        {
+            for (K=TUNING_START_SIZE_RECTAN_MATRIX,k=0; k<NUM_MATRIX_SIZE_TO_BENCHMARK; k++,K*=2) 
+            {
+                if(  (m>0 && ofld_flag[m-1][n][k]==OFFLOAD)
+                   ||(n>0 && ofld_flag[m][n-1][k]==OFFLOAD)
+                   ||(k>0 && ofld_flag[m][n][k-1]==OFFLOAD) ) {
+                    ofld_flag[m][n][k] = OFFLOAD;
+                    mem_flag[m][n][k]  = HAS_MEMORY;  // to avoid error
+                    time_DSP = -1.0;
+                    time_ARM = -1.0;
+                    printf("Offloading. Skipping (M,N,K)=(%d,%d,%d), (m,n,k)=(%d,%d,%d).\n", M,N,K,m,n,k);
+                }
+                else if(  (m>0 && (mem_flag[m-1][n][k]==NO_MEMORY))
+                        ||(n>0 && (mem_flag[m][n-1][k]==NO_MEMORY))
+                        ||(k>0 && (mem_flag[m][n][k-1]==NO_MEMORY))) {
+                    ofld_flag[m][n][k] = NO_OFFLOAD;
+                    mem_flag[m][n][k]  = NO_MEMORY;
+                    time_DSP = -2.0;
+                    time_ARM = -2.0;
+                    printf("Out of memory. Skipping (M,N,K)=(%d,%d,%d), (m,n,k)=(%d,%d,%d).\n", M,N,K,m,n,k);
+                }
+                else {                    
+                    printf("Measuring DSP and ARM GFLOPS for (M,N,K)=(%d,%d,%d), (m,n,k)=(%d,%d,%d).\n", M,N,K,m,n,k);
+                    zgemm_err = run_zgemm_dsp_and_arm(M, N, K, &t_dsp, &t_arm, &total_GFLOPS_DSP, &total_GFLOPS_ARM);
+                    //dsym_err  = run_dsymm_dsp_and_arm();
+              
+                    if(zgemm_err == -1) {  /* out of memory for DSP offloading */
+                        ofld_flag[m][n][k] = NO_OFFLOAD;
+                        mem_flag[m][n][k] = NO_MEMORY;
+                        time_DSP = -2.0;
+                        time_ARM = -2.0;
+                        printf("Out of memory, skipping next point.\n");
+                    }
+                    else {
+                        mem_flag[m][n][k] = HAS_MEMORY;                    
+                        time_DSP = t_dsp;
+                        time_ARM = t_arm;
+                        if (zgemm_err == 0){
+                            //if(total_GFLOPS_DSP - total_GFLOPS_ARM > 1.0) {
+                            if(t_dsp < t_arm) {
+                                ofld_flag[m][n][k] = OFFLOAD;
+                                printf("Offloading to DSP for this point. Skipping next point.\n");
+                            }
+                            else {
+                                ofld_flag[m][n][k] = NO_OFFLOAD;
+                            }
+                        }
+                        else {
+                            printf("Error in DGEMM tuning for (M,N,K)=(%d,%d,%d)!\n", M,N,K);
+                            exit(0);
+                        }
+                    }
+                }
+                
+                fprintf(fp_flag, "%d\t%d\n", (int)mem_flag[m][n][k], (int)ofld_flag[m][n][k]);
+                fprintf(fp_time, "%6d,%6d,%6d\t%10.8e\t%10.8e\n", M, N, K, time_ARM, time_DSP);
+
+                if(   (m==(NUM_MATRIX_SIZE_TO_BENCHMARK-1))
+                   && (n==(NUM_MATRIX_SIZE_TO_BENCHMARK-1))
+                   && (k==(NUM_MATRIX_SIZE_TO_BENCHMARK-1))) {
+                  fprintf(fp_tbl, "%d};", (int)ofld_flag[m][n][k]);
+                } else {
+                  fprintf(fp_tbl, "%d,", (int)ofld_flag[m][n][k]);
+                }
+            }
+            fprintf(fp_tbl, "\n");
+        }
+    }
+        
+    fclose(fp_flag);
+    fclose(fp_time);
+    fclose(fp_tbl);
+    
+    return 0;
+}
+
+
+int run_zgemm_dsp_and_arm(int M, int N, int K, float *time_dsp, float *time_arm, 
+                          float *gflops_dsp, float *gflops_arm)
+{
+    int    iter;
+    long long i;
+    float time_secs, total_time_dsp, total_time_arm;
+    float gflops_ARM, gflops_DSP;
+    float operation_count = 2.0*(float)M*(float)N*(float)K;
+    float total_GFLOPS_DSP = 0.0f;
+    float total_GFLOPS_ARM = 0.0f;
+    int    err_code = 0;
+    
+    total_time_dsp = 0.0;
+    total_time_arm = 0.0;
+    for (iter = 0; iter < NUM_TEST_RUN; iter++)
+    {      
+      /*-------------------------------------------------------------------------
+      * Allocate space for the matrices.  The matrices that will be passed to 
+      * the DSP are allocated using device memory.  The Carm array is not passed
+      * to the dsp and so can use system memory.
+      *------------------------------------------------------------------------*/
+      double complex *A    = (double complex*) __malloc_ddr(M*K*sizeof(double complex));
+      double complex *B    = (double complex*) __malloc_ddr(K*N*sizeof(double complex));
+      double complex *Cdsp = (double complex*) __malloc_ddr(M*N*sizeof(double complex));
+      double complex *Carm = (double complex*) malloc      (M*N*sizeof(double complex));
+  
+      if (!A || !B || !Cdsp || !Carm)
+      {
+          printf("Could not allocate enough space for the arrays!");
+          if(A) __free_ddr(A);
+          if(B) __free_ddr(B);
+          if(Cdsp) __free_ddr(Cdsp);
+          if(Carm) free(Carm);
+          
+          return (-1);
+      }
+  
+      /*-------------------------------------------------------------------------
+      * Initialize matrices and print if small enough.
+      *------------------------------------------------------------------------*/
+      for (i = 0; i < M*K; ++i) 
+      {
+          A[i] = (double)rand()/RAND_MAX + (double)rand()/RAND_MAX * I;
+      }
+      for (i = 0; i < K*N; ++i)
+      {
+          B[i] = (double)rand()/RAND_MAX + (double)rand()/RAND_MAX * I;
+      }
+      for (i = 0; i < M*N; ++i)
+      {
+          Carm[i] = Cdsp[i] = (double)rand()/RAND_MAX + (double)rand()/RAND_MAX * I;
+      }  
+  
+      int lda = ((order == CblasColMajor && transA == CblasNoTrans) ||
+              (order == CblasRowMajor && transA == CblasTrans)) ? M : K;
+  
+      int ldb = ((order == CblasColMajor && transB == CblasNoTrans) ||
+              (order == CblasRowMajor && transB == CblasTrans)) ? K : N;
+  
+      int ldc = (order == CblasColMajor) ? M : N;
+  
+      /*============ BLAS tuning: running on DSP and then on ARM =============*/
+      /*------------------------------------------------------------------------
+      * Time DSP zgemm
+      *-----------------------------------------------------------------------*/
+      //ti_cblas_offload_config("001");  /* force offloading level 3 to DSP */
+      TI_CBLAS_L3_OFFLOAD = 1;
+      
+      tick();
+      cblas_zgemm(order,transA,transB,M,N,K,&alpha,A,lda,B,ldb,&beta,Cdsp,ldc);
+      time_secs = tock();
+      total_time_dsp += time_secs;
+      gflops_DSP = operation_count/time_secs*1e-9;
+      total_GFLOPS_DSP += gflops_DSP;
+      
+      /*-------------------------------------------------------------------------
+      * Time ARM zgemm
+      *------------------------------------------------------------------------*/
+      //ti_cblas_offload_config("000");  /* force no offloading */
+      TI_CBLAS_L3_OFFLOAD = 0;
+      
+      tick();
+      cblas_zgemm(order,transA,transB,M,N,K,&alpha,A,lda,B,ldb,&beta,Carm,ldc);
+      time_secs = tock();
+      total_time_arm += time_secs;
+      gflops_ARM = operation_count/time_secs*1e-9;
+      total_GFLOPS_ARM += gflops_ARM;
+      //printf(" %6.3f  %6.3f  %9.6fs %9.6fs\n", gflops_DSP, gflops_ARM, time_dsp, time_arm);
+  
+      /*-------------------------------------------------------------------------
+      * Verify Results
+      *------------------------------------------------------------------------*/
+      //return check_results(Cdsp, Carm, M, N);
+      err_code += check_results(Cdsp, Carm, M, N);
+  
+      __free_ddr(A);
+      __free_ddr(B);
+      __free_ddr(Cdsp);
+      free(Carm);
+    }
+    
+    *gflops_dsp = total_GFLOPS_DSP;
+    *gflops_arm = total_GFLOPS_ARM;
+    *time_dsp   = total_time_dsp / (float)NUM_TEST_RUN;
+    *time_arm   = total_time_arm / (float)NUM_TEST_RUN;
+
+    return err_code;
+}
+
+/*-----------------------------------------------------------------------------
+* check_results
+*----------------------------------------------------------------------------*/
+int check_results(const double complex *C1, const double complex *C2, int M, int N)
+{
+    int i;
+    const double EPISILON = 1e-10;
+    //const double EPISILON = 1e-200;
+    const int NERRORS  = 5;
+    int       num_errors = 0;
+
+    for (i=0; i<M*N; i++)
+    {
+        double delta = fabs(cabs(C1[i]) - cabs(C2[i]));
+
+        if (delta > EPISILON*cabs(C1[i]))
+            if ((num_errors += 1) < NERRORS)
+                printf("Error [elem:%d]: %f <==> %f\n", i, cabs(C1[i]), cabs(C2[i]));
+    }
+
+    if (num_errors > 0)
+    {
+         printf("FAIL with %d errors!\n", num_errors);
+         return -1;
+    }
+    else 
+    {
+        //printf("PASS!\n");
+        return 0;
+    }
+}
+
+