Skip to content

Commit cb66aca

Browse files
committed
Improve single-thread performance of [SD]GER on A64FX and Neoverse V1
1 parent aef36a3 commit cb66aca

File tree

3 files changed

+141
-0
lines changed

3 files changed

+141
-0
lines changed

kernel/arm64/KERNEL.A64FX

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,6 @@ SDOTKERNEL = dot_sve_v8.c
1010

1111
SAXPYKERNEL = axpy_sve.c
1212
DAXPYKERNEL = axpy_sve.c
13+
14+
SGERKERNEL = ger_sve_v1x3.c
15+
DGERKERNEL = ger_sve_v1x3.c

kernel/arm64/KERNEL.NEOVERSEV1

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,6 @@ SBGEMVNKERNEL = sbgemv_n_neon.c
7070
SBGEMVTKERNEL = sbgemv_t_bfdot.c
7171

7272
endif
73+
74+
SGERKERNEL = ger_sve_v1x3.c
75+
DGERKERNEL = ger_sve_v1x3.c

kernel/arm64/ger_sve_v1x3.c

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
/***************************************************************************
2+
Copyright (c) 2025, The OpenBLAS Project
3+
All rights reserved.
4+
5+
Redistribution and use in source and binary forms, with or without
6+
modification, are permitted provided that the following conditions are
7+
met:
8+
9+
1. Redistributions of source code must retain the above copyright
10+
notice, this list of conditions and the following disclaimer.
11+
12+
2. Redistributions in binary form must reproduce the above copyright
13+
notice, this list of conditions and the following disclaimer in
14+
the documentation and/or other materials provided with the
15+
distribution.
16+
3. Neither the name of the OpenBLAS project nor the names of
17+
its contributors may be used to endorse or promote products
18+
derived from this software without specific prior written
19+
permission.
20+
21+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24+
ARE DISCLAIMED. IN NO EVENT SHALL THE OPENBLAS PROJECT OR CONTRIBUTORS BE
25+
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
30+
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31+
*****************************************************************************/
32+
33+
#include <arm_sve.h>
34+
#include "common.h"
35+
36+
#ifdef DOUBLE
37+
#define SV_COUNT svcntd
38+
#define SV_TYPE svfloat64_t
39+
#define SV_TRUE svptrue_b64
40+
#define SV_WHILE svwhilelt_b64_s64
41+
#define SV_DUP svdup_f64
42+
#else
43+
#define SV_COUNT svcntw
44+
#define SV_TYPE svfloat32_t
45+
#define SV_TRUE svptrue_b32
46+
#define SV_WHILE svwhilelt_b32_s64
47+
#define SV_DUP svdup_f32
48+
#endif
49+
50+
int CNAME(BLASLONG m, BLASLONG n, BLASLONG dummy1, FLOAT alpha,
51+
FLOAT *x, BLASLONG incx,
52+
FLOAT *y, BLASLONG incy,
53+
FLOAT *a, BLASLONG lda, FLOAT *buffer){
54+
55+
FLOAT *X = x;
56+
57+
if (incx != 1) {
58+
X = buffer;
59+
COPY_K(m, x, incx, X, 1);
60+
}
61+
62+
BLASLONG width = (n + 3 - 1) / 3;
63+
BLASLONG i, j;
64+
BLASLONG sve_size = SV_COUNT();
65+
66+
FLOAT *y0_ptr = y + incy * width * 0;
67+
FLOAT *y1_ptr = y + incy * width * 1;
68+
FLOAT *y2_ptr = y + incy * width * 2;
69+
70+
for (j = 0; j < width; j++) {
71+
svbool_t pg00 = (j + width * 0 < n) ? SV_TRUE() : svpfalse();
72+
svbool_t pg01 = (j + width * 1 < n) ? SV_TRUE() : svpfalse();
73+
svbool_t pg02 = (j + width * 2 < n) ? SV_TRUE() : svpfalse();
74+
75+
SV_TYPE temp0_vec = (j + width * 0 < n) ? SV_DUP(alpha * *y0_ptr) : SV_DUP(0.0);
76+
SV_TYPE temp1_vec = (j + width * 1 < n) ? SV_DUP(alpha * *y1_ptr) : SV_DUP(0.0);
77+
SV_TYPE temp2_vec = (j + width * 2 < n) ? SV_DUP(alpha * *y2_ptr) : SV_DUP(0.0);
78+
79+
FLOAT *x_ptr = X;
80+
FLOAT *a0_ptr = a + lda * width * 0 + lda * j;
81+
FLOAT *a1_ptr = a + lda * width * 1 + lda * j;
82+
FLOAT *a2_ptr = a + lda * width * 2 + lda * j;
83+
84+
i = 0;
85+
while (i + sve_size * 1 - 1 < m) {
86+
SV_TYPE x0_vec = svld1_vnum(SV_TRUE(), x_ptr, 0);
87+
88+
SV_TYPE a00_vec = svld1_vnum(pg00, a0_ptr, 0);
89+
SV_TYPE a01_vec = svld1_vnum(pg01, a1_ptr, 0);
90+
SV_TYPE a02_vec = svld1_vnum(pg02, a2_ptr, 0);
91+
92+
a00_vec = svmla_x(pg00, a00_vec, temp0_vec, x0_vec);
93+
a01_vec = svmla_x(pg01, a01_vec, temp1_vec, x0_vec);
94+
a02_vec = svmla_x(pg02, a02_vec, temp2_vec, x0_vec);
95+
96+
svst1_vnum(pg00, a0_ptr, 0, a00_vec);
97+
svst1_vnum(pg01, a1_ptr, 0, a01_vec);
98+
svst1_vnum(pg02, a2_ptr, 0, a02_vec);
99+
100+
i += sve_size * 1;
101+
x_ptr += sve_size * 1;
102+
a0_ptr += sve_size * 1;
103+
a1_ptr += sve_size * 1;
104+
a2_ptr += sve_size * 1;
105+
}
106+
107+
if (i < m) {
108+
svbool_t pg0 = SV_WHILE(i + sve_size * 0, m);
109+
110+
pg00 = svand_z(SV_TRUE(), pg0, pg00);
111+
pg01 = svand_z(SV_TRUE(), pg0, pg01);
112+
pg02 = svand_z(SV_TRUE(), pg0, pg02);
113+
114+
SV_TYPE x0_vec = svld1_vnum(pg0, x_ptr, 0);
115+
116+
SV_TYPE a00_vec = svld1_vnum(pg00, a0_ptr, 0);
117+
SV_TYPE a01_vec = svld1_vnum(pg01, a1_ptr, 0);
118+
SV_TYPE a02_vec = svld1_vnum(pg02, a2_ptr, 0);
119+
120+
a00_vec = svmla_x(pg00, a00_vec, temp0_vec, x0_vec);
121+
a01_vec = svmla_x(pg01, a01_vec, temp1_vec, x0_vec);
122+
a02_vec = svmla_x(pg02, a02_vec, temp2_vec, x0_vec);
123+
124+
svst1_vnum(pg00, a0_ptr, 0, a00_vec);
125+
svst1_vnum(pg01, a1_ptr, 0, a01_vec);
126+
svst1_vnum(pg02, a2_ptr, 0, a02_vec);
127+
}
128+
129+
y0_ptr += incy;
130+
y1_ptr += incy;
131+
y2_ptr += incy;
132+
}
133+
134+
return 0;
135+
}

0 commit comments

Comments
 (0)