Allow to do gemv and ger buffer allocation on the stack
authorJerome Robert <jeromerobert@users.sf.net>
Fri, 26 Dec 2014 13:42:00 +0000 (14:42 +0100)
committerJerome Robert <jeromerobert@users.sf.net>
Sat, 27 Dec 2014 13:33:12 +0000 (14:33 +0100)
ger and gemv call blas_memory_alloc/free which in their turn
call blas_lock. blas_lock create thread contention when matrices
are small and the number of thread is high enough. We avoid
call blas_memory_alloc by replacing it with stack allocation.
This can be enabled with:
make -DMAX_STACK_ALLOC=2048
The given size (in byte) must be high enough to avoid thread contention
and small enough to avoid stack overflow.

Fix #478

Makefile.system
interface/gemv.c
interface/ger.c
kernel/x86_64/sgemv_t_4.c

index ec6339d..6f3c0bc 100644 (file)
@@ -305,6 +305,10 @@ ifdef SANITY_CHECK
 CCOMMON_OPT    += -DSANITY_CHECK -DREFNAME=$(*F)f$(BU)
 endif
 
+ifdef MAX_STACK_ALLOC
+CCOMMON_OPT    += -DMAX_STACK_ALLOC=$(MAX_STACK_ALLOC)
+endif
+
 #
 #  Architecture dependent settings
 #
index 2dd82dc..155305b 100644 (file)
@@ -208,7 +208,18 @@ void CNAME(enum CBLAS_ORDER order,
   if (incx < 0) x -= (lenx - 1) * incx;
   if (incy < 0) y -= (leny - 1) * incy;
 
+#ifdef MAX_STACK_ALLOC
+  int stack_alloc_size = m + n;
+  if(stack_alloc_size < 128)
+      //dgemv_n.S require a 128 bytes buffer
+      stack_alloc_size = 128;
+  if(stack_alloc_size > MAX_STACK_ALLOC / sizeof(FLOAT))
+      stack_alloc_size = 0;
+  FLOAT stack_buffer[stack_alloc_size];
+  buffer = stack_alloc_size ? stack_buffer : (FLOAT *)blas_memory_alloc(1);
+#else
   buffer = (FLOAT *)blas_memory_alloc(1);
+#endif
 
 #ifdef SMP
 
@@ -237,7 +248,10 @@ void CNAME(enum CBLAS_ORDER order,
   }
 #endif
 
-  blas_memory_free(buffer);
+#ifdef MAX_STACK_ALLOC
+  if(!stack_alloc_size)
+#endif
+    blas_memory_free(buffer);
 
   FUNCTION_PROFILE_END(1, m * n + m + n,  2 * m * n);
 
index 9857d24..cac3577 100644 (file)
@@ -171,7 +171,15 @@ void CNAME(enum CBLAS_ORDER order,
   if (incy < 0) y -= (n - 1) * incy;
   if (incx < 0) x -= (m - 1) * incx;
 
+#ifdef MAX_STACK_ALLOC
+  int stack_alloc_size = m;
+  if(stack_alloc_size > MAX_STACK_ALLOC / sizeof(FLOAT))
+      stack_alloc_size = 0;
+  FLOAT stack_buffer[stack_alloc_size];
+  buffer = stack_alloc_size ? stack_buffer : (FLOAT *)blas_memory_alloc(1);
+#else
   buffer = (FLOAT *)blas_memory_alloc(1);
+#endif
 
 #ifdef SMPTEST
   nthreads = num_cpu_avail(2);
@@ -190,7 +198,10 @@ void CNAME(enum CBLAS_ORDER order,
   }
 #endif
 
-  blas_memory_free(buffer);
+#ifdef MAX_STACK_ALLOC
+  if(!stack_alloc_size)
+#endif
+    blas_memory_free(buffer);
 
   FUNCTION_PROFILE_END(1, m * n + m + n, 2 * m * n);
 
index cd13bb6..61eb1ed 100644 (file)
@@ -302,7 +302,7 @@ int CNAME(BLASLONG m, BLASLONG n, BLASLONG dummy1, FLOAT alpha, FLOAT *a, BLASLO
         if ( n < 1 ) return(0);
 
        xbuffer = buffer;
-       ytemp   = buffer + NBMAX;
+       ytemp   = buffer + (m < NBMAX ? m : NBMAX);
        
        n0 = n / NBMAX;
         n1 = (n % NBMAX)  >> 2 ;