SVE small SGEMM/DGEMM writes output padding at VL384 (QEMU)
維護者通常 1 天內回覆
還沒有人認領這個 Issue。
評估
- 難度
- 4/5
- 預估耗時
- 3-5 天
- 新手友好度
- 58/100
- Issue 類型
- 缺陷
- 描述清晰度
- 描述清楚
- 活躍度
- 活躍
- 技術堆疊
- c
- 領域
- performance
研究方向
Start with the two named files, kernel/arm64/sgemm_small_kernel_nn_sve.c near lines 250–251 and kernel/arm64/dgemm_small_kernel_nn_sve.c near lines 222–223, and inspect how their row-count bounds behave at VL384. Build OpenBLAS with the supplied AArch64/QEMU setup and run the repro.c SGEMM and DGEMM cases. Done means both calls produce nine zeros while preserving every allocated padding value of 17; verify other vector lengths remain unaffected.
由索引模型根據 Issue 內容生成。
描述
SVE small SGEMM/DGEMM writes output padding at VL384 (QEMU)
On OpenBLAS develop 277ef7801416412ee970873701fdf14d603d2c3f and release
v0.3.34, a public row-major 1-by-9 SGEMM or DGEMM with K=0 and beta=0
writes into padding beyond the nine output elements at SVE VL384 with
forced ARMV8SVE dispatch under QEMU. The one-call reproducer below
initializes the nine outputs to NaN and all remaining allocated elements
to 17. Correct output is nine zeros with every other element still 17.
The first padding element instead becomes zero.
QEMU 8.2.2 and 10.2.1 agree with ARMV8SVE, A64FX and NEOVERSEV1
dispatch. ARMV8 and NEOVERSEV2 preserve padding at VL384; the affected
tables pass these vectors at VL128, 256, 512, 1024 and 2048. Original
Reference BLAS v3.12.1 SGEMM/DGEMM, with equivalent column-major
dimensions, preserves the padding on both emulators at all six lengths.
All accesses demonstrated by this reproducer remain within its allocated
128-element arrays; the incorrect writes are outside the logical output.
Suspected cause
Row-major dimensions 1-by-9 become internal M=9, N=1. K=0 bypasses
GEMM-to-GEMV forwarding, while the small-matrix permit accepts the call.
Beta=0 selects sgemm_small_kernel_b0_nn or dgemm_small_kernel_b0_nn,
so this does not depend on the regular GEMM packers.
kernel/arm64/sgemm_small_kernel_nn_sve.c
near lines 250-251 and
kernel/arm64/dgemm_small_kernel_nn_sve.c
near lines 222-223 compute row counts as M & -(2*v_size) and
M & -v_size. At VL384, the respective lane counts are 12 and 6;
these masks do not compute floor-to-multiple counts. For example,
the float two-vector bound is 9 & -24 = 8, which enters a full
24-row store even though there are only nine output rows. The double
one-vector bound is 9 & -6 = 8, which permits two six-row stores.
Both explain the change to the first padding element without reading A
or B. Arithmetic count calculation is a candidate direction; no source
fix has been tested here.
Hardware scope
The names above select OpenBLAS dispatch tables on QEMU's max CPU.
Documented maximum SVE lengths for the named processors are 128 bits for
Neoverse N2/V2, 256 bits for Neoverse V1, and 512 bits for A64FX
(Arm, NVIDIA).
SVE permits non-power-of-two multiples of 128 bits;
VL384 is an architectural conformance case supported by QEMU. These forced
table/VL combinations do not establish a failure on the named native
processors. Native confirmation is unavailable.
Reproduce
On Linux, use Git, GNU Make, host GCC, an AArch64 GCC cross toolchain
with its glibc sysroot, and QEMU user mode. GCC 15.2 was used for the
reported builds. Save the C block below as repro.c in a clean
working directory, then run these commands from that directory:
git init openblas-src
git -C openblas-src fetch --depth=1 https://github.com/OpenMathLib/OpenBLAS.git 277ef7801416412ee970873701fdf14d603d2c3f
git -C openblas-src checkout --detach FETCH_HEAD
cd openblas-src
make -j4 ARCH=arm64 BINARY=64 TARGET=ARMV8 DYNAMIC_ARCH=1 \
'DYNAMIC_LIST=ARMV8SVE A64FX NEOVERSEV1 NEOVERSEN2' \
NOFORTRAN=1 NO_LAPACK=1 USE_THREAD=0 NUM_THREADS=1 HOSTCC=gcc \
CC=aarch64-linux-gnu-gcc AR=aarch64-linux-gnu-ar RANLIB=aarch64-linux-gnu-ranlib
make ARCH=arm64 BINARY=64 TARGET=ARMV8 DYNAMIC_ARCH=1 \
'DYNAMIC_LIST=ARMV8SVE A64FX NEOVERSEV1 NEOVERSEN2' \
NOFORTRAN=1 NO_LAPACK=1 USE_THREAD=0 NUM_THREADS=1 HOSTCC=gcc \
CC=aarch64-linux-gnu-gcc AR=aarch64-linux-gnu-ar RANLIB=aarch64-linux-gnu-ranlib \
PREFIX="$PWD/install" install
aarch64-linux-gnu-gcc -O2 -Wall -Wextra -Iinstall/include ../repro.c \
install/lib/libopenblas.a -lm -lpthread -o small-repro
OPENBLAS_CORETYPE=ARMV8SVE OPENBLAS_NUM_THREADS=1 \
qemu-aarch64 -L /usr/aarch64-linux-gnu \
-cpu max,sve-default-vector-length=48 ./small-repro 384 s
OPENBLAS_CORETYPE=ARMV8SVE OPENBLAS_NUM_THREADS=1 \
qemu-aarch64 -L /usr/aarch64-linux-gnu \
-cpu max,sve-default-vector-length=48 ./small-repro 384 d
The QEMU property is in bytes: 48 requests VL384.
Replace qemu-aarch64 with QEMU 8.2.2's qemu-aarch64-static to
repeat with the second emulator.
The program checks the actual vector length with PR_SVE_GET_VL and
prints the selected OpenBLAS core; confirm that the printed core matches
the requested dispatch table. Exit 0 means the checked values are right,
1 means a numerical or padding mismatch, and 2 means a setup/argument
failure rather than a valid numerical result. Each mode makes one public
BLAS call.
repro.c
/* Public beta-only SGEMM/DGEMM: SVE small-kernel VL384 count witness. */
#include <cblas.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/prctl.h>
int main(int argc,char **argv) {
int requested=argc>1?atoi(argv[1]):384;
int vl=prctl(51,0,0,0,0);
if(vl<0 || (vl&65535)*8!=requested)return 2;
int isdouble=argc>2&&!strcmp(argv[2],"d");
float af[128]={0},bf[128]={0},cf[128];
double ad[128]={0},bd[128]={0},cd[128];
for(int i=0;i<128;i++){cf[i]=cd[i]=i<9?NAN:17;}
if(isdouble)cblas_dgemm(CblasRowMajor,CblasNoTrans,CblasNoTrans,1,9,0,1,ad,1,bd,9,0,cd,12);
else cblas_sgemm(CblasRowMajor,CblasNoTrans,CblasNoTrans,1,9,0,1,af,1,bf,9,0,cf,12);
int wrong=0;
for(int i=0;i<128;i++)wrong+=(isdouble?cd[i]:cf[i])!=(i<9?0:17);
printf("SMALL-VL: %s precision=%c core=%s VL=%d m=1 n=9 k=0 padding=%g want=17 wrong=%d first_surfaced_by=differential\n",
wrong?"WRONG":"RIGHT",isdouble?'d':'s',openblas_get_corename(),requested,
isdouble?cd[9]:cf[9],wrong);
return wrong?1:0;
}
First surfaced by differential testing (first_surfaced_by: differential).
- 主要語言
- C
- 星號
- 7.6k
- 分支
- 1.7k
- 平均合併
- 1 天 11 小時
- 30 天內合併 PR
- 55
環境準備
這個專案沒有提供開發容器、Dockerfile 或貢獻指南,環境需要你自己搭建:先看它的 README,通用步驟見我們的新手貢獻指南。
從這裡開始
- 先讀完整個 Issue,再讀專案的貢獻指南。
- 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
- Fork 儲存庫,在一個分支上完成修改。
- 送出 Pull Request,並在描述裡引用這個 Issue 編號。
OpenMathLib/OpenBLAS 的其他 Issue
-
難度 5/5 一週以上 新手友好度 25/100
OpenMathLib/OpenBLAS#6119 · 2 則留言 ·
維護者通常 1 天內回覆
-
openblas_set_threads_callback_function is a silent no-op on Windows可能已有人在做 @martin-frbg 於 6 天前認領。 未關閉
難度 4/5 3-5 天 新手友好度 43/100
OpenMathLib/OpenBLAS#6108 · 2 則留言 · 1 個 reaction ·
維護者通常 1 天內回覆
-
難度 4/5 3-5 天 新手友好度 45/100
OpenMathLib/OpenBLAS#6104 ·
維護者通常 1 天內回覆
-
難度 4/5 3-5 天 新手友好度 52/100
OpenMathLib/OpenBLAS#6102 · 1 則留言 ·
維護者通常 1 天內回覆
-
難度 4/5 3-5 天 新手友好度 65/100
OpenMathLib/OpenBLAS#6100 · 2 則留言 ·
維護者通常 1 天內回覆
查看 OpenMathLib/OpenBLAS 的全部 Issue
相似的 Issue
-
難度 2/5 1-3 小時 新手友好度 80/100
維護者通常 1 天內回覆
-
難度 1/5 1 小時以內 新手友好度 85/100
libsdl-org/SDL#16530 ·
維護者通常 1 天內回覆
-
難度 2/5 1-3 小時 新手友好度 70/100
FriendsofECCE/ECCE#336 · 1 則留言 ·
-
難度 1/5 1 小時以內 新手友好度 85/100
fw876/helloworld#2067 ·
維護者通常 1 天內回覆
-
難度 2/5 1-3 小時 新手友好度 72/100
immortalwrt/immortalwrt#2501 ·