# The first commit's message is:
Optimizations for APM's xgene-1 (aarch64). 1) general system updates to support armv8 better. Make all did not work, one needed to supply TARGET=ARMV8. 2) sgem 4x4 kernel in assembler using SIMD, and configuration changes to use it. 3) strmm 4x4 kernel in C. Since the sgem kernel does 4x4, the trmm kernel must also do 4xN. Added Dave Nuechterlein to the contributors list.
This commit is contained in:
parent
2987bc7b40
commit
58c90d5937
|
@ -117,5 +117,9 @@ In chronological order:
|
|||
* Isaac Dunham <https://github.com/idunham>
|
||||
* [2014-08-03] Fixed link error on Linux/musl
|
||||
|
||||
* Dave Nuechterlein
|
||||
* [2014-10-10] trmm and sgemm kernels (optimized for APM's X-Gene 1).
|
||||
ARMv8 support.
|
||||
|
||||
* [Your name or handle] <[email or website]>
|
||||
* [Date] [Brief summary of your changes]
|
||||
|
|
|
@ -119,9 +119,9 @@ static inline int blas_quickdivide(blasint x, blasint y){
|
|||
}
|
||||
|
||||
#if defined(DOUBLE)
|
||||
#define GET_IMAGE(res) __asm__ __volatile__("vstr.f64 d1, %0" : "=m"(res) : : "memory")
|
||||
#define GET_IMAGE(res) __asm__ __volatile__("str d1, %0" : "=m"(res) : : "memory")
|
||||
#else
|
||||
#define GET_IMAGE(res) __asm__ __volatile__("vstr.f32 s1, %0" : "=m"(res) : : "memory")
|
||||
#define GET_IMAGE(res) __asm__ __volatile__("str s1, %0" : "=m"(res) : : "memory")
|
||||
#endif
|
||||
|
||||
#define GET_IMAGE_CANCEL
|
||||
|
@ -138,7 +138,6 @@ static inline int blas_quickdivide(blasint x, blasint y){
|
|||
#if defined(ASSEMBLER) && !defined(NEEDPARAM)
|
||||
|
||||
#define PROLOGUE \
|
||||
.arm ;\
|
||||
.global REALNAME ;\
|
||||
.func REALNAME ;\
|
||||
REALNAME:
|
||||
|
|
|
@ -0,0 +1,217 @@
|
|||
/**************************************************************************
|
||||
Copyright (c) 2013, The OpenBLAS Project
|
||||
All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
3. Neither the name of the OpenBLAS project 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 OPENBLAS PROJECT 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 <string.h>
|
||||
|
||||
#define CPU_UNKNOWN 0
|
||||
#define CPU_ARMV8 1
|
||||
|
||||
static char *cpuname[] = {
|
||||
"UNKOWN",
|
||||
"ARMV8"
|
||||
};
|
||||
|
||||
|
||||
int get_feature(char *search)
|
||||
{
|
||||
|
||||
#ifdef linux
|
||||
FILE *infile;
|
||||
char buffer[2048], *p,*t;
|
||||
p = (char *) NULL ;
|
||||
|
||||
infile = fopen("/proc/cpuinfo", "r");
|
||||
|
||||
while (fgets(buffer, sizeof(buffer), infile))
|
||||
{
|
||||
|
||||
if (!strncmp("Features", buffer, 8))
|
||||
{
|
||||
p = strchr(buffer, ':') + 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(infile);
|
||||
|
||||
|
||||
if( p == NULL ) return;
|
||||
|
||||
t = strtok(p," ");
|
||||
while( t = strtok(NULL," "))
|
||||
{
|
||||
if (!strcmp(t, search)) { return(1); }
|
||||
}
|
||||
|
||||
#endif
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
int detect(void)
|
||||
{
|
||||
|
||||
#ifdef linux
|
||||
|
||||
FILE *infile;
|
||||
char buffer[512], *p;
|
||||
p = (char *) NULL ;
|
||||
|
||||
infile = fopen("/proc/cpuinfo", "r");
|
||||
|
||||
while (fgets(buffer, sizeof(buffer), infile))
|
||||
{
|
||||
|
||||
if ((!strncmp("model name", buffer, 10)) || (!strncmp("Processor", buffer, 9)))
|
||||
{
|
||||
p = strchr(buffer, ':') + 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(infile);
|
||||
|
||||
if(p != NULL)
|
||||
{
|
||||
|
||||
if (strstr(p, "AArch64"))
|
||||
{
|
||||
return CPU_ARMV8;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
return CPU_UNKNOWN;
|
||||
}
|
||||
|
||||
char *get_corename(void)
|
||||
{
|
||||
return cpuname[detect()];
|
||||
}
|
||||
|
||||
void get_architecture(void)
|
||||
{
|
||||
printf("ARM");
|
||||
}
|
||||
|
||||
void get_subarchitecture(void)
|
||||
{
|
||||
int d = detect();
|
||||
switch (d)
|
||||
{
|
||||
|
||||
case CPU_ARMV8:
|
||||
printf("ARMV8");
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("UNKNOWN");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void get_subdirname(void)
|
||||
{
|
||||
printf("arm64");
|
||||
}
|
||||
|
||||
void get_cpuconfig(void)
|
||||
{
|
||||
|
||||
int d = detect();
|
||||
switch (d)
|
||||
{
|
||||
|
||||
case CPU_ARMV8:
|
||||
printf("#define ARMV8\n");
|
||||
printf("#define L1_DATA_SIZE 32768\n");
|
||||
printf("#define L1_DATA_LINESIZE 64\n");
|
||||
printf("#define L2_SIZE 262144\n");
|
||||
printf("#define L2_LINESIZE 64\n");
|
||||
printf("#define DTB_DEFAULT_ENTRIES 64\n");
|
||||
printf("#define DTB_SIZE 4096\n");
|
||||
printf("#define L2_ASSOCIATIVE 4\n");
|
||||
break;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void get_libname(void)
|
||||
{
|
||||
|
||||
int d = detect();
|
||||
switch (d)
|
||||
{
|
||||
|
||||
case CPU_ARMV8:
|
||||
printf("armv8\n");
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void get_features(void)
|
||||
{
|
||||
|
||||
#ifdef linux
|
||||
FILE *infile;
|
||||
char buffer[2048], *p,*t;
|
||||
p = (char *) NULL ;
|
||||
|
||||
infile = fopen("/proc/cpuinfo", "r");
|
||||
|
||||
while (fgets(buffer, sizeof(buffer), infile))
|
||||
{
|
||||
|
||||
if (!strncmp("Features", buffer, 8))
|
||||
{
|
||||
p = strchr(buffer, ':') + 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(infile);
|
||||
|
||||
|
||||
if( p == NULL ) return;
|
||||
|
||||
t = strtok(p," ");
|
||||
while( t = strtok(NULL," "))
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
|
18
getarch.c
18
getarch.c
|
@ -746,12 +746,11 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#define SUBARCHITECTURE "ARMV8"
|
||||
#define SUBDIRNAME "arm64"
|
||||
#define ARCHCONFIG "-DARMV8 " \
|
||||
"-DL1_DATA_SIZE=65536 -DL1_DATA_LINESIZE=32 " \
|
||||
"-DL2_SIZE=512488 -DL2_LINESIZE=32 " \
|
||||
"-DDTB_DEFAULT_ENTRIES=64 -DDTB_SIZE=4096 -DL2_ASSOCIATIVE=4 " \
|
||||
"-DHAVE_VFP -DHAVE_VFPV3 -DHAVE_VFPV4"
|
||||
"-DL1_DATA_SIZE=32768 -DL1_DATA_LINESIZE=64 " \
|
||||
"-DL2_SIZE=262144 -DL2_LINESIZE=64 " \
|
||||
"-DDTB_DEFAULT_ENTRIES=64 -DDTB_SIZE=4096 -DL2_ASSOCIATIVE=32 "
|
||||
#define LIBNAME "armv8"
|
||||
#define CORENAME "ARMV8"
|
||||
#define CORENAME "XGENE1"
|
||||
#else
|
||||
#endif
|
||||
|
||||
|
@ -801,6 +800,11 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#define OPENBLAS_SUPPORTED
|
||||
#endif
|
||||
|
||||
#ifdef __aarch64__
|
||||
#include "cpuid_arm64.c"
|
||||
#define OPENBLAS_SUPPORTED
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef OPENBLAS_SUPPORTED
|
||||
#error "This arch/CPU is not supported by OpenBLAS."
|
||||
|
@ -856,7 +860,7 @@ int main(int argc, char *argv[]){
|
|||
#ifdef FORCE
|
||||
printf("CORE=%s\n", CORENAME);
|
||||
#else
|
||||
#if defined(__i386__) || defined(__x86_64__) || defined(POWER) || defined(__mips__) || defined(__arm__)
|
||||
#if defined(__i386__) || defined(__x86_64__) || defined(POWER) || defined(__mips__) || defined(__arm__) || defined(__aarch64__)
|
||||
printf("CORE=%s\n", get_corename());
|
||||
#endif
|
||||
#endif
|
||||
|
@ -956,7 +960,7 @@ int main(int argc, char *argv[]){
|
|||
#ifdef FORCE
|
||||
printf("#define CHAR_CORENAME \"%s\"\n", CORENAME);
|
||||
#else
|
||||
#if defined(__i386__) || defined(__x86_64__) || defined(POWER) || defined(__mips__) || defined(__arm__)
|
||||
#if defined(__i386__) || defined(__x86_64__) || defined(POWER) || defined(__mips__) || defined(__arm__) || defined(__aarch64__)
|
||||
printf("#define CHAR_CORENAME \"%s\"\n", get_corename());
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -80,14 +80,14 @@ DGEMVTKERNEL = ../arm/gemv_t.c
|
|||
CGEMVTKERNEL = ../arm/zgemv_t.c
|
||||
ZGEMVTKERNEL = ../arm/zgemv_t.c
|
||||
|
||||
STRMMKERNEL = ../generic/trmmkernel_2x2.c
|
||||
STRMMKERNEL = ../generic/trmmkernel_4x4.c
|
||||
DTRMMKERNEL = ../generic/trmmkernel_2x2.c
|
||||
CTRMMKERNEL = ../generic/ztrmmkernel_2x2.c
|
||||
ZTRMMKERNEL = ../generic/ztrmmkernel_2x2.c
|
||||
|
||||
SGEMMKERNEL = ../generic/gemmkernel_2x2.c
|
||||
SGEMMONCOPY = ../generic/gemm_ncopy_2.c
|
||||
SGEMMOTCOPY = ../generic/gemm_tcopy_2.c
|
||||
SGEMMKERNEL = sgemm_kernel_4x4.S
|
||||
SGEMMONCOPY = ../generic/gemm_ncopy_4.c
|
||||
SGEMMOTCOPY = ../generic/gemm_tcopy_4.c
|
||||
SGEMMONCOPYOBJ = sgemm_oncopy.o
|
||||
SGEMMOTCOPYOBJ = sgemm_otcopy.o
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,875 @@
|
|||
#include "common.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
int CNAME(BLASLONG bm,BLASLONG bn,BLASLONG bk,FLOAT alpha,FLOAT* ba,FLOAT* bb,FLOAT* C,BLASLONG ldc ,BLASLONG offset)
|
||||
{
|
||||
|
||||
BLASLONG i,j,k;
|
||||
FLOAT *C0,*C1,*C2,*C3,*ptrba,*ptrbb;
|
||||
|
||||
FLOAT res0_0;
|
||||
FLOAT res0_1;
|
||||
FLOAT res0_2;
|
||||
FLOAT res0_3;
|
||||
|
||||
FLOAT res1_0;
|
||||
FLOAT res1_1;
|
||||
FLOAT res1_2;
|
||||
FLOAT res1_3;
|
||||
|
||||
FLOAT res2_0;
|
||||
FLOAT res2_1;
|
||||
FLOAT res2_2;
|
||||
FLOAT res2_3;
|
||||
|
||||
FLOAT res3_0;
|
||||
FLOAT res3_1;
|
||||
FLOAT res3_2;
|
||||
FLOAT res3_3;
|
||||
|
||||
FLOAT a0;
|
||||
FLOAT a1;
|
||||
|
||||
FLOAT b0;
|
||||
FLOAT b1;
|
||||
FLOAT b2;
|
||||
FLOAT b3;
|
||||
|
||||
BLASLONG off, temp;
|
||||
|
||||
bool left;
|
||||
bool transposed;
|
||||
bool backwards;
|
||||
|
||||
#ifdef LEFT
|
||||
left = true;
|
||||
#else
|
||||
left = false;
|
||||
#endif
|
||||
|
||||
#ifdef TRANSA
|
||||
transposed = true;
|
||||
#else
|
||||
transposed = false;
|
||||
#endif
|
||||
|
||||
backwards = left != transposed;
|
||||
|
||||
if (!left) {
|
||||
off = -offset;
|
||||
}
|
||||
|
||||
|
||||
for (j=0; j<bn/4; j+=1) // do blocks of the Mx4 loops
|
||||
{
|
||||
C0 = C;
|
||||
C1 = C0+ldc;
|
||||
C2 = C1+ldc;
|
||||
C3 = C2+ldc;
|
||||
|
||||
|
||||
if (left) {
|
||||
off = offset;
|
||||
}
|
||||
|
||||
ptrba = ba;
|
||||
|
||||
for (i=0; i<bm/4; i+=1) // do blocks of 4x4
|
||||
{
|
||||
|
||||
ptrbb = bb;
|
||||
if (backwards)
|
||||
{
|
||||
ptrba += off*4; // number of values in A
|
||||
ptrbb += off*4; // number of values in B
|
||||
}
|
||||
|
||||
res0_0 = 0;
|
||||
res0_1 = 0;
|
||||
res0_2 = 0;
|
||||
res0_3 = 0;
|
||||
|
||||
res1_0 = 0;
|
||||
res1_1 = 0;
|
||||
res1_2 = 0;
|
||||
res1_3 = 0;
|
||||
|
||||
res2_0 = 0;
|
||||
res2_1 = 0;
|
||||
res2_2 = 0;
|
||||
res2_3 = 0;
|
||||
|
||||
res3_0 = 0;
|
||||
res3_1 = 0;
|
||||
res3_2 = 0;
|
||||
res3_3 = 0;
|
||||
|
||||
temp = backwards ? bk-off :
|
||||
left ? off + 4 : // number of values in A
|
||||
off + 4; // number of values in B
|
||||
|
||||
for (k=0; k<temp; k++)
|
||||
{
|
||||
b0 = ptrbb[0];
|
||||
b1 = ptrbb[1];
|
||||
b2 = ptrbb[2];
|
||||
b3 = ptrbb[3];
|
||||
|
||||
a0 = ptrba[0];
|
||||
res0_0 += a0*b0;
|
||||
res1_0 += a0*b1;
|
||||
res2_0 += a0*b2;
|
||||
res3_0 += a0*b3;
|
||||
|
||||
a1 = ptrba[1];
|
||||
res0_1 += a1*b0;
|
||||
res1_1 += a1*b1;
|
||||
res2_1 += a1*b2;
|
||||
res3_1 += a1*b3;
|
||||
|
||||
a0 = ptrba[2];
|
||||
res0_2 += a0*b0;
|
||||
res1_2 += a0*b1;
|
||||
res2_2 += a0*b2;
|
||||
res3_2 += a0*b3;
|
||||
|
||||
a1 = ptrba[3];
|
||||
res0_3 += a1*b0;
|
||||
res1_3 += a1*b1;
|
||||
res2_3 += a1*b2;
|
||||
res3_3 += a1*b3;
|
||||
|
||||
ptrba = ptrba+4;
|
||||
ptrbb = ptrbb+4;
|
||||
}
|
||||
|
||||
res0_0 *= alpha;
|
||||
res0_1 *= alpha;
|
||||
res0_2 *= alpha;
|
||||
res0_3 *= alpha;
|
||||
|
||||
res1_0 *= alpha;
|
||||
res1_1 *= alpha;
|
||||
res1_2 *= alpha;
|
||||
res1_3 *= alpha;
|
||||
|
||||
res2_0 *= alpha;
|
||||
res2_1 *= alpha;
|
||||
res2_2 *= alpha;
|
||||
res2_3 *= alpha;
|
||||
|
||||
res3_0 *= alpha;
|
||||
res3_1 *= alpha;
|
||||
res3_2 *= alpha;
|
||||
res3_3 *= alpha;
|
||||
|
||||
C0[0] = res0_0;
|
||||
C0[1] = res0_1;
|
||||
C0[2] = res0_2;
|
||||
C0[3] = res0_3;
|
||||
|
||||
C1[0] = res1_0;
|
||||
C1[1] = res1_1;
|
||||
C1[2] = res1_2;
|
||||
C1[3] = res1_3;
|
||||
|
||||
C2[0] = res2_0;
|
||||
C2[1] = res2_1;
|
||||
C2[2] = res2_2;
|
||||
C2[3] = res2_3;
|
||||
|
||||
C3[0] = res3_0;
|
||||
C3[1] = res3_1;
|
||||
C3[2] = res3_2;
|
||||
C3[3] = res3_3;
|
||||
|
||||
if (!backwards) {
|
||||
temp = bk-off;
|
||||
temp = left ? temp - 4 : // number of values in A
|
||||
temp - 4; // number of values in B
|
||||
|
||||
ptrba += temp*4; // number of values in A
|
||||
ptrbb += temp*4; // number of values in B
|
||||
}
|
||||
#ifdef LEFT
|
||||
off += 4; // number of values in A
|
||||
#endif
|
||||
|
||||
C0 = C0+4;
|
||||
C1 = C1+4;
|
||||
C2 = C2+4;
|
||||
C3 = C3+4;
|
||||
|
||||
}
|
||||
|
||||
if ( bm & 2 ) // do any 2x4 loop
|
||||
{
|
||||
|
||||
#if (defined(LEFT) && defined(TRANSA)) || (!defined(LEFT) && !defined(TRANSA))
|
||||
ptrbb = bb;
|
||||
#else
|
||||
ptrba += off*2;
|
||||
ptrbb = bb + off*4;
|
||||
#endif
|
||||
|
||||
res0_0 = 0;
|
||||
res0_1 = 0;
|
||||
|
||||
res1_0 = 0;
|
||||
res1_1 = 0;
|
||||
|
||||
res2_0 = 0;
|
||||
res2_1 = 0;
|
||||
|
||||
res3_0 = 0;
|
||||
res3_1 = 0;
|
||||
|
||||
|
||||
#if (defined(LEFT) && !defined(TRANSA)) || (!defined(LEFT) && defined(TRANSA))
|
||||
temp = bk-off;
|
||||
#elif defined(LEFT)
|
||||
temp = off+2; // number of values in A
|
||||
#else
|
||||
temp = off+4; // number of values in B
|
||||
#endif
|
||||
|
||||
for (k=0; k<temp; k++)
|
||||
{
|
||||
b0 = ptrbb[0];
|
||||
b1 = ptrbb[1];
|
||||
b2 = ptrbb[2];
|
||||
b3 = ptrbb[3];
|
||||
|
||||
a0 = ptrba[0];
|
||||
res0_0 += a0*b0;
|
||||
res1_0 += a0*b1;
|
||||
res2_0 += a0*b2;
|
||||
res3_0 += a0*b3;
|
||||
|
||||
a1 = ptrba[1];
|
||||
res0_1 += a1*b0;
|
||||
res1_1 += a1*b1;
|
||||
res2_1 += a1*b2;
|
||||
res3_1 += a1*b3;
|
||||
|
||||
ptrba = ptrba+2;
|
||||
ptrbb = ptrbb+4;
|
||||
}
|
||||
|
||||
res0_0 *= alpha;
|
||||
res0_1 *= alpha;
|
||||
|
||||
res1_0 *= alpha;
|
||||
res1_1 *= alpha;
|
||||
|
||||
res2_0 *= alpha;
|
||||
res2_1 *= alpha;
|
||||
|
||||
res3_0 *= alpha;
|
||||
res3_1 *= alpha;
|
||||
|
||||
C0[0] = res0_0;
|
||||
C0[1] = res0_1;
|
||||
|
||||
C1[0] = res1_0;
|
||||
C1[1] = res1_1;
|
||||
|
||||
C2[0] = res2_0;
|
||||
C2[1] = res2_1;
|
||||
|
||||
C3[0] = res3_0;
|
||||
C3[1] = res3_1;
|
||||
|
||||
|
||||
#if ( defined(LEFT) && defined(TRANSA)) || (!defined(LEFT) && !defined(TRANSA))
|
||||
temp = bk - off;
|
||||
#ifdef LEFT
|
||||
temp -= 2; // number of values in A
|
||||
#else
|
||||
temp -= 4; // number of values in B
|
||||
#endif
|
||||
ptrba += temp*2;
|
||||
ptrbb += temp*4;
|
||||
#endif
|
||||
|
||||
#ifdef LEFT
|
||||
off += 2; // number of values in A
|
||||
#endif
|
||||
|
||||
C0 = C0+2;
|
||||
C1 = C1+2;
|
||||
C2 = C2+2;
|
||||
C3 = C3+2;
|
||||
|
||||
}
|
||||
|
||||
if ( bm & 1 ) // do any 1x4 loop
|
||||
{
|
||||
|
||||
#if (defined(LEFT) && defined(TRANSA)) || (!defined(LEFT) && !defined(TRANSA))
|
||||
ptrbb = bb;
|
||||
#else
|
||||
ptrba += off*1;
|
||||
ptrbb = bb + off*4;
|
||||
#endif
|
||||
|
||||
res0_0 = 0;
|
||||
res1_0 = 0;
|
||||
res2_0 = 0;
|
||||
res3_0 = 0;
|
||||
|
||||
|
||||
#if (defined(LEFT) && !defined(TRANSA)) || (!defined(LEFT) && defined(TRANSA))
|
||||
temp = bk-off;
|
||||
#elif defined(LEFT)
|
||||
temp = off+1; // number of values in A
|
||||
#else
|
||||
temp = off+4; // number of values in B
|
||||
#endif
|
||||
|
||||
for (k=0; k<temp; k++)
|
||||
{
|
||||
b0 = ptrbb[0];
|
||||
b1 = ptrbb[1];
|
||||
b2 = ptrbb[2];
|
||||
b3 = ptrbb[3];
|
||||
|
||||
a0 = ptrba[0];
|
||||
res0_0 += a0*b0;
|
||||
res1_0 += a0*b1;
|
||||
res2_0 += a0*b2;
|
||||
res3_0 += a0*b3;
|
||||
|
||||
ptrba = ptrba+1;
|
||||
ptrbb = ptrbb+4;
|
||||
}
|
||||
|
||||
res0_0 *= alpha;
|
||||
|
||||
res1_0 *= alpha;
|
||||
|
||||
res2_0 *= alpha;
|
||||
|
||||
res3_0 *= alpha;
|
||||
|
||||
C0[0] = res0_0;
|
||||
|
||||
C1[0] = res1_0;
|
||||
|
||||
C2[0] = res2_0;
|
||||
|
||||
C3[0] = res3_0;
|
||||
|
||||
|
||||
#if ( defined(LEFT) && defined(TRANSA)) || (!defined(LEFT) && !defined(TRANSA))
|
||||
temp = bk - off;
|
||||
#ifdef LEFT
|
||||
temp -= 1; // number of values in A
|
||||
#else
|
||||
temp -= 4; // number of values in B
|
||||
#endif
|
||||
ptrba += temp*1;
|
||||
ptrbb += temp*4;
|
||||
#endif
|
||||
|
||||
#ifdef LEFT
|
||||
off += 1; // number of values in A
|
||||
#endif
|
||||
|
||||
C0 = C0+1;
|
||||
C1 = C1+1;
|
||||
C2 = C2+1;
|
||||
C3 = C3+1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
#if defined(TRMMKERNEL) && !defined(LEFT)
|
||||
off += 4;
|
||||
#endif
|
||||
|
||||
k = (bk<<2);
|
||||
bb = bb+k;
|
||||
i = (ldc<<2);
|
||||
C = C+i;
|
||||
}
|
||||
|
||||
for (j=0; j<(bn&2); j+=2) // do the Mx2 loops
|
||||
{
|
||||
C0 = C;
|
||||
C1 = C0+ldc;
|
||||
|
||||
#if defined(TRMMKERNEL) && defined(LEFT)
|
||||
off = offset;
|
||||
#endif
|
||||
|
||||
|
||||
ptrba = ba;
|
||||
|
||||
for (i=0; i<bm/4; i+=1) // do blocks of 4x2
|
||||
{
|
||||
|
||||
#if (defined(LEFT) && defined(TRANSA)) || (!defined(LEFT) && !defined(TRANSA))
|
||||
ptrbb = bb;
|
||||
#else
|
||||
ptrba += off*4;
|
||||
ptrbb = bb + off*2;
|
||||
#endif
|
||||
|
||||
res0_0 = 0;
|
||||
res0_1 = 0;
|
||||
res0_2 = 0;
|
||||
res0_3 = 0;
|
||||
|
||||
res1_0 = 0;
|
||||
res1_1 = 0;
|
||||
res1_2 = 0;
|
||||
res1_3 = 0;
|
||||
|
||||
|
||||
#if (defined(LEFT) && !defined(TRANSA)) || (!defined(LEFT) && defined(TRANSA))
|
||||
temp = bk-off;
|
||||
#elif defined(LEFT)
|
||||
temp = off+4; // number of values in A
|
||||
#else
|
||||
temp = off+2; // number of values in B
|
||||
#endif
|
||||
|
||||
for (k=0; k<temp; k++)
|
||||
{
|
||||
b0 = ptrbb[0];
|
||||
b1 = ptrbb[1];
|
||||
|
||||
a0 = ptrba[0];
|
||||
res0_0 += a0*b0;
|
||||
res1_0 += a0*b1;
|
||||
|
||||
a1 = ptrba[1];
|
||||
res0_1 += a1*b0;
|
||||
res1_1 += a1*b1;
|
||||
|
||||
a0 = ptrba[2];
|
||||
res0_2 += a0*b0;
|
||||
res1_2 += a0*b1;
|
||||
|
||||
a1 = ptrba[3];
|
||||
res0_3 += a1*b0;
|
||||
res1_3 += a1*b1;
|
||||
|
||||
ptrba = ptrba+4;
|
||||
ptrbb = ptrbb+2;
|
||||
}
|
||||
|
||||
res0_0 *= alpha;
|
||||
res0_1 *= alpha;
|
||||
res0_2 *= alpha;
|
||||
res0_3 *= alpha;
|
||||
|
||||
res1_0 *= alpha;
|
||||
res1_1 *= alpha;
|
||||
res1_2 *= alpha;
|
||||
res1_3 *= alpha;
|
||||
|
||||
C0[0] = res0_0;
|
||||
C0[1] = res0_1;
|
||||
C0[2] = res0_2;
|
||||
C0[3] = res0_3;
|
||||
|
||||
C1[0] = res1_0;
|
||||
C1[1] = res1_1;
|
||||
C1[2] = res1_2;
|
||||
C1[3] = res1_3;
|
||||
|
||||
|
||||
#if ( defined(LEFT) && defined(TRANSA)) || (!defined(LEFT) && !defined(TRANSA))
|
||||
temp = bk - off;
|
||||
#ifdef LEFT
|
||||
temp -= 4; // number of values in A
|
||||
#else
|
||||
temp -= 2; // number of values in B
|
||||
#endif
|
||||
ptrba += temp*4;
|
||||
ptrbb += temp*2;
|
||||
#endif
|
||||
|
||||
#ifdef LEFT
|
||||
off += 4; // number of values in A
|
||||
#endif
|
||||
|
||||
C0 = C0+4;
|
||||
C1 = C1+4;
|
||||
|
||||
}
|
||||
|
||||
if ( bm & 2 ) // do any 2x2 loop
|
||||
{
|
||||
|
||||
#if (defined(LEFT) && defined(TRANSA)) || (!defined(LEFT) && !defined(TRANSA))
|
||||
ptrbb = bb;
|
||||
#else
|
||||
ptrba += off*2;
|
||||
ptrbb = bb + off*2;
|
||||
#endif
|
||||
|
||||
res0_0 = 0;
|
||||
res0_1 = 0;
|
||||
|
||||
res1_0 = 0;
|
||||
res1_1 = 0;
|
||||
|
||||
|
||||
#if (defined(LEFT) && !defined(TRANSA)) || (!defined(LEFT) && defined(TRANSA))
|
||||
temp = bk-off;
|
||||
#elif defined(LEFT)
|
||||
temp = off+2; // number of values in A
|
||||
#else
|
||||
temp = off+2; // number of values in B
|
||||
#endif
|
||||
|
||||
for (k=0; k<temp; k++)
|
||||
{
|
||||
b0 = ptrbb[0];
|
||||
b1 = ptrbb[1];
|
||||
|
||||
a0 = ptrba[0];
|
||||
res0_0 += a0*b0;
|
||||
res1_0 += a0*b1;
|
||||
|
||||
a1 = ptrba[1];
|
||||
res0_1 += a1*b0;
|
||||
res1_1 += a1*b1;
|
||||
|
||||
ptrba = ptrba+2;
|
||||
ptrbb = ptrbb+2;
|
||||
}
|
||||
|
||||
res0_0 *= alpha;
|
||||
res0_1 *= alpha;
|
||||
|
||||
res1_0 *= alpha;
|
||||
res1_1 *= alpha;
|
||||
|
||||
C0[0] = res0_0;
|
||||
C0[1] = res0_1;
|
||||
|
||||
C1[0] = res1_0;
|
||||
C1[1] = res1_1;
|
||||
|
||||
|
||||
#if ( defined(LEFT) && defined(TRANSA)) || (!defined(LEFT) && !defined(TRANSA))
|
||||
temp = bk - off;
|
||||
#ifdef LEFT
|
||||
temp -= 2; // number of values in A
|
||||
#else
|
||||
temp -= 2; // number of values in B
|
||||
#endif
|
||||
ptrba += temp*2;
|
||||
ptrbb += temp*2;
|
||||
#endif
|
||||
|
||||
#ifdef LEFT
|
||||
off += 2; // number of values in A
|
||||
#endif
|
||||
|
||||
C0 = C0+2;
|
||||
C1 = C1+2;
|
||||
|
||||
}
|
||||
|
||||
if ( bm & 1 ) // do any 1x2 loop
|
||||
{
|
||||
|
||||
#if (defined(LEFT) && defined(TRANSA)) || (!defined(LEFT) && !defined(TRANSA))
|
||||
ptrbb = bb;
|
||||
#else
|
||||
ptrba += off*1;
|
||||
ptrbb = bb + off*2;
|
||||
#endif
|
||||
|
||||
res0_0 = 0;
|
||||
|
||||
res1_0 = 0;
|
||||
|
||||
|
||||
#if (defined(LEFT) && !defined(TRANSA)) || (!defined(LEFT) && defined(TRANSA))
|
||||
temp = bk-off;
|
||||
#elif defined(LEFT)
|
||||
temp = off+1; // number of values in A
|
||||
#else
|
||||
temp = off+2; // number of values in B
|
||||
#endif
|
||||
|
||||
for (k=0; k<temp; k++)
|
||||
{
|
||||
b0 = ptrbb[0];
|
||||
b1 = ptrbb[1];
|
||||
|
||||
a0 = ptrba[0];
|
||||
res0_0 += a0*b0;
|
||||
res1_0 += a0*b1;
|
||||
|
||||
ptrba = ptrba+1;
|
||||
ptrbb = ptrbb+2;
|
||||
}
|
||||
|
||||
res0_0 *= alpha;
|
||||
|
||||
res1_0 *= alpha;
|
||||
|
||||
C0[0] = res0_0;
|
||||
|
||||
C1[0] = res1_0;
|
||||
|
||||
|
||||
#if ( defined(LEFT) && defined(TRANSA)) || (!defined(LEFT) && !defined(TRANSA))
|
||||
temp = bk - off;
|
||||
#ifdef LEFT
|
||||
temp -= 1; // number of values in A
|
||||
#else
|
||||
temp -= 2; // number of values in B
|
||||
#endif
|
||||
ptrba += temp*1;
|
||||
ptrbb += temp*2;
|
||||
#endif
|
||||
|
||||
#ifdef LEFT
|
||||
off += 1; // number of values in A
|
||||
#endif
|
||||
|
||||
C0 = C0+1;
|
||||
C1 = C1+1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
#if defined(TRMMKERNEL) && !defined(LEFT)
|
||||
off += 2;
|
||||
#endif
|
||||
|
||||
k = (bk<<1);
|
||||
bb = bb+k;
|
||||
i = (ldc<<1);
|
||||
C = C+i;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
for (j=0; j<(bn&1); j+=1) // do the Mx1 loops
|
||||
{
|
||||
C0 = C;
|
||||
|
||||
#if defined(TRMMKERNEL) && defined(LEFT)
|
||||
off = offset;
|
||||
#endif
|
||||
|
||||
ptrba = ba;
|
||||
|
||||
for (i=0; i<bm/4; i+=1) // do blocks of 4x1 loops
|
||||
{
|
||||
|
||||
#if (defined(LEFT) && defined(TRANSA)) || (!defined(LEFT) && !defined(TRANSA))
|
||||
ptrbb = bb;
|
||||
#else
|
||||
ptrba += off*4;
|
||||
ptrbb = bb + off*1;
|
||||
#endif
|
||||
|
||||
res0_0 = 0;
|
||||
res0_1 = 0;
|
||||
res0_2 = 0;
|
||||
res0_3 = 0;
|
||||
|
||||
|
||||
#if (defined(LEFT) && !defined(TRANSA)) || (!defined(LEFT) && defined(TRANSA))
|
||||
temp = bk-off;
|
||||
#elif defined(LEFT)
|
||||
temp = off+4; // number of values in A
|
||||
#else
|
||||
temp = off+1; // number of values in B
|
||||
#endif
|
||||
|
||||
for (k=0; k<temp; k++)
|
||||
{
|
||||
b0 = ptrbb[0];
|
||||
|
||||
a0 = ptrba[0];
|
||||
res0_0 += a0*b0;
|
||||
|
||||
a1 = ptrba[1];
|
||||
res0_1 += a1*b0;
|
||||
|
||||
a0 = ptrba[2];
|
||||
res0_2 += a0*b0;
|
||||
|
||||
a1 = ptrba[3];
|
||||
res0_3 += a1*b0;
|
||||
|
||||
ptrba = ptrba+4;
|
||||
ptrbb = ptrbb+1;
|
||||
}
|
||||
|
||||
res0_0 *= alpha;
|
||||
res0_1 *= alpha;
|
||||
res0_2 *= alpha;
|
||||
res0_3 *= alpha;
|
||||
|
||||
C0[0] = res0_0;
|
||||
C0[1] = res0_1;
|
||||
C0[2] = res0_2;
|
||||
C0[3] = res0_3;
|
||||
|
||||
|
||||
#if ( defined(LEFT) && defined(TRANSA)) || (!defined(LEFT) && !defined(TRANSA))
|
||||
temp = bk - off;
|
||||
#ifdef LEFT
|
||||
temp -= 4; // number of values in A
|
||||
#else
|
||||
temp -= 1; // number of values in B
|
||||
#endif
|
||||
ptrba += temp*4;
|
||||
ptrbb += temp*1;
|
||||
#endif
|
||||
|
||||
#ifdef LEFT
|
||||
off += 4; // number of values in A
|
||||
#endif
|
||||
|
||||
C0 = C0+4;
|
||||
|
||||
}
|
||||
|
||||
if ( bm & 2 ) // do any 2x1 loop
|
||||
{
|
||||
|
||||
#if (defined(LEFT) && defined(TRANSA)) || (!defined(LEFT) && !defined(TRANSA))
|
||||
ptrbb = bb;
|
||||
#else
|
||||
ptrba += off*2;
|
||||
ptrbb = bb + off*1;
|
||||
#endif
|
||||
|
||||
res0_0 = 0;
|
||||
res0_1 = 0;
|
||||
|
||||
|
||||
|
||||
#if (defined(LEFT) && !defined(TRANSA)) || (!defined(LEFT) && defined(TRANSA))
|
||||
temp = bk-off;
|
||||
#elif defined(LEFT)
|
||||
temp = off+2; // number of values in A
|
||||
#else
|
||||
temp = off+1; // number of values in B
|
||||
#endif
|
||||
|
||||
for (k=0; k<temp; k++)
|
||||
{
|
||||
b0 = ptrbb[0];
|
||||
|
||||
a0 = ptrba[0];
|
||||
res0_0 += a0*b0;
|
||||
|
||||
a1 = ptrba[1];
|
||||
res0_1 += a1*b0;
|
||||
|
||||
ptrba = ptrba+2;
|
||||
ptrbb = ptrbb+1;
|
||||
}
|
||||
|
||||
res0_0 *= alpha;
|
||||
res0_1 *= alpha;
|
||||
|
||||
C0[0] = res0_0;
|
||||
C0[1] = res0_1;
|
||||
|
||||
|
||||
#if ( defined(LEFT) && defined(TRANSA)) || (!defined(LEFT) && !defined(TRANSA))
|
||||
temp = bk - off;
|
||||
#ifdef LEFT
|
||||
temp -= 2; // number of values in A
|
||||
#else
|
||||
temp -= 1; // number of values in B
|
||||
#endif
|
||||
ptrba += temp*2;
|
||||
ptrbb += temp*1;
|
||||
#endif
|
||||
|
||||
#ifdef LEFT
|
||||
off += 2; // number of values in A
|
||||
#endif
|
||||
|
||||
C0 = C0+2;
|
||||
|
||||
}
|
||||
|
||||
if ( bm & 1 ) // do any 1x1 loop
|
||||
{
|
||||
|
||||
#if (defined(LEFT) && defined(TRANSA)) || (!defined(LEFT) && !defined(TRANSA))
|
||||
ptrbb = bb;
|
||||
#else
|
||||
ptrba += off*1;
|
||||
ptrbb = bb + off*1;
|
||||
#endif
|
||||
|
||||
res0_0 = 0;
|
||||
|
||||
|
||||
#if (defined(LEFT) && !defined(TRANSA)) || (!defined(LEFT) && defined(TRANSA))
|
||||
temp = bk-off;
|
||||
#elif defined(LEFT)
|
||||
temp = off+1; // number of values in A
|
||||
#else
|
||||
temp = off+1; // number of values in B
|
||||
#endif
|
||||
|
||||
for (k=0; k<temp; k++)
|
||||
{
|
||||
b0 = ptrbb[0];
|
||||
|
||||
a0 = ptrba[0];
|
||||
res0_0 += a0*b0;
|
||||
|
||||
ptrba = ptrba+1;
|
||||
ptrbb = ptrbb+1;
|
||||
}
|
||||
|
||||
res0_0 *= alpha;
|
||||
|
||||
C0[0] = res0_0;
|
||||
|
||||
|
||||
#if ( defined(LEFT) && defined(TRANSA)) || (!defined(LEFT) && !defined(TRANSA))
|
||||
temp = bk - off;
|
||||
#ifdef LEFT
|
||||
temp -= 1; // number of values in A
|
||||
#else
|
||||
temp -= 1; // number of values in B
|
||||
#endif
|
||||
ptrba += temp*1;
|
||||
ptrbb += temp*1;
|
||||
#endif
|
||||
|
||||
#ifdef LEFT
|
||||
off += 1; // number of values in A
|
||||
#endif
|
||||
|
||||
C0 = C0+1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if defined(TRMMKERNEL) && !defined(LEFT)
|
||||
off += 1;
|
||||
#endif
|
||||
|
||||
k = (bk<<0);
|
||||
bb = bb+k;
|
||||
C = C+ldc;
|
||||
}
|
||||
return 0;
|
||||
}
|
4
param.h
4
param.h
|
@ -2039,8 +2039,8 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#define GEMM_DEFAULT_OFFSET_B 0
|
||||
#define GEMM_DEFAULT_ALIGN 0x03fffUL
|
||||
|
||||
#define SGEMM_DEFAULT_UNROLL_M 2
|
||||
#define SGEMM_DEFAULT_UNROLL_N 2
|
||||
#define SGEMM_DEFAULT_UNROLL_M 4
|
||||
#define SGEMM_DEFAULT_UNROLL_N 4
|
||||
|
||||
#define DGEMM_DEFAULT_UNROLL_M 2
|
||||
#define DGEMM_DEFAULT_UNROLL_N 2
|
||||
|
|
Loading…
Reference in New Issue