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 天 19 小时
- 30 天内合并 PR
- 53
环境准备
这个项目没有提供开发容器、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 于 8 天前认领。 未关闭
难度 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
-
backlog bug
难度 2/5 1-3 小时 新手友好度 75/100
EchoTools/nevr-runtime#653 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 75/100
InfiniTimeOrg/InfiniTime#2492 ·
-
难度 2/5 1-3 小时 新手友好度 80/100
维护者通常 1 天内回复
-
system: coco
难度 1/5 1 小时以内 新手友好度 90/100
FujiNetWIFI/fujinet-config#274 ·
维护者通常 1 天内回复
-
base-files: 82_config_generate: regenerate /etc/board.json if 0-bytes / truncated after power cut未关闭
难度 2/5 1-3 小时 新手友好度 72/100
openwrt/openwrt#25940 · 5 条评论 ·
维护者通常 1 天内回复