Browse Source

Merge branch 'OpenMathLib:develop' into gemmt_tests

pull/5187/head
Martin Kroeker GitHub 11 months ago
parent
commit
4e0cf1eccb
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
79 changed files with 3393 additions and 338 deletions
  1. +2
    -1
      .github/workflows/arm64_graviton.yml
  2. +82
    -0
      .github/workflows/windows_arm64.yml
  3. +7
    -1
      .gitignore
  4. +13
    -1
      CONTRIBUTORS.md
  5. +6
    -4
      Makefile.system
  6. +33
    -2
      Makefile.tail
  7. +1
    -0
      README.md
  8. +1
    -0
      TargetList.txt
  9. +33
    -1
      benchmark/Makefile
  10. +12
    -0
      benchmark/gemm.c
  11. +31
    -0
      cblas.h
  12. +3
    -3
      cmake/cc.cmake
  13. +43
    -0
      cmake/kernel.cmake
  14. +30
    -0
      cmake/prebuild.cmake
  15. +4
    -4
      cmake/system.cmake
  16. +29
    -1
      cmake/utils.cmake
  17. +6
    -1
      common.h
  18. +100
    -0
      common_b.h
  19. +6
    -0
      common_interface.h
  20. +4
    -0
      common_level1.h
  21. +6
    -0
      common_level2.h
  22. +24
    -0
      common_level3.h
  23. +57
    -5
      common_macro.h
  24. +48
    -1
      common_param.h
  25. +2
    -0
      common_s.h
  26. +4
    -0
      cpuid.S
  27. +4
    -0
      cpuid_power.c
  28. +3
    -1
      cpuid_x86.c
  29. +10
    -2
      docs/install.md
  30. +35
    -0
      driver/level2/Makefile
  31. +10
    -9
      driver/level2/sbgemv_thread.c
  32. +55
    -0
      driver/level3/Makefile
  33. +19
    -6
      driver/level3/level3.c
  34. +19
    -7
      driver/level3/level3_thread.c
  35. +10
    -0
      driver/others/dynamic_power.c
  36. +17
    -0
      driver/others/parameter.c
  37. +29
    -1
      exports/gensymbol
  38. +29
    -1
      exports/gensymbol.pl
  39. +3
    -3
      getarch.c
  40. +32
    -0
      getarch_2nd.c
  41. +30
    -0
      interface/CMakeLists.txt
  42. +53
    -3
      interface/Makefile
  43. +10
    -2
      interface/gemm.c
  44. +2
    -2
      interface/sbgemmt.c
  45. +32
    -14
      interface/sbgemv.c
  46. +9
    -1
      interface/scal.c
  47. +49
    -0
      kernel/CMakeLists.txt
  48. +36
    -0
      kernel/Makefile.L1
  49. +43
    -0
      kernel/Makefile.L2
  50. +91
    -4
      kernel/Makefile.L3
  51. +3
    -0
      kernel/arm64/KERNEL.A64FX
  52. +42
    -1
      kernel/arm64/KERNEL.NEOVERSEV1
  53. +107
    -0
      kernel/arm64/bgemm_beta_neon.c
  54. +50
    -0
      kernel/arm64/bgemm_kernel_4x4_neoversev1.c
  55. +429
    -0
      kernel/arm64/bgemm_kernel_4x4_neoversev1_impl.c
  56. +4
    -0
      kernel/arm64/dot.c
  57. +146
    -0
      kernel/arm64/dot_kernel_sve_v8.c
  58. +34
    -0
      kernel/arm64/dot_sve_v8.c
  59. +57
    -39
      kernel/arm64/gemv_n_sve_v1x3.c
  60. +199
    -0
      kernel/arm64/sgemm_direct_alpha_beta_arm64_sme1.c
  61. +46
    -0
      kernel/arm64/sme_abi.h
  62. +64
    -0
      kernel/generic/bf16_macros.h
  63. +50
    -19
      kernel/generic/gemm_beta.c
  64. +52
    -35
      kernel/generic/gemmkernel_2x2.c
  65. +70
    -0
      kernel/generic/gemv_n.c
  66. +60
    -0
      kernel/generic/gemv_t.c
  67. +106
    -0
      kernel/generic/scal.c
  68. +42
    -3
      kernel/setparam-ref.c
  69. +6
    -0
      lapack-netlib/LAPACKE/src/lapacke_dtrsen.c
  70. +7
    -0
      lapack-netlib/LAPACKE/src/lapacke_strsen.c
  71. +1
    -1
      lapack/CMakeLists.txt
  72. +3
    -2
      lapack/potrf/potrf_parallel.c
  73. +16
    -1
      param.h
  74. +73
    -6
      test/Makefile
  75. +155
    -0
      test/compare_sgemm_bgemm.c
  76. +11
    -150
      test/compare_sgemm_sbgemm.c
  77. +149
    -0
      test/compare_sgemv_bgemv.c
  78. +128
    -0
      test/compare_sgemv_sbgemv.c
  79. +66
    -0
      test/test_helpers.h

+ 2
- 1
.github/workflows/arm64_graviton.yml View File

@@ -88,13 +88,14 @@ jobs:
run: |
case "${{ matrix.build }}" in
"make")
make -j$(nproc) DYNAMIC_ARCH=1 USE_OPENMP=0 FC="ccache ${{ matrix.fortran }}"
make -j$(nproc) DYNAMIC_ARCH=1 BUILD_BFLOAT16=1 USE_OPENMP=0 FC="ccache ${{ matrix.fortran }}"
;;
"cmake")
mkdir build && cd build
cmake -DDYNAMIC_ARCH=1 \
-DNOFORTRAN=0 \
-DBUILD_WITHOUT_LAPACK=0 \
-DBUILD_BFLOAT16=1 \
-DCMAKE_VERBOSE_MAKEFILE=ON \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_Fortran_COMPILER=${{ matrix.fortran }} \


+ 82
- 0
.github/workflows/windows_arm64.yml View File

@@ -0,0 +1,82 @@
name: Windows ARM64 CI

on:
push:
branches:
- develop
- release-**
pull_request:
branches:
- develop
- release-**

concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true

permissions:
contents: read # to fetch code (actions/checkout)

jobs:
build:
if: "github.repository == 'OpenMathLib/OpenBLAS'"
runs-on: windows-11-arm
steps:
- name: Checkout repository
uses: actions/checkout@v3

- name: Install LLVM for Win-ARM64
shell: pwsh
run: |
Invoke-WebRequest https://github.com/llvm/llvm-project/releases/download/llvmorg-20.1.6/LLVM-20.1.6-woa64.exe -UseBasicParsing -OutFile LLVM-woa64.exe
Start-Process -FilePath ".\LLVM-woa64.exe" -ArgumentList "/S" -Wait
echo "C:\Program Files\LLVM\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append

- name: Install CMake and Ninja for Win-ARM64
shell: pwsh
run: |
Invoke-WebRequest https://github.com/Kitware/CMake/releases/download/v3.29.4/cmake-3.29.4-windows-arm64.msi -OutFile cmake-arm64.msi
Start-Process msiexec.exe -ArgumentList "/i cmake-arm64.msi /quiet /norestart" -Wait
echo "C:\Program Files\CMake\bin" >> $env:GITHUB_PATH
Invoke-WebRequest https://github.com/ninja-build/ninja/releases/download/v1.13.1/ninja-winarm64.zip -OutFile ninja-winarm64.zip
Expand-Archive ninja-winarm64.zip -DestinationPath ninja
Copy-Item ninja\ninja.exe -Destination "C:\Windows\System32"

- name: Configure OpenBLAS
shell: cmd
run: |
CALL "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsarm64.bat"
mkdir build
cd build
cmake .. -G Ninja ^
-DCMAKE_BUILD_TYPE=Release ^
-DTARGET=ARMV8 ^
-DBINARY=64 ^
-DCMAKE_C_COMPILER=clang-cl ^
-DCMAKE_Fortran_COMPILER=flang-new ^
-DBUILD_SHARED_LIBS=ON ^
-DCMAKE_SYSTEM_PROCESSOR=arm64 ^
-DCMAKE_SYSTEM_NAME=Windows ^
-DCMAKE_INSTALL_PREFIX=C:/opt

- name: Build OpenBLAS
shell: cmd
run: |
cd build
ninja -j16

- name: Install OpenBLAS
shell: cmd
run: |
cd build
cmake --install .

- name: Run ctests
shell: pwsh
run: |
$env:PATH = "C:\opt\bin;$env:PATH"
cd build
ctest



+ 7
- 1
.gitignore View File

@@ -13,8 +13,8 @@ lapack-3.4.1.tgz
lapack-3.4.2
lapack-3.4.2.tgz
lapack-netlib/make.inc
lapack-netlib/lapacke/include/lapacke_mangling.h
lapack-netlib/SRC/la_constants.mod
lapack-netlib/SRC/la_xisnan.mod
lapack-netlib/TESTING/testing_results.txt
lapack-netlib/INSTALL/test*
lapack-netlib/TESTING/xeigtstc
@@ -81,7 +81,10 @@ test/ZBLAT2.SUMM
test/ZBLAT3.SUMM
test/ZBLAT3_3M.SUMM
test/SHBLAT3.SUMM
test/SBBLAT2.SUMM
test/SBBLAT3.SUMM
test/BBLAT2.SUMM
test/BBLAT3.SUMM
test/cblat1
test/cblat2
test/cblat3
@@ -96,6 +99,9 @@ test/sblat3
test/sblat3_3m
test/test_shgemm
test/test_sbgemm
test/test_sbgemv
test/test_bgemm
test/test_bgemv
test/zblat1
test/zblat2
test/zblat3


+ 13
- 1
CONTRIBUTORS.md View File

@@ -251,6 +251,18 @@ In chronological order:
* Ye Tao <ye.tao@arm.com>
* [2025-02-03] Optimize SBGEMM kernel on NEOVERSEV1
* [2025-02-27] Add sbgemv_n_neon kernel
* [2025-05-17] Impl prototype of BGEMM inferface

* Abhishek Kumar <https://github.com/abhishek-iitmadras>
* [2025-04-22] Optimise dot kernel for NEOVERSE V1
* [2025-04-22] Optimise dot kernel for NEOVERSE V1

* Sharif Inamdar <sharif.inamdar@arm.com>
* [2025-06-05] Optimize gemv_n_sve_v1x3 kernel

* Guoyuan Li <https://github.com/guoyuanplct>
* [2025-04-11] Optimise gemv kernel for RISCV64_ZVL256B
* [2025-05-01] Optimise zgemv kernel for RISCV64_ZVL256B
* [2025-05-17] Optimise omatcopy/zomatcopy kernel for RISCV64_ZVL256B
* [2025-05-29] Optimise axpby kernel for RISCV64_ZVL256B
* [2025-06-05] Optimise hbmv kernel for RISCV64_ZVL256B


+ 6
- 4
Makefile.system View File

@@ -276,14 +276,14 @@ SMALL_MATRIX_OPT = 1
endif
ifeq ($(ARCH), arm64)
GEMM_GEMV_FORWARD = 1
GEMM_GEMV_FORWARD_BF16 = 1
SBGEMM_GEMV_FORWARD = 1
endif
ifeq ($(ARCH), riscv)
GEMM_GEMV_FORWARD = 1
endif
ifeq ($(ARCH), power)
GEMM_GEMV_FORWARD = 1
GEMM_GEMV_FORWARD_BF16 = 1
SBGEMM_GEMV_FORWARD = 1
endif

ifeq ($(SMALL_MATRIX_OPT), 1)
@@ -293,8 +293,8 @@ ifneq ($(ONLY_CBLAS), 1)
ifeq ($(GEMM_GEMV_FORWARD), 1)
CCOMMON_OPT += -DGEMM_GEMV_FORWARD
endif
ifeq ($(GEMM_GEMV_FORWARD_BF16), 1)
CCOMMON_OPT += -DGEMM_GEMV_FORWARD_BF16
ifeq ($(SBGEMM_GEMV_FORWARD), 1)
CCOMMON_OPT += -DSBGEMM_GEMV_FORWARD
endif
endif

@@ -1905,6 +1905,8 @@ export BUILD_HFLOAT16
export NO_LSX
export NO_LASX

export BGEMM_UNROLL_M
export BGEMM_UNROLL_N
export SBGEMM_UNROLL_M
export SBGEMM_UNROLL_N
export SHGEMM_UNROLL_M


+ 33
- 2
Makefile.tail View File

@@ -1,3 +1,32 @@
###############################################################################
# Copyright (c) 2025, 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.
###############################################################################

BBLASOBJS_P = $(BBLASOBJS:.$(SUFFIX)=.$(PSUFFIX))
SBBLASOBJS_P = $(SBBLASOBJS:.$(SUFFIX)=.$(PSUFFIX))
SHBLASPBJS_P = $(SHBLASOBJS:.$(SUFFIX)=.$(PSUFFIX))
SBLASOBJS_P = $(SBLASOBJS:.$(SUFFIX)=.$(PSUFFIX))
@@ -12,8 +41,8 @@ COMMONOBJS_P = $(COMMONOBJS:.$(SUFFIX)=.$(PSUFFIX))

HPLOBJS_P = $(HPLOBJS:.$(SUFFIX)=.$(PSUFFIX))

BLASOBJS = $(SHBLASOBJS) $(SBEXTOBJS) $(SBBLASOBJS) $(SBLASOBJS) $(DBLASOBJS) $(CBLASOBJS) $(ZBLASOBJS) $(CBAUXOBJS)
BLASOBJS_P = $(SHBLASPBJS_P) $(SBEXTOBJS_P) $(SBBLASOBJS_P) $(SBLASOBJS_P) $(DBLASOBJS_P) $(CBLASOBJS_P) $(ZBLASOBJS_P) $(CBAUXOBJS_P)
BLASOBJS = $(SHBLASOBJS) $(BBLASOBJS) $(SBEXTOBJS) $(SBBLASOBJS) $(SBLASOBJS) $(DBLASOBJS) $(CBLASOBJS) $(ZBLASOBJS) $(CBAUXOBJS)
BLASOBJS_P = $(SHBLASPBJS_P) $(BBLASOBJS_P) $(SBEXTOBJS_P) $(SBBLASOBJS_P) $(SBLASOBJS_P) $(DBLASOBJS_P) $(CBLASOBJS_P) $(ZBLASOBJS_P) $(CBAUXOBJS_P)

ifdef EXPRECISION
BLASOBJS += $(QBLASOBJS) $(XBLASOBJS)
@@ -26,6 +55,7 @@ BLASOBJS_P += $(QBLASOBJS_P) $(XBLASOBJS_P)
endif

$(SHBLASOBJS) $(SHBLASOBJS_P) : override CFLAGS += -DHFLOAT16 -UDOUBLE -UCOMPLEX
$(BBLASOBJS) $(BBLASOBJS_P) : override CFLAGS += -DBFLOAT16 -DBGEMM -UDOUBLE -UCOMPLEX
$(SBBLASOBJS) $(SBBLASOBJS_P) : override CFLAGS += -DBFLOAT16 -UDOUBLE -UCOMPLEX
$(SBLASOBJS) $(SBLASOBJS_P) : override CFLAGS += -UDOUBLE -UCOMPLEX
$(DBLASOBJS) $(DBLASOBJS_P) : override CFLAGS += -DDOUBLE -UCOMPLEX
@@ -36,6 +66,7 @@ $(XBLASOBJS) $(XBLASOBJS_P) : override CFLAGS += -DXDOUBLE -DCOMPLEX
$(SBEXTOBJS) $(SBEXTOBJS_P) : override CFLAGS += -DBFLOAT16 -UDOUBLE -UCOMPLEX

$(SHBLASOBJS_P) : override CFLAGS += -DPROFILE $(COMMON_PROF)
$(BBLASOBJS_P) : override CFLAGS += -DPROFILE $(COMMON_PROF)
$(SBBLASOBJS_P) : override CFLAGS += -DPROFILE $(COMMON_PROF)
$(SBLASOBJS_P) : override CFLAGS += -DPROFILE $(COMMON_PROF)
$(DBLASOBJS_P) : override CFLAGS += -DPROFILE $(COMMON_PROF)


+ 1
- 0
README.md View File

@@ -29,6 +29,7 @@ For a general introduction to the BLAS routines, please refer to the extensive d
We provide official binary packages for the following platform:

* Windows x86/x86_64
* Windows arm64 (woa)

You can download them from [file hosting on sourceforge.net](https://sourceforge.net/projects/openblas/files/) or from the [Releases section of the GitHub project page](https://github.com/OpenMathLib/OpenBLAS/releases).



+ 1
- 0
TargetList.txt View File

@@ -52,6 +52,7 @@ POWER7
POWER8
POWER9
POWER10
POWER11
PPCG4
PPC970
PPC970MP


+ 33
- 1
benchmark/Makefile View File

@@ -1,3 +1,31 @@
###############################################################################
# Copyright (c) 2025, 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.
###############################################################################

TOPDIR = ..
include $(TOPDIR)/Makefile.system

@@ -56,7 +84,7 @@ GOTO_LAPACK_TARGETS=
endif

ifeq ($(BUILD_BFLOAT16),1)
GOTO_BFLOAT_TARGETS=sbgemm.goto
GOTO_BFLOAT_TARGETS=bgemm.goto sbgemm.goto
else
GOTO_BFLOAT_TARGETS=
endif
@@ -635,6 +663,8 @@ zcholesky.essl : zcholesky.$(SUFFIX)

##################################### Sgemm ####################################################
ifeq ($(BUILD_BFLOAT16),1)
bgemm.goto : bgemm.$(SUFFIX) ../$(LIBNAME)
$(CC) $(CFLAGS) -o $(@F) $^ $(CEXTRALIB) $(EXTRALIB) $(FEXTRALIB) -lm
sbgemm.goto : sbgemm.$(SUFFIX) ../$(LIBNAME)
$(CC) $(CFLAGS) -o $(@F) $^ $(CEXTRALIB) $(EXTRALIB) $(FEXTRALIB) -lm
endif
@@ -2970,6 +3000,8 @@ zcholesky.$(SUFFIX) : cholesky.c
$(CC) $(CFLAGS) -c -DCOMPLEX -DDOUBLE -o $(@F) $^

ifeq ($(BUILD_BFLOAT16),1)
bgemm.$(SUFFIX) : gemm.c
$(CC) $(CFLAGS) -c -DBFLOAT16 -DBGEMM -UCOMPLEX -UDOUBLE -o $(@F) $^
sbgemm.$(SUFFIX) : gemm.c
$(CC) $(CFLAGS) -c -DBFLOAT16 -UCOMPLEX -UDOUBLE -o $(@F) $^
endif


+ 12
- 0
benchmark/gemm.c View File

@@ -33,6 +33,8 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#ifdef DOUBLE
#define GEMM BLASFUNC(dgemm)
#elif defined(BFLOAT16) && defined(BGEMM)
#define GEMM BLASFUNC(bgemm)
#elif defined(BFLOAT16)
#define GEMM BLASFUNC(sbgemm)
#undef IFLOAT
@@ -60,8 +62,18 @@ int main(int argc, char *argv[]){

IFLOAT *a, *b;
FLOAT *c;
#ifdef BGEMM
blasint one=1;
blasint two=2;
float alpha_in[] = {1.0, 0.0};
float beta_in[] = {0.0, 0.0};
FLOAT alpha[2], beta[2];
sbstobf16_(&two, alpha_in, &one, alpha, &one);
sbstobf16_(&two, beta_in, &one, beta, &one);
#else
FLOAT alpha[] = {1.0, 0.0};
FLOAT beta [] = {0.0, 0.0};
#endif
char transa = 'N';
char transb = 'N';
blasint m, n, k, i, j, lda, ldb, ldc;


+ 31
- 0
cblas.h View File

@@ -1,3 +1,31 @@
/***************************************************************************
* Copyright (c) 2025, 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.
* *****************************************************************************/

#ifndef CBLAS_H
#define CBLAS_H

@@ -445,10 +473,13 @@ void cblas_sbdtobf16(OPENBLAS_CONST blasint n, OPENBLAS_CONST double *in, OPEN
void cblas_sbf16tos(OPENBLAS_CONST blasint n, OPENBLAS_CONST bfloat16 *in, OPENBLAS_CONST blasint incin, float *out, OPENBLAS_CONST blasint incout);
/* convert BFLOAT16 array to double array */
void cblas_dbf16tod(OPENBLAS_CONST blasint n, OPENBLAS_CONST bfloat16 *in, OPENBLAS_CONST blasint incin, double *out, OPENBLAS_CONST blasint incout);
void cblas_bgemv(OPENBLAS_CONST enum CBLAS_ORDER order, OPENBLAS_CONST enum CBLAS_TRANSPOSE trans, OPENBLAS_CONST blasint m, OPENBLAS_CONST blasint n, OPENBLAS_CONST bfloat16 alpha, OPENBLAS_CONST bfloat16 *a, OPENBLAS_CONST blasint lda, OPENBLAS_CONST bfloat16 *x, OPENBLAS_CONST blasint incx, OPENBLAS_CONST bfloat16 beta, bfloat16 *y, OPENBLAS_CONST blasint incy);
/* dot production of BFLOAT16 input arrays, and output as float */
float cblas_sbdot(OPENBLAS_CONST blasint n, OPENBLAS_CONST bfloat16 *x, OPENBLAS_CONST blasint incx, OPENBLAS_CONST bfloat16 *y, OPENBLAS_CONST blasint incy);
void cblas_sbgemv(OPENBLAS_CONST enum CBLAS_ORDER order, OPENBLAS_CONST enum CBLAS_TRANSPOSE trans, OPENBLAS_CONST blasint m, OPENBLAS_CONST blasint n, OPENBLAS_CONST float alpha, OPENBLAS_CONST bfloat16 *a, OPENBLAS_CONST blasint lda, OPENBLAS_CONST bfloat16 *x, OPENBLAS_CONST blasint incx, OPENBLAS_CONST float beta, float *y, OPENBLAS_CONST blasint incy);

void cblas_bgemm(OPENBLAS_CONST enum CBLAS_ORDER Order, OPENBLAS_CONST enum CBLAS_TRANSPOSE TransA, OPENBLAS_CONST enum CBLAS_TRANSPOSE TransB, OPENBLAS_CONST blasint M, OPENBLAS_CONST blasint N, OPENBLAS_CONST blasint K,
OPENBLAS_CONST bfloat16 alpha, OPENBLAS_CONST bfloat16 *A, OPENBLAS_CONST blasint lda, OPENBLAS_CONST bfloat16 *B, OPENBLAS_CONST blasint ldb, OPENBLAS_CONST bfloat16 beta, bfloat16 *C, OPENBLAS_CONST blasint ldc);
void cblas_sbgemm(OPENBLAS_CONST enum CBLAS_ORDER Order, OPENBLAS_CONST enum CBLAS_TRANSPOSE TransA, OPENBLAS_CONST enum CBLAS_TRANSPOSE TransB, OPENBLAS_CONST blasint M, OPENBLAS_CONST blasint N, OPENBLAS_CONST blasint K,
OPENBLAS_CONST float alpha, OPENBLAS_CONST bfloat16 *A, OPENBLAS_CONST blasint lda, OPENBLAS_CONST bfloat16 *B, OPENBLAS_CONST blasint ldb, OPENBLAS_CONST float beta, float *C, OPENBLAS_CONST blasint ldc);
void cblas_sbgemm_batch(OPENBLAS_CONST enum CBLAS_ORDER Order, OPENBLAS_CONST enum CBLAS_TRANSPOSE * TransA_array, OPENBLAS_CONST enum CBLAS_TRANSPOSE * TransB_array, OPENBLAS_CONST blasint * M_array, OPENBLAS_CONST blasint * N_array, OPENBLAS_CONST blasint * K_array,


+ 3
- 3
cmake/cc.cmake View File

@@ -211,14 +211,14 @@ endif ()
if (${CORE} STREQUAL NEOVERSEV1)
if (NOT DYNAMIC_ARCH)
if (${CMAKE_C_COMPILER_ID} STREQUAL "PGI" AND NOT NO_SVE)
set (CCOMMON_OPT "${CCOMMON_OPT} -Msve_intrinsics -march=armv8.4-a+sve -mtune=neoverse-v1")
set (CCOMMON_OPT "${CCOMMON_OPT} -Msve_intrinsics -march=armv8.4-a+sve+bf16 -mtune=neoverse-v1")
elseif (${CMAKE_C_COMPILER_ID} STREQUAL "NVC" AND NOT NO_SVE)
set (CCOMMON_OPT "${CCOMMON_OPT} -tp=neoverse-v1")
else ()
if (${GCC_VERSION} VERSION_GREATER 10.4 OR ${GCC_VERSION} VERSION_EQUAL 10.4)
set (CCOMMON_OPT "${CCOMMON_OPT} -march=armv8.4-a+sve -mtune=neoverse-v1")
set (CCOMMON_OPT "${CCOMMON_OPT} -march=armv8.4-a+sve+bf16 -mtune=neoverse-v1")
else ()
set (CCOMMON_OPT "${CCOMMON_OPT} -march=armv8.2-a+sve")
set (CCOMMON_OPT "${CCOMMON_OPT} -march=armv8.2-a+sve+bf16")
endif()
endif()
endif ()


+ 43
- 0
cmake/kernel.cmake View File

@@ -1,3 +1,31 @@
###############################################################################
# Copyright (c) 2025, 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.
###############################################################################

# helper functions for the kernel CMakeLists.txt

function(SetFallback KERNEL SOURCE_PATH)
@@ -82,6 +110,7 @@ macro(SetDefaultL1)
SetFallback(SROTMKERNEL rotm.S)
SetFallback(DROTMKERNEL rotm.S)
SetFallback(QROTMKERNEL rotm.S)
SetFallback(BSCALKERNEL ../generic/scal.c)
SetFallback(SSCALKERNEL scal.S)
SetFallback(DSCALKERNEL scal.S)
SetFallback(CSCALKERNEL zscal.S)
@@ -141,6 +170,8 @@ if (BUILD_BFLOAT16)
SetFallback(SHSWAPKERNEL ../arm/swap.c)
SetFallback(TOBF16KERNEL ../x86_64/tobf16.c)
SetFallback(BF16TOKERNEL ../x86_64/bf16to.c)
SetFallback(BGEMVNKERNEL ../generic/gemv_n.c)
SetFallback(BGEMVTKERNEL ../generic/gemv_t.c)
SetFallback(SBGEMVNKERNEL ../x86_64/sbgemv_n.c)
SetFallback(SBGEMVTKERNEL ../x86_64/sbgemv_t.c)
endif ()
@@ -193,6 +224,8 @@ macro(SetDefaultL2)
SetFallback(XHEMV_V_KERNEL ../generic/zhemv_k.c)
SetFallback(XHEMV_M_KERNEL ../generic/zhemv_k.c)
if (BUILD_BFLOAT16)
SetFallback(BGEMVNKERNEL ../generic/gemv_n.c)
SetFallback(BGEMVTKERNEL ../generic/gemv_t.c)
SetFallback(SBGEMVNKERNEL ../x86_64/sbgemv_n.c)
SetFallback(SBGEMVTKERNEL ../x86_64/sbgemv_t.c)
SetFallback(SHGERKERNEL ../generic/ger.c)
@@ -206,6 +239,16 @@ macro(SetDefaultL3)
SetFallback(ZGEADD_KERNEL ../generic/zgeadd.c)
if (BUILD_BFLOAT16)
SetFallback(SHGEADD_KERNEL ../generic/geadd.c)
SetFallback(BGEMMKERNEL ../generic/gemmkernel_2x2.c)
SetFallback(BGEMM_BETA ../generic/gemm_beta.c)
SetFallback(BGEMMINCOPY ../generic/gemm_ncopy_2.c)
SetFallback(BGEMMITCOPY ../generic/gemm_tcopy_2.c)
SetFallback(BGEMMONCOPY ../generic/gemm_ncopy_2.c)
SetFallback(BGEMMOTCOPY ../generic/gemm_tcopy_2.c)
SetFallback(BGEMMINCOPYOBJ bgemm_incopy.o)
SetFallback(BGEMMITCOPYOBJ bgemm_itcopy.o)
SetFallback(BGEMMONCOPYOBJ bgemm_oncopy.o)
SetFallback(BGEMMOTCOPYOBJ bgemm_otcopy.o)
SetFallback(SBGEMMKERNEL ../generic/gemmkernel_2x2.c)
SetFallback(SBGEMM_BETA ../generic/gemm_beta.c)
SetFallback(SBGEMMINCOPY ../generic/gemm_ncopy_2.c)


+ 30
- 0
cmake/prebuild.cmake View File

@@ -1,3 +1,31 @@
###############################################################################
# Copyright (c) 2025, 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.
###############################################################################

##
## Author: Hank Anderson <hank@statease.com>
## Description: Ported from OpenBLAS/Makefile.prebuild
@@ -131,6 +159,8 @@ if (DEFINED CORE AND CMAKE_CROSSCOMPILING AND NOT (${HOST_OS} STREQUAL "WINDOWSS
set(HAVE_SSE2 1)
set(HAVE_SSE3 1)
set(HAVE_SSSE3 1)
set(BGEMM_UNROLL_M 8)
set(BGEMM_UNROLL_N 4)
set(SBGEMM_UNROLL_M 8)
set(SBGEMM_UNROLL_N 4)
set(SGEMM_UNROLL_M 8)


+ 4
- 4
cmake/system.cmake View File

@@ -291,10 +291,10 @@ if (DEFINED TARGET)

if (${TARGET} STREQUAL NEOVERSEV1)
if (${CMAKE_C_COMPILER_ID} STREQUAL "PGI" AND NOT NO_SVE)
set (KERNEL_DEFINITIONS "${KERNEL_DEFINITIONS} -Msve_intrinsics -march=armv8.4-a+sve -mtune=neoverse-v1")
set (KERNEL_DEFINITIONS "${KERNEL_DEFINITIONS} -Msve_intrinsics -march=armv8.4-a+sve+bf16 -mtune=neoverse-v1")
else ()
if (CMAKE_C_COMPILER_VERSION VERSION_GREATER 10.4 OR CMAKE_C_COMPILER_VERSION VERSION_EQUAL 10.4)
set (KERNEL_DEFINITIONS "${KERNEL_DEFINITIONS} -march=armv8.4-a+sve -mtune=neoverse-v1")
set (KERNEL_DEFINITIONS "${KERNEL_DEFINITIONS} -march=armv8.4-a+sve+bf16 -mtune=neoverse-v1")
else ()
message(FATAL_ERROR "Compiler ${CMAKE_C_COMPILER} ${CMAKE_C_COMPILER_VERSION} does not support Neoverse V1.")
endif()
@@ -425,8 +425,8 @@ endif ()
if (GEMM_GEMV_FORWARD AND NOT ONLY_CBLAS)
set(CCOMMON_OPT "${CCOMMON_OPT} -DGEMM_GEMV_FORWARD")
endif ()
if (GEMM_GEMV_FORWARD_BF16 AND NOT ONLY_CBLAS)
set(CCOMMON_OPT "${CCOMMON_OPT} -DGEMM_GEMV_FORWARD_BF16")
if (SBGEMM_GEMV_FORWARD AND NOT ONLY_CBLAS)
set(CCOMMON_OPT "${CCOMMON_OPT} -DSBGEMM_GEMV_FORWARD")
endif ()
if (SMALL_MATRIX_OPT)
set(CCOMMON_OPT "${CCOMMON_OPT} -DSMALL_MATRIX_OPT")


+ 29
- 1
cmake/utils.cmake View File

@@ -1,3 +1,31 @@
###############################################################################
# Copyright (c) 2025, 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.
###############################################################################

# Functions to help with the OpenBLAS build

# Reads string from getarch into CMake vars. Format of getarch vars is VARNAME=VALUE
@@ -347,7 +375,7 @@ function(GenerateNamedObjects sources_in)
if (NOT no_float_type)
string(SUBSTRING ${float_type} 0 1 float_char)
string(TOLOWER ${float_char} float_char)
if (${float_type} STREQUAL "BFLOAT16")
if (${float_type} STREQUAL "BFLOAT16" AND NOT "${defines_in}" MATCHES "BGEM")
set (float_char "sb")
endif ()
endif ()


+ 6
- 1
common.h View File

@@ -1,5 +1,6 @@
/*********************************************************************/
/* Copyright 2009, 2010 The University of Texas at Austin. */
/* Copyright 2025 The OpenBLAS Project. */
/* All rights reserved. */
/* */
/* Redistribution and use in source and binary forms, with or */
@@ -317,7 +318,11 @@ typedef int blasint;
#elif defined(BFLOAT16)
#define IFLOAT bfloat16
#define XFLOAT IFLOAT
#define FLOAT float
#ifdef BGEMM
#define FLOAT bfloat16
#else
#define FLOAT float
#endif
#define SIZE 2
#define BASE_SHIFT 1
#define ZBASE_SHIFT 2


+ 100
- 0
common_b.h View File

@@ -0,0 +1,100 @@
/***************************************************************************
* Copyright (c) 2025, 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.
* *****************************************************************************/

#ifndef COMMON_B_H
#define COMMON_B_H

#ifndef DYNAMIC_ARCH
#define BGEMV_N_K bgemv_n
#define BGEMV_T_K bgemv_t

#define BSCAL_K bscal_k

#define BGEMM_ONCOPY bgemm_oncopy
#define BGEMM_OTCOPY bgemm_otcopy

#if BGEMM_DEFAULT_UNROLL_M == BGEMM_DEFAULT_UNROLL_N
#define BGEMM_INCOPY bgemm_oncopy
#define BGEMM_ITCOPY bgemm_otcopy
#else
#define BGEMM_INCOPY bgemm_incopy
#define BGEMM_ITCOPY bgemm_itcopy
#endif

#define BGEMM_BETA bgemm_beta
#define BGEMM_KERNEL bgemm_kernel

#else
#define BGEMV_N_K gotoblas->bgemv_n
#define BGEMV_T_K gotoblas->bgemv_t

#define BSCAL_K gotoblas->bscal_k

#define BGEMM_ONCOPY gotoblas->bgemm_oncopy
#define BGEMM_OTCOPY gotoblas->bgemm_otcopy
#define BGEMM_INCOPY gotoblas->bgemm_incopy
#define BGEMM_ITCOPY gotoblas->bgemm_itcopy
#define BGEMM_BETA gotoblas->bgemm_beta
#define BGEMM_KERNEL gotoblas->bgemm_kernel

#endif

#define BGEMM_NN bgemm_nn
#define BGEMM_CN bgemm_tn
#define BGEMM_TN bgemm_tn
#define BGEMM_NC bgemm_nt
#define BGEMM_NT bgemm_nt
#define BGEMM_CC bgemm_tt
#define BGEMM_CT bgemm_tt
#define BGEMM_TC bgemm_tt
#define BGEMM_TT bgemm_tt
#define BGEMM_NR bgemm_nn
#define BGEMM_TR bgemm_tn
#define BGEMM_CR bgemm_tn
#define BGEMM_RN bgemm_nn
#define BGEMM_RT bgemm_nt
#define BGEMM_RC bgemm_nt
#define BGEMM_RR bgemm_nn

#define BGEMM_THREAD_NN bgemm_thread_nn
#define BGEMM_THREAD_CN bgemm_thread_tn
#define BGEMM_THREAD_TN bgemm_thread_tn
#define BGEMM_THREAD_NC bgemm_thread_nt
#define BGEMM_THREAD_NT bgemm_thread_nt
#define BGEMM_THREAD_CC bgemm_thread_tt
#define BGEMM_THREAD_CT bgemm_thread_tt
#define BGEMM_THREAD_TC bgemm_thread_tt
#define BGEMM_THREAD_TT bgemm_thread_tt
#define BGEMM_THREAD_NR bgemm_thread_nn
#define BGEMM_THREAD_TR bgemm_thread_tn
#define BGEMM_THREAD_CR bgemm_thread_tn
#define BGEMM_THREAD_RN bgemm_thread_nn
#define BGEMM_THREAD_RT bgemm_thread_nt
#define BGEMM_THREAD_RC bgemm_thread_nt
#define BGEMM_THREAD_RR bgemm_thread_nn
#endif

+ 6
- 0
common_interface.h View File

@@ -1,5 +1,6 @@
/*********************************************************************/
/* Copyright 2009, 2010 The University of Texas at Austin. */
/* Copyright 2025 The OpenBLAS Project. */
/* All rights reserved. */
/* */
/* Redistribution and use in source and binary forms, with or */
@@ -59,6 +60,7 @@ double BLASFUNC(dsdot) (blasint *, float *, blasint *, float *, blasint *);
double BLASFUNC(ddot) (blasint *, double *, blasint *, double *, blasint *);
xdouble BLASFUNC(qdot) (blasint *, xdouble *, blasint *, xdouble *, blasint *);

void BLASFUNC(bscal) (blasint *, bfloat16 *, bfloat16 *, blasint *);
float BLASFUNC(sbdot) (blasint *, bfloat16 *, blasint *, bfloat16 *, blasint *);
void BLASFUNC(sbstobf16) (blasint *, float *, blasint *, bfloat16 *, blasint *);
void BLASFUNC(sbdtobf16) (blasint *, double *, blasint *, bfloat16 *, blasint *);
@@ -255,6 +257,8 @@ void BLASFUNC(xgeru)(blasint *, blasint *, xdouble *, xdouble *, blasint *,
void BLASFUNC(xgerc)(blasint *, blasint *, xdouble *, xdouble *, blasint *,
xdouble *, blasint *, xdouble *, blasint *);

void BLASFUNC(bgemv)(char *, blasint *, blasint *, bfloat16 *, bfloat16 *, blasint *,
bfloat16 *, blasint *, bfloat16 *, bfloat16 *, blasint *);
void BLASFUNC(sbgemv)(char *, blasint *, blasint *, float *, bfloat16 *, blasint *,
bfloat16 *, blasint *, float *, float *, blasint *);
void BLASFUNC(sgemv)(char *, blasint *, blasint *, float *, float *, blasint *,
@@ -483,6 +487,8 @@ void BLASFUNC(xhbmv)(char *, blasint *, blasint *, xdouble *, xdouble *, blasint

void BLASFUNC(shgemm)(char *, char *, blasint *, blasint *, blasint *, float *,
hfloat16 *, blasint *, hfloat16 *, blasint *, float *, float *, blasint *);
void BLASFUNC(bgemm)(char *, char *, blasint *, blasint *, blasint *, bfloat16 *,
bfloat16 *, blasint *, bfloat16 *, blasint *, bfloat16 *, bfloat16 *, blasint *);
void BLASFUNC(sbgemm)(char *, char *, blasint *, blasint *, blasint *, float *,
bfloat16 *, blasint *, bfloat16 *, blasint *, float *, float *, blasint *);
void BLASFUNC(sgemm)(char *, char *, blasint *, blasint *, blasint *, float *,


+ 4
- 0
common_level1.h View File

@@ -1,4 +1,5 @@
/*********************************************************************/
/* Copyright 2025 The OpenBLAS Project. */
/* Copyright 2009, 2010 The University of Texas at Austin. */
/* All rights reserved. */
/* */
@@ -169,6 +170,9 @@ BLASLONG icmin_k(BLASLONG, float *, BLASLONG);
BLASLONG izmin_k(BLASLONG, double *, BLASLONG);
BLASLONG ixmin_k(BLASLONG, xdouble *, BLASLONG);


int bscal_k(BLASLONG, BLASLONG, BLASLONG, bfloat16,
bfloat16 *, BLASLONG, bfloat16 *, BLASLONG, bfloat16 *, BLASLONG);
int sscal_k(BLASLONG, BLASLONG, BLASLONG, float,
float *, BLASLONG, float *, BLASLONG, float *, BLASLONG);
int dscal_k(BLASLONG, BLASLONG, BLASLONG, double,


+ 6
- 0
common_level2.h View File

@@ -1,4 +1,5 @@
/*********************************************************************/
/* Copyright 2025 The OpenBLAS Project */
/* Copyright 2009, 2010 The University of Texas at Austin. */
/* All rights reserved. */
/* */
@@ -44,6 +45,11 @@
extern "C" {
#endif


int bgemv_n(BLASLONG, BLASLONG, bfloat16, bfloat16 *, BLASLONG, bfloat16 *, BLASLONG, bfloat16, bfloat16 *, BLASLONG);
int bgemv_t(BLASLONG, BLASLONG, bfloat16, bfloat16 *, BLASLONG, bfloat16 *, BLASLONG, bfloat16, bfloat16 *, BLASLONG);
int bgemv_thread_n(BLASLONG, BLASLONG, bfloat16, bfloat16 *, BLASLONG, bfloat16 *, BLASLONG, bfloat16, bfloat16 *, BLASLONG, int);
int bgemv_thread_t(BLASLONG, BLASLONG, bfloat16, bfloat16 *, BLASLONG, bfloat16 *, BLASLONG, bfloat16, bfloat16 *, BLASLONG, int);
int sbgemv_n(BLASLONG, BLASLONG, float, bfloat16 *, BLASLONG, bfloat16 *, BLASLONG, float, float *, BLASLONG);
int sbgemv_t(BLASLONG, BLASLONG, float, bfloat16 *, BLASLONG, bfloat16 *, BLASLONG, float, float *, BLASLONG);
int sbgemv_thread_n(BLASLONG, BLASLONG, float, bfloat16 *, BLASLONG, bfloat16 *, BLASLONG, float, float *, BLASLONG, int);


+ 24
- 0
common_level3.h View File

@@ -52,10 +52,19 @@ void sgemm_direct(BLASLONG M, BLASLONG N, BLASLONG K,
float * B, BLASLONG strideB,
float * R, BLASLONG strideR);

void sgemm_direct_alpha_beta(BLASLONG M, BLASLONG N, BLASLONG K,
float alpha,
float * A, BLASLONG strideA,
float * B, BLASLONG strideB,
float beta,
float * R, BLASLONG strideR);

int sgemm_direct_performant(BLASLONG M, BLASLONG N, BLASLONG K);

int shgemm_beta(BLASLONG, BLASLONG, BLASLONG, float,
hfloat16 *, BLASLONG, hfloat16 *, BLASLONG, float *, BLASLONG);
int bgemm_beta(BLASLONG, BLASLONG, BLASLONG, bfloat16,
bfloat16 *, BLASLONG, bfloat16 *, BLASLONG, bfloat16 *, BLASLONG);
int sbgemm_beta(BLASLONG, BLASLONG, BLASLONG, float,
bfloat16 *, BLASLONG, bfloat16 *, BLASLONG, float *, BLASLONG);
int sgemm_beta(BLASLONG, BLASLONG, BLASLONG, float,
@@ -83,6 +92,10 @@ int shgemm_incopy(BLASLONG m, BLASLONG n, hfloat16 *a, BLASLONG lda, hfloat16 *b
int shgemm_itcopy(BLASLONG m, BLASLONG n, hfloat16 *a, BLASLONG lda, hfloat16 *b);
int shgemm_oncopy(BLASLONG m, BLASLONG n, hfloat16 *a, BLASLONG lda, hfloat16 *b);
int shgemm_otcopy(BLASLONG m, BLASLONG n, hfloat16 *a, BLASLONG lda, hfloat16 *b);
int bgemm_incopy(BLASLONG m, BLASLONG n, bfloat16 *a, BLASLONG lda, bfloat16 *b);
int bgemm_itcopy(BLASLONG m, BLASLONG n, bfloat16 *a, BLASLONG lda, bfloat16 *b);
int bgemm_oncopy(BLASLONG m, BLASLONG n, bfloat16 *a, BLASLONG lda, bfloat16 *b);
int bgemm_otcopy(BLASLONG m, BLASLONG n, bfloat16 *a, BLASLONG lda, bfloat16 *b);
int sbgemm_incopy(BLASLONG m, BLASLONG n, bfloat16 *a, BLASLONG lda, bfloat16 *b);
int sbgemm_itcopy(BLASLONG m, BLASLONG n, bfloat16 *a, BLASLONG lda, bfloat16 *b);
int sbgemm_oncopy(BLASLONG m, BLASLONG n, bfloat16 *a, BLASLONG lda, bfloat16 *b);
@@ -511,6 +524,7 @@ int xher2k_kernel_LN(BLASLONG m, BLASLONG n, BLASLONG k, xdouble alpha_r, xdoubl
int xher2k_kernel_LC(BLASLONG m, BLASLONG n, BLASLONG k, xdouble alpha_r, xdouble alpha_i, xdouble *a, xdouble *b, xdouble *c, BLASLONG ldc, BLASLONG offset, int flag);

int shgemm_kernel(BLASLONG, BLASLONG, BLASLONG, float, hfloat16 *, hfloat16 *, float *, BLASLONG);
int bgemm_kernel(BLASLONG, BLASLONG, BLASLONG, bfloat16, bfloat16 *, bfloat16 *, bfloat16 *, BLASLONG);
int sbgemm_kernel(BLASLONG, BLASLONG, BLASLONG, float, bfloat16 *, bfloat16 *, float *, BLASLONG);
int sgemm_kernel(BLASLONG, BLASLONG, BLASLONG, float, float *, float *, float *, BLASLONG);
int dgemm_kernel(BLASLONG, BLASLONG, BLASLONG, double, double *, double *, double *, BLASLONG);
@@ -668,6 +682,11 @@ int shgemm_nt(blas_arg_t *, BLASLONG *, BLASLONG *, hfloat16 *, hfloat16 *, BLAS
int shgemm_tn(blas_arg_t *, BLASLONG *, BLASLONG *, hfloat16 *, hfloat16 *, BLASLONG);
int shgemm_tt(blas_arg_t *, BLASLONG *, BLASLONG *, hfloat16 *, hfloat16 *, BLASLONG);

int bgemm_nn(blas_arg_t *, BLASLONG *, BLASLONG *, bfloat16 *, bfloat16 *, BLASLONG);
int bgemm_nt(blas_arg_t *, BLASLONG *, BLASLONG *, bfloat16 *, bfloat16 *, BLASLONG);
int bgemm_tn(blas_arg_t *, BLASLONG *, BLASLONG *, bfloat16 *, bfloat16 *, BLASLONG);
int bgemm_tt(blas_arg_t *, BLASLONG *, BLASLONG *, bfloat16 *, bfloat16 *, BLASLONG);

int sbgemm_nn(blas_arg_t *, BLASLONG *, BLASLONG *, bfloat16 *, bfloat16 *, BLASLONG);
int sbgemm_nt(blas_arg_t *, BLASLONG *, BLASLONG *, bfloat16 *, bfloat16 *, BLASLONG);
int sbgemm_tn(blas_arg_t *, BLASLONG *, BLASLONG *, bfloat16 *, bfloat16 *, BLASLONG);
@@ -770,6 +789,11 @@ int shgemm_thread_nt(blas_arg_t *, BLASLONG *, BLASLONG *, hfloat16 *, hfloat16
int shgemm_thread_tn(blas_arg_t *, BLASLONG *, BLASLONG *, hfloat16 *, hfloat16 *, BLASLONG);
int shgemm_thread_tt(blas_arg_t *, BLASLONG *, BLASLONG *, hfloat16 *, hfloat16 *, BLASLONG);

int bgemm_thread_nn(blas_arg_t *, BLASLONG *, BLASLONG *, bfloat16 *, bfloat16 *, BLASLONG);
int bgemm_thread_nt(blas_arg_t *, BLASLONG *, BLASLONG *, bfloat16 *, bfloat16 *, BLASLONG);
int bgemm_thread_tn(blas_arg_t *, BLASLONG *, BLASLONG *, bfloat16 *, bfloat16 *, BLASLONG);
int bgemm_thread_tt(blas_arg_t *, BLASLONG *, BLASLONG *, bfloat16 *, bfloat16 *, BLASLONG);

int sbgemm_thread_nn(blas_arg_t *, BLASLONG *, BLASLONG *, bfloat16 *, bfloat16 *, BLASLONG);
int sbgemm_thread_nt(blas_arg_t *, BLASLONG *, BLASLONG *, bfloat16 *, bfloat16 *, BLASLONG);
int sbgemm_thread_tn(blas_arg_t *, BLASLONG *, BLASLONG *, bfloat16 *, bfloat16 *, BLASLONG);


+ 57
- 5
common_macro.h View File

@@ -1,5 +1,6 @@
/*********************************************************************/
/* Copyright 2009, 2010 The University of Texas at Austin. */
/* Copyright 2025 The OpenBLAS Project. */
/* All rights reserved. */
/* */
/* Redistribution and use in source and binary forms, with or */
@@ -40,6 +41,7 @@
#define COMMON_MACRO

#include "common_sh.h"
#include "common_b.h"
#include "common_sb.h"
#include "common_s.h"
#include "common_d.h"
@@ -702,14 +704,63 @@
#define GEMM_THREAD_RR SHGEMM_THREAD_NN


#elif defined(BFLOAT16)
#elif defined(BFLOAT16) && defined(BGEMM)
#define SCAL_K BSCAL_K

#define GEMV_N BGEMV_N_K
#define GEMV_T BGEMV_T_K

#define GEMM_BETA BGEMM_BETA
#define GEMM_KERNEL_N BGEMM_KERNEL
#define GEMM_KERNEL_L BGEMM_KERNEL
#define GEMM_KERNEL_R BGEMM_KERNEL
#define GEMM_KERNEL_B BGEMM_KERNEL

#define GEMM_NN BGEMM_NN
#define GEMM_CN BGEMM_TN
#define GEMM_TN BGEMM_TN
#define GEMM_NC BGEMM_NT
#define GEMM_NT BGEMM_NT
#define GEMM_CC BGEMM_TT
#define GEMM_CT BGEMM_TT
#define GEMM_TC BGEMM_TT
#define GEMM_TT BGEMM_TT
#define GEMM_NR BGEMM_NN
#define GEMM_TR BGEMM_TN
#define GEMM_CR BGEMM_TN
#define GEMM_RN BGEMM_NN
#define GEMM_RT BGEMM_NT
#define GEMM_RC BGEMM_NT
#define GEMM_RR BGEMM_NN
#define GEMM_ONCOPY BGEMM_ONCOPY
#define GEMM_OTCOPY BGEMM_OTCOPY
#define GEMM_INCOPY BGEMM_INCOPY
#define GEMM_ITCOPY BGEMM_ITCOPY

#define GEMM_THREAD_NN BGEMM_THREAD_NN
#define GEMM_THREAD_CN BGEMM_THREAD_TN
#define GEMM_THREAD_TN BGEMM_THREAD_TN
#define GEMM_THREAD_NC BGEMM_THREAD_NT
#define GEMM_THREAD_NT BGEMM_THREAD_NT
#define GEMM_THREAD_CC BGEMM_THREAD_TT
#define GEMM_THREAD_CT BGEMM_THREAD_TT
#define GEMM_THREAD_TC BGEMM_THREAD_TT
#define GEMM_THREAD_TT BGEMM_THREAD_TT
#define GEMM_THREAD_NR BGEMM_THREAD_NN
#define GEMM_THREAD_TR BGEMM_THREAD_TN
#define GEMM_THREAD_CR BGEMM_THREAD_TN
#define GEMM_THREAD_RN BGEMM_THREAD_NN
#define GEMM_THREAD_RT BGEMM_THREAD_NT
#define GEMM_THREAD_RC BGEMM_THREAD_NT
#define GEMM_THREAD_RR BGEMM_THREAD_NN

#elif defined(BFLOAT16)
#define D_TO_BF16_K SBDTOBF16_K
#define D_BF16_TO_K DBF16TOD_K
#define S_TO_BF16_K SBSTOBF16_K
#define S_BF16_TO_K SBF16TOS_K
#define SBGEMV_N SBGEMV_N_K
#define SBGEMV_T SBGEMV_T_K
#define GEMV_N SBGEMV_N_K
#define GEMV_T SBGEMV_T_K

#define AMAX_K SAMAX_K
#define AMIN_K SAMIN_K
@@ -727,8 +778,6 @@
#define AXPYC_K SAXPYC_K
#define AXPBY_K SAXPBY_K
#define SCAL_K SSCAL_K
#define GEMV_N SGEMV_N
#define GEMV_T SGEMV_T
#define SYMV_U SSYMV_U
#define SYMV_L SSYMV_L
#define GERU_K SGERU_K
@@ -2663,6 +2712,9 @@
|| defined(ARCH_LOONGARCH64) || defined(ARCH_E2K) || defined(ARCH_ALPHA))
extern BLASLONG gemm_offset_a;
extern BLASLONG gemm_offset_b;
extern BLASLONG bgemm_p;
extern BLASLONG bgemm_q;
extern BLASLONG bgemm_r;
extern BLASLONG sbgemm_p;
extern BLASLONG sbgemm_q;
extern BLASLONG sbgemm_r;


+ 48
- 1
common_param.h View File

@@ -1,6 +1,6 @@
/*********************************************************************/
/* Copyright 2009, 2010 The University of Texas at Austin. */
/* Copyright 2023 The OpenBLAS Project. */
/* Copyright 2023, 2025 The OpenBLAS Project. */
/* All rights reserved. */
/* */
/* Redistribution and use in source and binary forms, with or */
@@ -65,6 +65,10 @@ int (*shgemm_otcopy )(BLASLONG, BLASLONG, hfloat16 *, BLASLONG, hfloat16 *);


#if BUILD_BFLOAT16 == 1
int bgemm_p, bgemm_q, bgemm_r;
int bgemm_unroll_m, bgemm_unroll_n, bgemm_unroll_mn;
int bgemm_align_k;

int sbgemm_p, sbgemm_q, sbgemm_r;
int sbgemm_unroll_m, sbgemm_unroll_n, sbgemm_unroll_mn;
int sbgemm_align_k;
@@ -94,10 +98,14 @@ int (*shgemm_otcopy )(BLASLONG, BLASLONG, hfloat16 *, BLASLONG, hfloat16 *);
int (*sbrot_k) (BLASLONG, float *, BLASLONG, float *, BLASLONG, float, float);
int (*sbrotm_k) (BLASLONG, float *, BLASLONG, float *, BLASLONG, float *);

int (*bscal_k) (BLASLONG, BLASLONG, BLASLONG, bfloat16, bfloat16 *, BLASLONG, bfloat16 *, BLASLONG, bfloat16 *, BLASLONG);
int (*sbaxpy_k) (BLASLONG, BLASLONG, BLASLONG, float, float *, BLASLONG, float *, BLASLONG, float *, BLASLONG);
int (*sbscal_k) (BLASLONG, BLASLONG, BLASLONG, float, float *, BLASLONG, float *, BLASLONG, float *, BLASLONG);
int (*sbswap_k) (BLASLONG, BLASLONG, BLASLONG, float, float *, BLASLONG, float *, BLASLONG, float *, BLASLONG);

int (*bgemv_n) (BLASLONG, BLASLONG, bfloat16, bfloat16 *, BLASLONG, bfloat16 *, BLASLONG, bfloat16, bfloat16 *, BLASLONG);
int (*bgemv_t) (BLASLONG, BLASLONG, bfloat16, bfloat16 *, BLASLONG, bfloat16 *, BLASLONG, bfloat16, bfloat16 *, BLASLONG);

int (*sbgemv_n) (BLASLONG, BLASLONG, float, bfloat16 *, BLASLONG, bfloat16 *, BLASLONG, float, float *, BLASLONG);
int (*sbgemv_t) (BLASLONG, BLASLONG, float, bfloat16 *, BLASLONG, bfloat16 *, BLASLONG, float, float *, BLASLONG);
int (*sbger_k) (BLASLONG, BLASLONG, BLASLONG, float, float *, BLASLONG, float *, BLASLONG, float *, BLASLONG, float *);
@@ -105,6 +113,14 @@ int (*shgemm_otcopy )(BLASLONG, BLASLONG, hfloat16 *, BLASLONG, hfloat16 *);
int (*sbsymv_L) (BLASLONG, BLASLONG, float, float *, BLASLONG, float *, BLASLONG, float *, BLASLONG, float *);
int (*sbsymv_U) (BLASLONG, BLASLONG, float, float *, BLASLONG, float *, BLASLONG, float *, BLASLONG, float *);

int (*bgemm_kernel )(BLASLONG, BLASLONG, BLASLONG, bfloat16, bfloat16 *, bfloat16 *, bfloat16 *, BLASLONG);
int (*bgemm_beta )(BLASLONG, BLASLONG, BLASLONG, bfloat16, bfloat16 *, BLASLONG, bfloat16 *, BLASLONG, bfloat16 *, BLASLONG);

int (*bgemm_incopy )(BLASLONG, BLASLONG, bfloat16 *, BLASLONG, bfloat16 *);
int (*bgemm_itcopy )(BLASLONG, BLASLONG, bfloat16 *, BLASLONG, bfloat16 *);
int (*bgemm_oncopy )(BLASLONG, BLASLONG, bfloat16 *, BLASLONG, bfloat16 *);
int (*bgemm_otcopy )(BLASLONG, BLASLONG, bfloat16 *, BLASLONG, bfloat16 *);

int (*sbgemm_kernel )(BLASLONG, BLASLONG, BLASLONG, float, bfloat16 *, bfloat16 *, float *, BLASLONG);
int (*sbgemm_beta )(BLASLONG, BLASLONG, BLASLONG, float, bfloat16 *, BLASLONG, bfloat16 *, BLASLONG, float *, BLASLONG);

@@ -240,6 +256,7 @@ int (*shgemm_otcopy )(BLASLONG, BLASLONG, hfloat16 *, BLASLONG, hfloat16 *);
#endif
#ifdef ARCH_ARM64
void (*sgemm_direct) (BLASLONG, BLASLONG, BLASLONG, float *, BLASLONG , float *, BLASLONG , float * , BLASLONG);
void (*sgemm_direct_alpha_beta) (BLASLONG, BLASLONG, BLASLONG, float, float *, BLASLONG, float *, BLASLONG, float, float * , BLASLONG);
#endif

@@ -1254,6 +1271,13 @@ extern gotoblas_t *gotoblas;
#endif

#if (BUILD_BFLOAT16==1)
#define BGEMM_P gotoblas -> bgemm_p
#define BGEMM_Q gotoblas -> bgemm_q
#define BGEMM_R gotoblas -> bgemm_r
#define BGEMM_UNROLL_M gotoblas -> bgemm_unroll_m
#define BGEMM_UNROLL_N gotoblas -> bgemm_unroll_n
#define BGEMM_UNROLL_MN gotoblas -> bgemm_unroll_mn

#define SBGEMM_P gotoblas -> sbgemm_p
#define SBGEMM_Q gotoblas -> sbgemm_q
#define SBGEMM_R gotoblas -> sbgemm_r
@@ -1395,6 +1419,17 @@ extern gotoblas_t *gotoblas;
#endif

#if (BUILD_BFLOAT16 == 1)
#define BGEMM_P BGEMM_DEFAULT_P
#define BGEMM_Q BGEMM_DEFAULT_Q
#define BGEMM_R BGEMM_DEFAULT_R
#define BGEMM_UNROLL_M BGEMM_DEFAULT_UNROLL_M
#define BGEMM_UNROLL_N BGEMM_DEFAULT_UNROLL_N
#ifdef BGEMM_DEFAULT_UNROLL_MN
#define BGEMM_UNROLL_MN BGEMM_DEFAULT_UNROLL_MN
#else
#define BGEMM_UNROLL_MN MAX((BGEMM_UNROLL_M), (BGEMM_UNROLL_N))
#endif

#define SBGEMM_P SBGEMM_DEFAULT_P
#define SBGEMM_Q SBGEMM_DEFAULT_Q
#define SBGEMM_R SBGEMM_DEFAULT_R
@@ -1555,6 +1590,18 @@ extern gotoblas_t *gotoblas;
#define GEMM_DEFAULT_R SHGEMM_DEFAULT_R
#define GEMM_DEFAULT_UNROLL_M SHGEMM_DEFAULT_UNROLL_M
#define GEMM_DEFAULT_UNROLL_N SHGEMM_DEFAULT_UNROLL_N
#elif defined(BFLOAT16) && defined(BGEMM)
#define GEMM_P BGEMM_P
#define GEMM_Q BGEMM_Q
#define GEMM_R BGEMM_R
#define GEMM_UNROLL_M BGEMM_UNROLL_M
#define GEMM_UNROLL_N BGEMM_UNROLL_N
#define GEMM_UNROLL_MN BGEMM_UNROLL_MN
#define GEMM_DEFAULT_P BGEMM_DEFAULT_P
#define GEMM_DEFAULT_Q BGEMM_DEFAULT_Q
#define GEMM_DEFAULT_R BGEMM_DEFAULT_R
#define GEMM_DEFAULT_UNROLL_M BGEMM_DEFAULT_UNROLL_M
#define GEMM_DEFAULT_UNROLL_N BGEMM_DEFAULT_UNROLL_N
#elif defined(BFLOAT16)
#define GEMM_P SBGEMM_P
#define GEMM_Q SBGEMM_Q


+ 2
- 0
common_s.h View File

@@ -49,6 +49,7 @@

#define SGEMM_DIRECT_PERFORMANT sgemm_direct_performant
#define SGEMM_DIRECT sgemm_direct
#define SGEMM_DIRECT_ALPHA_BETA sgemm_direct_alpha_beta

#define SGEMM_ONCOPY sgemm_oncopy
#define SGEMM_OTCOPY sgemm_otcopy
@@ -218,6 +219,7 @@
#elif ARCH_ARM64
#define SGEMM_DIRECT_PERFORMANT sgemm_direct_performant
#define SGEMM_DIRECT gotoblas -> sgemm_direct
#define SGEMM_DIRECT_ALPHA_BETA gotoblas -> sgemm_direct_alpha_beta
#endif

#define SGEMM_ONCOPY gotoblas -> sgemm_oncopy


+ 4
- 0
cpuid.S View File

@@ -66,5 +66,9 @@ _cpuid:

#endif
#if defined(__ELF__) && defined(__linux__)
#if defined(__arm__)
.section .note.GNU-stack,"",%progbits
#else
.section .note.GNU-stack,"",@progbits
#endif
#endif

+ 4
- 0
cpuid_power.c View File

@@ -131,6 +131,7 @@ int detect(void){
if (!strncasecmp(p, "POWER8", 6)) return CPUTYPE_POWER8;
if (!strncasecmp(p, "POWER9", 6)) return CPUTYPE_POWER9;
if (!strncasecmp(p, "POWER10", 7)) return CPUTYPE_POWER10;
if (!strncasecmp(p, "POWER11", 7)) return CPUTYPE_POWER10;
if (!strncasecmp(p, "Cell", 4)) return CPUTYPE_CELL;
if (!strncasecmp(p, "7447", 4)) return CPUTYPE_PPCG4;

@@ -171,6 +172,9 @@ int detect(void){
int id;
__asm __volatile("mfpvr %0" : "=r"(id));
switch ( id >> 16 ) {
case 0x82: // POWER11
return CPUTYPE_POWER10;
break;
case 0x80: // POWER10
return CPUTYPE_POWER10;
break;


+ 3
- 1
cpuid_x86.c View File

@@ -1567,6 +1567,7 @@ int get_cpuname(void){
case 10:
case 15:
case 14: // Alder Lake N
case 13: // Lunar Lake
if(support_avx2())
return CPUTYPE_HASWELL;
if(support_avx())
@@ -2412,7 +2413,8 @@ int get_coretype(void){
case 7: // Raptor Lake
case 10:
case 15:
case 14: // Alder Lake N
case 14: // Alder Lake N
case 13: // Lunar Lake
#ifndef NO_AVX2
if(support_avx2())
return CORE_HASWELL;


+ 10
- 2
docs/install.md View File

@@ -623,14 +623,22 @@ Note: using `TARGET=CORTEXA57` in place of `ARMV8` will pick up better
optimized routines. Implementations for the `CORTEXA57` target are compatible
with all other `ARMV8` targets.

Note: for NDK 23b, something as simple as:
Note: for NDK 23b and later, something as simple as:
```bash
export PATH=/opt/android-ndk-r23b/toolchains/llvm/prebuilt/linux-x86_64/bin/:$PATH
make HOSTCC=gcc CC=/opt/android-ndk-r23b/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android31-clang ONLY_CBLAS=1 TARGET=ARMV8
make HOSTCC=gcc CC=/opt/android-ndk-r23b/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android31-clang ONLY_CBLAS=1 TARGET=ARMV8 RANLIB=echo
```
appears to be sufficient on Linux. On OSX, setting AR to the ar provided in the
"bin" path of the NDK (probably `llvm-ar`) is also necessary.

If you prefer building with CMake, running
```bash
cmake -DANDROID_ABI=arm64-v8a -DTARGET=ARMV8 -DCMAKE_TOOLCHAIN_FILE=/opt/android-ndk-r27/build/cmake/android.toolchain.cmake -DNOFORTRAN=1 -DANDROID_PLATFORM=android-23 ..
cmake --build .
```
in your build directory should work (be sure to adjust the toolchain_file argument according to where you installed the NDK, and the ANDROID_PLATFORM
according to the minimum version of Android you want to support. (If you leave out the ANDROID_PLATFORM parameter, the build will fail with an error
message about a missing declaration or missing header file complex.h)

??? note "Alternative build script for 3 architectures"



+ 35
- 0
driver/level2/Makefile View File

@@ -1,3 +1,31 @@
###############################################################################
# Copyright (c) 2025 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.
###############################################################################

TOPDIR = ../..
include ../../Makefile.system

@@ -423,6 +451,9 @@ XBLASOBJS += \
xtbmv_thread_CLU.$(SUFFIX) xtbmv_thread_CLN.$(SUFFIX)

ifeq ($(BUILD_BFLOAT16),1)
BBLASOBJS += \
bgemv_thread_n$(TSUFFIX).$(SUFFIX) \
bgemv_thread_t$(TSUFFIX).$(SUFFIX)
SBBLASOBJS += \
sbgemv_thread_n$(TSUFFIX).$(SUFFIX) \
sbgemv_thread_t$(TSUFFIX).$(SUFFIX)
@@ -3707,6 +3738,10 @@ xtrsv_CUN.$(SUFFIX) xtrsv_CUN.$(PSUFFIX) : ztrsv_L.c ../../param.h
$(CC) -c $(CFLAGS) -DXDOUBLE -DCOMPLEX -DTRANSA=4 -UUNIT $< -o $(@F)

ifeq ($(BUILD_BFLOAT16),1)
bgemv_thread_n.$(SUFFIX) bgemv_thread_n.$(PSUFFIX) : sbgemv_thread.c ../../common.h
$(CC) -c $(CFLAGS) -DBGEMM -UCOMPLEX -UDOUBLE -UTRANSA -UCONJ -UXCONJ $< -o $(@F)
bgemv_thread_t.$(SUFFIX) bgemv_thread_t.$(PSUFFIX) : sbgemv_thread.c ../../common.h
$(CC) -c $(CFLAGS) -DBGEMM -UCOMPLEX -UDOUBLE -DTRANSA -UCONJ -UXCONJ $< -o $(@F)
sbgemv_thread_n.$(SUFFIX) sbgemv_thread_n.$(PSUFFIX) : sbgemv_thread.c ../../common.h
$(CC) -c $(CFLAGS) -UCOMPLEX -UDOUBLE -UTRANSA -UCONJ -UXCONJ $< -o $(@F)
sbgemv_thread_t.$(SUFFIX) sbgemv_thread_t.$(PSUFFIX) : sbgemv_thread.c ../../common.h


+ 10
- 9
driver/level2/sbgemv_thread.c View File

@@ -1,4 +1,5 @@
/*********************************************************************/
/* Copyright 2025 The OpenBLAS Project. */
/* Copyright 2009, 2010 The University of Texas at Austin. */
/* All rights reserved. */
/* */
@@ -41,21 +42,21 @@
#include "common.h"

#ifndef TRANSA
#define SBGEMV SBGEMV_N
#define GEMV GEMV_N
#else
#define SBGEMV SBGEMV_T
#define GEMV GEMV_T
#endif

static int sbgemv_kernel(blas_arg_t *args, BLASLONG *range_m, BLASLONG *range_n, FLOAT *dummy1, FLOAT *dummy2, BLASLONG dummy3){

bfloat16 *a, *x;
float *y;
IFLOAT *a, *x;
FLOAT *y;
BLASLONG lda, incx, incy;
BLASLONG m_from, m_to, n_from, n_to;

a = (bfloat16 *)args->a;
x = (bfloat16 *)args->b;
y = (float *)args->c;
a = (IFLOAT *)args->a;
x = (IFLOAT *)args->b;
y = (FLOAT *)args->c;

lda = args->lda;
incx = args->ldb;
@@ -77,12 +78,12 @@ static int sbgemv_kernel(blas_arg_t *args, BLASLONG *range_m, BLASLONG *range_n,
y += n_from * incy;
#endif

SBGEMV(m_to - m_from, n_to - n_from, *((FLOAT *)(args->alpha)), a, lda, x, incx, *((FLOAT *)(args->beta)), y, incy);
GEMV(m_to - m_from, n_to - n_from, *((FLOAT *)(args->alpha)), a, lda, x, incx, *((FLOAT *)(args->beta)), y, incy);

return 0;
}

int CNAME(BLASLONG m, BLASLONG n, float alpha, bfloat16 *a, BLASLONG lda, bfloat16 *x, BLASLONG incx, float beta, float *y, BLASLONG incy, int threads)
int CNAME(BLASLONG m, BLASLONG n, FLOAT alpha, IFLOAT *a, BLASLONG lda, IFLOAT *x, BLASLONG incx, FLOAT beta, FLOAT *y, BLASLONG incy, int threads)
{
blas_arg_t args;
blas_queue_t queue[MAX_CPU_NUMBER];


+ 55
- 0
driver/level3/Makefile View File

@@ -1,3 +1,32 @@
###############################################################################
# Copyright (c) 2025, 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.
###############################################################################

TOPDIR = ../..
include ../../Makefile.system

@@ -20,6 +49,7 @@ USE_GEMM3M = 1
endif

ifeq ($(BUILD_BFLOAT16),1)
BBLASOBJS += bgemm_nn.$(SUFFIX) bgemm_nt.$(SUFFIX) bgemm_tn.$(SUFFIX) bgemm_tt.$(SUFFIX)
SBBLASOBJS += sbgemm_nn.$(SUFFIX) sbgemm_nt.$(SUFFIX) sbgemm_tn.$(SUFFIX) sbgemm_tt.$(SUFFIX)
endif

@@ -212,6 +242,7 @@ COMMONOBJS += syrk_thread.$(SUFFIX)

ifneq ($(USE_SIMPLE_THREADED_LEVEL3), 1)
ifeq ($(BUILD_BFLOAT16),1)
BBLASOBJS += bgemm_thread_nn.$(SUFFIX) bgemm_thread_nt.$(SUFFIX) bgemm_thread_tn.$(SUFFIX) bgemm_thread_tt.$(SUFFIX)
SBBLASOBJS += sbgemm_thread_nn.$(SUFFIX) sbgemm_thread_nt.$(SUFFIX) sbgemm_thread_tn.$(SUFFIX) sbgemm_thread_tt.$(SUFFIX)
endif
ifeq ($(BUILD_HFLOAT16),1)
@@ -350,6 +381,18 @@ endif

all ::

bgemm_nn.$(SUFFIX) : gemm.c level3.c ../../param.h
$(CC) $(CFLAGS) $(BLOCKS) -c -DBFLOAT16 -DBGEMM -UDOUBLE -UCOMPLEX -DNN $< -o $(@F)

bgemm_nt.$(SUFFIX) : gemm.c level3.c ../../param.h
$(CC) $(CFLAGS) $(BLOCKS) -c -DBFLOAT16 -DBGEMM -UDOUBLE -UCOMPLEX -DNT $< -o $(@F)

bgemm_tn.$(SUFFIX) : gemm.c level3.c ../../param.h
$(CC) $(CFLAGS) $(BLOCKS) -c -DBFLOAT16 -DBGEMM -UDOUBLE -UCOMPLEX -DTN $< -o $(@F)

bgemm_tt.$(SUFFIX) : gemm.c level3.c ../../param.h
$(CC) $(CFLAGS) $(BLOCKS) -c -DBFLOAT16 -DBGEMM -UDOUBLE -UCOMPLEX -DTT $< -o $(@F)

sbgemm_nn.$(SUFFIX) : gemm.c level3.c ../../param.h
$(CC) $(CFLAGS) $(BLOCKS) -c -DBFLOAT16 -UDOUBLE -UCOMPLEX -DNN $< -o $(@F)

@@ -569,6 +612,18 @@ gemm_thread_variable.$(SUFFIX) : gemm_thread_variable.c ../../common.h
beta_thread.$(SUFFIX) : beta_thread.c ../../common.h
$(CC) -c $(CFLAGS) $< -o $(@F)

bgemm_thread_nn.$(SUFFIX) : gemm.c level3_thread.c ../../param.h
$(CC) $(CFLAGS) $(BLOCKS) -c -DTHREADED_LEVEL3 -DBFLOAT16 -DBGEMM -UDOUBLE -UCOMPLEX -DNN $< -o $(@F)

bgemm_thread_nt.$(SUFFIX) : gemm.c level3_thread.c ../../param.h
$(CC) $(CFLAGS) $(BLOCKS) -c -DTHREADED_LEVEL3 -DBFLOAT16 -DBGEMM -UDOUBLE -UCOMPLEX -DNT $< -o $(@F)

bgemm_thread_tn.$(SUFFIX) : gemm.c level3_thread.c ../../param.h
$(CC) $(CFLAGS) $(BLOCKS) -c -DTHREADED_LEVEL3 -DBFLOAT16 -DBGEMM -UDOUBLE -UCOMPLEX -DTN $< -o $(@F)

bgemm_thread_tt.$(SUFFIX) : gemm.c level3_thread.c ../../param.h
$(CC) $(CFLAGS) $(BLOCKS) -c -DTHREADED_LEVEL3 -DBFLOAT16 -DBGEMM -UDOUBLE -UCOMPLEX -DTT $< -o $(@F)

sbgemm_thread_nn.$(SUFFIX) : gemm.c level3_thread.c ../../param.h
$(CC) $(CFLAGS) $(BLOCKS) -c -DTHREADED_LEVEL3 -DBFLOAT16 -UDOUBLE -UCOMPLEX -DNN $< -o $(@F)



+ 19
- 6
driver/level3/level3.c View File

@@ -1,5 +1,6 @@
/*********************************************************************/
/* Copyright 2009, 2010 The University of Texas at Austin. */
/* Copyright 2025 The OpenBLAS Project. */
/* All rights reserved. */
/* */
/* Redistribution and use in source and binary forms, with or */
@@ -169,6 +170,22 @@
#define STOP_RPCC(COUNTER)
#endif

#if defined(BUILD_BFLOAT16)
#if defined(DYNAMIC_ARCH)
#if defined(BGEMM)
#define BFLOAT16_ALIGN_K gotoblas->bgemm_align_k
#else
#define BFLOAT16_ALIGN_K gotoblas->sbgemm_align_k
#endif
#else
#if defined(BGEMM)
#define BFLOAT16_ALIGN_K BGEMM_ALIGN_K
#else
#define BFLOAT16_ALIGN_K SBGEMM_ALIGN_K
#endif
#endif
#endif

int CNAME(blas_arg_t *args, BLASLONG *range_m, BLASLONG *range_n,
XFLOAT *sa, XFLOAT *sb, BLASLONG dummy){
BLASLONG k, lda, ldb, ldc;
@@ -305,12 +322,8 @@ int CNAME(blas_arg_t *args, BLASLONG *range_m, BLASLONG *range_n,
}

BLASLONG pad_min_l = min_l;
#if defined(HALF)
#if defined(DYNAMIC_ARCH)
pad_min_l = (min_l + gotoblas->sbgemm_align_k - 1) & ~(gotoblas->sbgemm_align_k-1);
#else
pad_min_l = (min_l + SBGEMM_ALIGN_K - 1) & ~(SBGEMM_ALIGN_K - 1);;
#endif
#if defined(BFLOAT16)
pad_min_l = (min_l + BFLOAT16_ALIGN_K - 1) & ~(BFLOAT16_ALIGN_K - 1);
#endif

/* First, we have to move data A to L2 cache */


+ 19
- 7
driver/level3/level3_thread.c View File

@@ -1,6 +1,6 @@
/*********************************************************************/
/* Copyright 2009, 2010 The University of Texas at Austin. */
/* Copyright 2023 The OpenBLAS Project. */
/* Copyright 2023, 2025 The OpenBLAS Project. */
/* All rights reserved. */
/* */
/* Redistribution and use in source and binary forms, with or */
@@ -216,6 +216,22 @@ typedef struct {
#define STOP_RPCC(COUNTER)
#endif

#if defined(BUILD_BFLOAT16)
#if defined(DYNAMIC_ARCH)
#if defined(BGEMM)
#define BFLOAT16_ALIGN_K gotoblas->bgemm_align_k
#else
#define BFLOAT16_ALIGN_K gotoblas->sbgemm_align_k
#endif
#else
#if defined(BGEMM)
#define BFLOAT16_ALIGN_K BGEMM_ALIGN_K
#else
#define BFLOAT16_ALIGN_K SBGEMM_ALIGN_K
#endif
#endif
#endif

static int inner_thread(blas_arg_t *args, BLASLONG *range_m, BLASLONG *range_n, IFLOAT *sa, IFLOAT *sb, BLASLONG mypos){

IFLOAT *buffer[DIVIDE_RATE];
@@ -324,12 +340,8 @@ static int inner_thread(blas_arg_t *args, BLASLONG *range_m, BLASLONG *range_n,
BLASLONG pad_min_l = min_l;

#if defined(HALF)
#if defined(DYNAMIC_ARCH)
pad_min_l = (min_l + gotoblas->sbgemm_align_k - 1) & ~(gotoblas->sbgemm_align_k-1);
#else
pad_min_l = (min_l + SBGEMM_ALIGN_K - 1) & ~(SBGEMM_ALIGN_K - 1);;
#endif
#if defined(BFLOAT16)
pad_min_l = (min_l + BFLOAT16_ALIGN_K - 1) & ~(BFLOAT16_ALIGN_K - 1);
#endif

/* Determine step size in m


+ 10
- 0
driver/others/dynamic_power.c View File

@@ -70,6 +70,9 @@ static int cpuid(void)
#endif
#ifdef POWER_10
else if (arch >= POWER_10) return CPU_POWER10;
#endif
#ifdef POWER_11
else if (arch >= POWER_11) return CPU_POWER10;
#endif
return CPU_UNKNOWN;
}
@@ -173,6 +176,13 @@ static struct {
.cpu_type = CPU_POWER10,
},

{ /* Power11 */
.pvr_mask = 0xffff0000,
.pvr_value = 0x00820000,
.cpu_name = "POWER11 (raw)",
.cpu_type = CPU_POWER10,
},

{ /* End of table, pvr_mask and pvr_value must be zero */
.pvr_mask = 0x0,
.pvr_value = 0x0,


+ 17
- 0
driver/others/parameter.c View File

@@ -72,6 +72,11 @@ BLASLONG shgemm_p = DEFAULT_GEMM_P;
#else
BLASLONG shgemm_p = SHGEMM_P;
#endif
#if BGEMM_P == bgemm_p
BLASLONG bgemm_p = DEFAULT_GEMM_P;
#else
BLASLONG bgemm_p = BGEMM_P;
#endif
#if SGEMM_P == sgemm_p
BLASLONG sgemm_p = DEFAULT_GEMM_P;
#else
@@ -103,6 +108,11 @@ BLASLONG shgemm_q = DEFAULT_GEMM_Q;
#else
BLASLONG shgemm_q = SHGEMM_Q;
#endif
#if BGEMM_Q == bgemm_q
BLASLONG bgemm_q = DEFAULT_GEMM_Q;
#else
BLASLONG bgemm_q = BGEMM_Q;
#endif
#if SGEMM_Q == sgemm_q
BLASLONG sgemm_q = DEFAULT_GEMM_Q;
#else
@@ -134,6 +144,11 @@ BLASLONG shgemm_r = DEFAULT_GEMM_R;
#else
BLASLONG shgemm_r = SHGEMM_R;
#endif
#if BGEMM_R == bgemm_r
BLASLONG bgemm_r = DEFAULT_GEMM_R;
#else
BLASLONG bgemm_r = BGEMM_R;
#endif
#if SGEMM_R == sgemm_r
BLASLONG sgemm_r = DEFAULT_GEMM_R;
#else
@@ -541,6 +556,7 @@ void blas_set_parameter(void){

#ifdef BUILD_BFLOAT16
sbgemm_r = (((BUFFER_SIZE - ((SBGEMM_P * SBGEMM_Q * 4 + GEMM_OFFSET_A + GEMM_ALIGN) & ~GEMM_ALIGN)) / (SBGEMM_Q * 4)) - 15) & ~15;
bgemm_r = (((BUFFER_SIZE - ((BGEMM_P * BGEMM_Q * 4 + GEMM_OFFSET_A + GEMM_ALIGN) & ~GEMM_ALIGN)) / (BGEMM_Q * 4)) - 15) & ~15;
#endif
#ifdef BUILD_HFLOAT16
shgemm_r = (((BUFFER_SIZE - ((SHGEMM_P * SHGEMM_Q * 4 + GEMM_OFFSET_A + GEMM_ALIGN) & ~GEMM_ALIGN)) / (SHGEMM_Q * 4)) - 15) & ~15;
@@ -653,6 +669,7 @@ void blas_set_parameter(void){

#ifdef BUILD_BFLOAT16
sbgemm_r = (((BUFFER_SIZE - ((SBGEMM_P * SBGEMM_Q * 4 + GEMM_OFFSET_A + GEMM_ALIGN) & ~GEMM_ALIGN)) / (SBGEMM_Q * 4)) - 15) & ~15;
bgemm_r = (((BUFFER_SIZE - ((BGEMM_P * BGEMM_Q * 4 + GEMM_OFFSET_A + GEMM_ALIGN) & ~GEMM_ALIGN)) / (BGEMM_Q * 4)) - 15) & ~15;
#endif
#ifdef BUILD_HFLOAT16
shgemm_r = (((BUFFER_SIZE - ((SHGEMM_P * SHGEMM_Q * 4 + GEMM_OFFSET_A + GEMM_ALIGN) & ~GEMM_ALIGN)) / (SHGEMM_Q * 4)) - 15) & ~15;


+ 29
- 1
exports/gensymbol View File

@@ -1,5 +1,33 @@
#!/bin/sh

###############################################################################
# Copyright (c) 2025, 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.
###############################################################################

# Changelog
# 2017/09/03 staticfloat
# Added zsymv and csymv into @lapackobjs2 so they are properly renamed
@@ -51,7 +79,7 @@ blasobjsz="
zgeadd dzsum zgemmt zgemmtr"

blasobjs="lsame xerbla"
bfblasobjs="sbgemm sbgemmt sbgemmtr sbgemv sbdot sbstobf16 sbdtobf16 sbf16tos dbf16tod"
bfblasobjs="bgemm bgemv sbgemm sbgemmt sbgemmtr sbgemv sbdot sbstobf16 sbdtobf16 sbf16tos dbf16tod"
hfblasobjs="shgemm"
cblasobjsc="
cblas_caxpy cblas_ccopy cblas_cdotc cblas_cdotu cblas_cgbmv cblas_cgemm cblas_cgemv


+ 29
- 1
exports/gensymbol.pl View File

@@ -1,5 +1,33 @@
#!/usr/bin/env perl

###############################################################################
# Copyright (c) 2025, 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.
###############################################################################

# Changelog
# 2017/09/03 staticfloat
# Added zsymv and csymv into @lapackobjs2 so they are properly renamed
@@ -51,7 +79,7 @@
zgeadd, dzsum, zgemmt,zgemmtr);

@blasobjs = (lsame, xerbla);
@bfblasobjs = (sbgemm, sbgemmt, sbgemmtr, sbgemv, sbdot, sbstobf16, sbdtobf16, sbf16tos, dbf16tod);
@bfblasobjs = (bgemm, bgemv, sbgemm, sbgemmt, sbgemmtr, sbgemv, sbdot, sbstobf16, sbdtobf16, sbf16tos, dbf16tod);
@hfblasobjs = (shgemm);
@cblasobjsc = (
cblas_caxpy, cblas_ccopy, cblas_cdotc, cblas_cdotu, cblas_cgbmv, cblas_cgemm, cblas_cgemv,


+ 3
- 3
getarch.c View File

@@ -1,5 +1,5 @@
/*****************************************************************************
Copyright (c) 2011-2014, The OpenBLAS Project
Copyright (c) 2011-2014, 2025 The OpenBLAS Project
All rights reserved.

Redistribution and use in source and binary forms, with or without
@@ -836,7 +836,7 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define CORENAME "POWER9"
#endif

#if defined(FORCE_POWER10)
#if defined(FORCE_POWER10) || (FORCE_POWER11)
#define FORCE
#define ARCHITECTURE "POWER"
#define SUBARCHITECTURE "POWER10"
@@ -1476,7 +1476,7 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"-DL2_SIZE=1048576 -DL2_LINESIZE=64 -DL2_ASSOCIATIVE=16 " \
"-DDTB_DEFAULT_ENTRIES=64 -DDTB_SIZE=4096 " \
"-DHAVE_VFPV4 -DHAVE_VFPV3 -DHAVE_VFP -DHAVE_NEON -DHAVE_SVE -DARMV8 " \
"-march=armv8.4-a+sve -mtune=neoverse-v1"
"-march=armv8.4-a+sve+bf16 -mtune=neoverse-v1"
#define LIBNAME "neoversev1"
#define CORENAME "NEOVERSEV1"
#endif


+ 32
- 0
getarch_2nd.c View File

@@ -1,3 +1,31 @@
/***************************************************************************
* Copyright (c) 2025, 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 <stdio.h>
#ifndef BUILD_KERNEL
#include "config.h"
@@ -17,6 +45,10 @@ typedef unsigned long BLASULONG;
int main(int argc, char **argv) {

if ( (argc <= 1) || ((argc >= 2) && (*argv[1] == '0'))) {
printf("BGEMM_UNROLL_M=%d\n", BGEMM_DEFAULT_UNROLL_M);
printf("BGEMM_UNROLL_N=%d\n", BGEMM_DEFAULT_UNROLL_N);
printf("BGEMM_UNROLL_M=%d\n", BGEMM_DEFAULT_UNROLL_M);
printf("BGEMM_UNROLL_N=%d\n", BGEMM_DEFAULT_UNROLL_N);
printf("SBGEMM_UNROLL_M=%d\n", SBGEMM_DEFAULT_UNROLL_M);
printf("SBGEMM_UNROLL_N=%d\n", SBGEMM_DEFAULT_UNROLL_N);
printf("SHGEMM_UNROLL_M=%d\n", SHGEMM_DEFAULT_UNROLL_M);


+ 30
- 0
interface/CMakeLists.txt View File

@@ -1,3 +1,30 @@
###############################################################################
# Copyright (c) 2025, 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_directories(${PROJECT_SOURCE_DIR})
include_directories(${PROJECT_BINARY_DIR})
@@ -123,10 +150,13 @@ endif ()
GenerateNamedObjects("imax.c" "USE_MIN" "i*min" ${CBLAS_FLAG})

if (BUILD_BFLOAT16)
GenerateNamedObjects("scal.c" "BGEMM" "bscal" ${CBLAS_FLAG} "" "" true "BFLOAT16")
GenerateNamedObjects("bf16dot.c" "" "sbdot" ${CBLAS_FLAG} "" "" true "BFLOAT16")
GenerateNamedObjects("gemm.c" "BGEMM" "bgemm" ${CBLAS_FLAG} "" "" true "BFLOAT16")
GenerateNamedObjects("gemm.c" "" "sbgemm" ${CBLAS_FLAG} "" "" true "BFLOAT16")
GenerateNamedObjects("sbgemmt.c" "" "sbgemmt" ${CBLAS_FLAG} "" "" true "BFLOAT16")
GenerateNamedObjects("sbgemmt.c" "RNAME" "sbgemmtr" ${CBLAS_FLAG} "" "" true "BFLOAT16")
GenerateNamedObjects("sbgemv.c" "BGEMM" "bgemv" ${CBLAS_FLAG} "" "" true "BFLOAT16")
GenerateNamedObjects("sbgemv.c" "" "sbgemv" ${CBLAS_FLAG} "" "" true "BFLOAT16")
GenerateNamedObjects("tobf16.c" "SINGLE_PREC" "sbstobf16" ${CBLAS_FLAG} "" "" true "BFLOAT16")
GenerateNamedObjects("tobf16.c" "DOUBLE_PREC" "sbdtobf16" ${CBLAS_FLAG} "" "" true "BFLOAT16")


+ 53
- 3
interface/Makefile View File

@@ -1,3 +1,31 @@
###############################################################################
# Copyright (c) 2025, 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.
###############################################################################

TOPDIR = ..
include $(TOPDIR)/Makefile.system

@@ -47,6 +75,9 @@ SBLAS3OBJS = \
sgeadd.$(SUFFIX) sgemmt.$(SUFFIX) sgemmtr.$(SUFFIX)

ifeq ($(BUILD_BFLOAT16),1)
BBLAS3OBJS = bgemm.$(SUFFIX)
BBLAS2OBJS = bgemv.$(SUFFIX)
BBLAS1OBJS = bscal.$(SUFFIX)
SBBLAS1OBJS = sbdot.$(SUFFIX)
SBBLAS2OBJS = sbgemv.$(SUFFIX)
SBBLAS3OBJS = sbgemm.$(SUFFIX) sbgemmt.$(SUFFIX) sbgemmtr.$(SUFFIX)
@@ -289,6 +320,9 @@ CSBLAS3OBJS = \
cblas_sgeadd.$(SUFFIX) cblas_sgemmt.$(SUFFIX) cblas_sgemmtr.$(SUFFIX) cblas_sgemm_batch.$(SUFFIX)

ifeq ($(BUILD_BFLOAT16),1)
CBBLAS3OBJS = cblas_bgemm.$(SUFFIX)
CBBLAS2OBJS = cblas_bgemv.$(SUFFIX)
CBBLAS1OBJS = cblas_bscal.$(SUFFIX)
CSBBLAS1OBJS = cblas_sbdot.$(SUFFIX)
CSBBLAS2OBJS = cblas_sbgemv.$(SUFFIX)
CSBBLAS3OBJS = cblas_sbgemm.$(SUFFIX) cblas_sbgemmt.$(SUFFIX) cblas_sbgemmtr.$(SUFFIX) cblas_sbgemm_batch.$(SUFFIX)
@@ -393,6 +427,9 @@ override CFLAGS += -I.
SBLAS1OBJS += $(CSBLAS1OBJS)
SBLAS2OBJS += $(CSBLAS2OBJS)
SBLAS3OBJS += $(CSBLAS3OBJS)
BBLAS3OBJS += $(CBBLAS3OBJS)
BBLAS2OBJS += $(CBBLAS2OBJS)
BBLAS1OBJS += $(CBBLAS1OBJS)
SBBLAS1OBJS += $(CSBBLAS1OBJS)
SBBLAS2OBJS += $(CSBBLAS2OBJS)
SBBLAS3OBJS += $(CSBBLAS3OBJS)
@@ -412,6 +449,7 @@ SBEXTOBJS += $(CSBEXTOBJS)
CBAUXOBJS += $(CXERBLAOBJ)
endif

BBLASOBJS = $(BBLAS3OBJS) $(BBLAS2OBJS) $(BBLAS1OBJS)
SBLASOBJS = $(SBLAS1OBJS) $(SBLAS2OBJS) $(SBLAS3OBJS)
SBBLASOBJS = $(SBBLAS1OBJS) $(SBBLAS2OBJS) $(SBBLAS3OBJS)
SHBLASOBJS = $(SHBLAS3OBJS)
@@ -522,7 +560,7 @@ ifneq ($(BUILD_COMPLEX16),1)
ZBLASOBJS=
endif

FUNCOBJS = $(SBEXTOBJS) $(CXERBLAOBJS) $(SBBLASOBJS) $(SBLASOBJS) $(DBLASOBJS) $(CBLASOBJS) $(ZBLASOBJS) $(SHBLASOBJS)
FUNCOBJS = $(SBEXTOBJS) $(CXERBLAOBJS) $(BBLASOBJS) $(SBBLASOBJS) $(SBLASOBJS) $(DBLASOBJS) $(CBLASOBJS) $(ZBLASOBJS) $(SHBLASOBJS)

ifeq ($(EXPRECISION), 1)
FUNCOBJS += $(QBLASOBJS) $(XBLASOBJS)
@@ -557,10 +595,10 @@ clean ::
level1 : $(SBEXTOBJS) $(SBBLAS1OBJS) $(SBLAS1OBJS) $(DBLAS1OBJS) $(QBLAS1OBJS) $(CBLAS1OBJS) $(ZBLAS1OBJS) $(XBLAS1OBJS)
$(AR) $(ARFLAGS) -ru $(TOPDIR)/$(LIBNAME) $^

level2 : $(SBBLAS2OBJS) $(SBLAS2OBJS) $(DBLAS2OBJS) $(QBLAS2OBJS) $(CBLAS2OBJS) $(ZBLAS2OBJS) $(XBLAS2OBJS)
level2 : $(SBBLAS2OBJS) $(BBLAS2OBJS) $(SBLAS2OBJS) $(DBLAS2OBJS) $(QBLAS2OBJS) $(CBLAS2OBJS) $(ZBLAS2OBJS) $(XBLAS2OBJS)
$(AR) $(ARFLAGS) -ru $(TOPDIR)/$(LIBNAME) $^

level3 : $(SBBLAS3OBJS) $(SBLAS3OBJS) $(DBLAS3OBJS) $(QBLAS3OBJS) $(CBLAS3OBJS) $(ZBLAS3OBJS) $(XBLAS3OBJS) $(SHBLAS3OBJS)
level3 : $(SBBLAS3OBJS) $(BBLAS3OBJ) $(SBLAS3OBJS) $(DBLAS3OBJS) $(QBLAS3OBJS) $(CBLAS3OBJS) $(ZBLAS3OBJS) $(XBLAS3OBJS) $(SHBLAS3OBJS)
$(AR) $(ARFLAGS) -ru $(TOPDIR)/$(LIBNAME) $^

aux : $(CBAUXOBJS)
@@ -792,6 +830,8 @@ dsdot.$(SUFFIX) dsdot.$(PSUFFIX) : dsdot.c
$(CC) $(CFLAGS) -c $< -o $(@F)

ifeq ($(BUILD_BFLOAT16),1)
bscal.$(SUFFIX) bscal.$(PSUFFIX) : scal.c
$(CC) $(CFLAGS) -DBGEMM -c $< -o $(@F)
sbdot.$(SUFFIX) sbdot.$(PSUFFIX) : bf16dot.c
$(CC) $(CFLAGS) -c $< -o $(@F)
sbstobf16.$(SUFFIX) sbstobf16.$(PSUFFIX) : tobf16.c
@@ -949,6 +989,8 @@ xgerc.$(SUFFIX) xgerc.$(PSUFFIX) : zger.c
$(CC) -c $(CFLAGS) -DCONJ $< -o $(@F)

ifeq ($(BUILD_BFLOAT16),1)
bgemv.$(SUFFIX) bgemv.$(PSUFFIX) : sbgemv.c
$(CC) $(CFLAGS) -DBGEMM -c $< -o $(@F)
sbgemv.$(SUFFIX) sbgemv.$(PSUFFIX) : sbgemv.c
$(CC) $(CFLAGS) -c $< -o $(@F)
endif
@@ -1311,6 +1353,8 @@ xhpr2.$(SUFFIX) xhpr2.$(PSUFFIX) : zhpr2.c
$(CC) -c $(CFLAGS) $< -o $(@F)

ifeq ($(BUILD_BFLOAT16),1)
bgemm.$(SUFFIX) bgemm.$(PSUFFIX) : gemm.c ../param.h
$(CC) -c $(CFLAGS) $< -o $(@F)
sbgemm.$(SUFFIX) sbgemm.$(PSUFFIX) : gemm.c ../param.h
$(CC) -c $(CFLAGS) $< -o $(@F)
sbgemmt.$(SUFFIX) sbgemmt.$(PSUFFIX) : sbgemmt.c ../param.h
@@ -1619,6 +1663,8 @@ cblas_dsdot.$(SUFFIX) cblas_dsdot.$(PSUFFIX) : dsdot.c
$(CC) $(CFLAGS) -DCBLAS -c $< -o $(@F)

ifeq ($(BUILD_BFLOAT16),1)
cblas_bscal.$(SUFFIX) cblas_bscal.$(PSUFFIX) : scal.c
$(CC) $(CFLAGS) -DCBLAS -c $< -o $(@F)
cblas_sbdot.$(SUFFIX) cblas_sbdot.$(PSUFFIX) : bf16dot.c
$(CC) $(CFLAGS) -DCBLAS -c $< -o $(@F)
cblas_sbstobf16.$(SUFFIX) cblas_sbstobf16.$(PSUFFIX) : tobf16.c
@@ -1773,6 +1819,8 @@ cblas_zdrot.$(SUFFIX) cblas_zdrot.$(PSUFFIX) : zrot.c
$(CC) $(CFLAGS) -DCBLAS -c $< -o $(@F)

ifeq ($(BUILD_BFLOAT16),1)
cblas_bgemv.$(SUFFIX) cblas_bgemv.$(PSUFFIX) : sbgemv.c
$(CC) -DCBLAS -DBGEMM -c $(CFLAGS) $< -o $(@F)
cblas_sbgemv.$(SUFFIX) cblas_sbgemv.$(PSUFFIX) : sbgemv.c
$(CC) -DCBLAS -c $(CFLAGS) $< -o $(@F)
endif
@@ -1979,6 +2027,8 @@ cblas_sgemm.$(SUFFIX) cblas_sgemm.$(PSUFFIX) : gemm.c ../param.h
$(CC) -DCBLAS -c $(CFLAGS) $< -o $(@F)

ifeq ($(BUILD_BFLOAT16),1)
cblas_bgemm.$(SUFFIX) cblas_bgemm.$(PSUFFIX) : gemm.c ../param.h
$(CC) -DCBLAS -DBGEMM -c $(CFLAGS) $< -o $(@F)
cblas_sbgemm.$(SUFFIX) cblas_sbgemm.$(PSUFFIX) : gemm.c ../param.h
$(CC) -DCBLAS -c $(CFLAGS) $< -o $(@F)
endif


+ 10
- 2
interface/gemm.c View File

@@ -54,8 +54,13 @@
#define ERROR_NAME "DGEMM "
#define GEMV BLASFUNC(dgemv)
#elif defined(BFLOAT16)
#ifdef BGEMM
#define ERROR_NAME "BGEMM "
#define GEMV BLASFUNC(bgemv)
#else
#define ERROR_NAME "SBGEMM "
#define GEMV BLASFUNC(sbgemv)
#endif
#elif defined(HFLOAT16)
#define ERROR_NAME "SHGEMM "
#else
@@ -113,7 +118,7 @@ static int (*gemm[])(blas_arg_t *, BLASLONG *, BLASLONG *, IFLOAT *, IFLOAT *, B
#endif
};

#if defined(SMALL_MATRIX_OPT) && !defined(GEMM3M) && !defined(XDOUBLE) &&!defined(HFLOAT16)
#if defined(SMALL_MATRIX_OPT) && !defined(GEMM3M) && !defined(XDOUBLE) && !defined(HFLOAT16) && !defined(BGEMM)
#define USE_SMALL_MATRIX_OPT 1
#else
#define USE_SMALL_MATRIX_OPT 0
@@ -436,6 +441,9 @@ void CNAME(enum CBLAS_ORDER order, enum CBLAS_TRANSPOSE TransA, enum CBLAS_TRANS
if (beta == 0 && alpha == 1.0 && order == CblasRowMajor && TransA == CblasNoTrans && TransB == CblasNoTrans) {
SGEMM_DIRECT(m, n, k, a, lda, b, ldb, c, ldc);
return;
}else if (order == CblasRowMajor && TransA == CblasNoTrans && TransB == CblasNoTrans) {
SGEMM_DIRECT_ALPHA_BETA(m, n, k, alpha, a, lda, b, ldb, beta, c, ldc);
return;
}
#endif
#endif
@@ -579,7 +587,7 @@ void CNAME(enum CBLAS_ORDER order, enum CBLAS_TRANSPOSE TransA, enum CBLAS_TRANS
args.m, args.n, args.k, args.lda, args.ldb, args.ldc);
#endif

#if defined(GEMM_GEMV_FORWARD) && !defined(GEMM3M) && !defined(COMPLEX) && !defined(HFLOAT16) && (!defined(BFLOAT16) || defined(GEMM_GEMV_FORWARD_BF16))
#if defined(GEMM_GEMV_FORWARD) && !defined(GEMM3M) && !defined(COMPLEX) && !defined(HFLOAT16) && (!defined(BFLOAT16) || (!defined(BGEMM) && defined(SBGEMM_GEMV_FORWARD)) || (defined(BGEMM) && defined(BGEMM_GEMV_FORWARD)))
#if defined(ARCH_ARM64)
// The gemv kernels in arm64/{gemv_n.S,gemv_n_sve.c,gemv_t.S,gemv_t_sve.c}
// perform poorly in certain circumstances. We use the following boolean


+ 2
- 2
interface/sbgemmt.c View File

@@ -1,5 +1,5 @@
/*********************************************************************/
/* Copyright 2024, The OpenBLAS Project. */
/* Copyright 2024-2025 The OpenBLAS Project. */
/* All rights reserved. */
/* */
/* Redistribution and use in source and binary forms, with or */
@@ -305,7 +305,7 @@ void CNAME(enum CBLAS_ORDER order, enum CBLAS_UPLO Uplo,
#endif
int (*gemv[]) (BLASLONG, BLASLONG, FLOAT, IFLOAT *, BLASLONG,
IFLOAT *, BLASLONG, FLOAT, FLOAT *, BLASLONG) = {
SBGEMV_N, SBGEMV_T,};
GEMV_N, GEMV_T,};


if (m == 0)


+ 32
- 14
interface/sbgemv.c View File

@@ -1,4 +1,5 @@
/*********************************************************************/
/* Copyright 2025 The OpenBLAS Project. */
/* Copyright 2009, 2010 The University of Texas at Austin. */
/* All rights reserved. */
/* */
@@ -43,17 +44,25 @@
#include "functable.h"
#endif

#ifdef BGEMM
#define GEMV_THREAD_N bgemv_thread_n
#define GEMV_THREAD_T bgemv_thread_t
#define ERROR_NAME "BGEMV "
#else
#define GEMV_THREAD_N sbgemv_thread_n
#define GEMV_THREAD_T sbgemv_thread_t
#define ERROR_NAME "SBGEMV "
#endif

#ifdef SMP
static int (*sbgemv_thread[])(BLASLONG, BLASLONG, float, bfloat16 *, BLASLONG, bfloat16 * , BLASLONG, float, float *, BLASLONG, int) = {
sbgemv_thread_n, sbgemv_thread_t,
static int (*gemv_thread[])(BLASLONG, BLASLONG, FLOAT, IFLOAT *, BLASLONG, IFLOAT * , BLASLONG, FLOAT, FLOAT *, BLASLONG, int) = {
GEMV_THREAD_N, GEMV_THREAD_T,
};
#endif

#ifndef CBLAS

void NAME(char *TRANS, blasint *M, blasint *N, float *ALPHA, bfloat16 *a, blasint *LDA, bfloat16 *x, blasint *INCX, float *BETA, float *y, blasint *INCY)
void NAME(char *TRANS, blasint *M, blasint *N, FLOAT *ALPHA, IFLOAT *a, blasint *LDA, IFLOAT *x, blasint *INCX, FLOAT *BETA, FLOAT *y, blasint *INCY)
{
char trans = *TRANS;
blasint m = *M;
@@ -61,14 +70,14 @@ void NAME(char *TRANS, blasint *M, blasint *N, float *ALPHA, bfloat16 *a, blasin
blasint lda = *LDA;
blasint incx = *INCX;
blasint incy = *INCY;
float alpha = *ALPHA;
float beta = *BETA;
FLOAT alpha = *ALPHA;
FLOAT beta = *BETA;
#ifdef SMP
int nthreads;
#endif

int (*sbgemv[])(BLASLONG, BLASLONG, float, bfloat16 *, BLASLONG, bfloat16 * , BLASLONG, float, float *, BLASLONG) = {
SBGEMV_N, SBGEMV_T,
int (*gemv[])(BLASLONG, BLASLONG, FLOAT, IFLOAT *, BLASLONG, IFLOAT * , BLASLONG, FLOAT, FLOAT *, BLASLONG) = {
GEMV_N, GEMV_T,
};

blasint info;
@@ -104,7 +113,7 @@ void NAME(char *TRANS, blasint *M, blasint *N, float *ALPHA, bfloat16 *a, blasin

#else

void CNAME(enum CBLAS_ORDER order, enum CBLAS_TRANSPOSE TransA, blasint m, blasint n, float alpha, bfloat16 *a, blasint lda, bfloat16 *x, blasint incx, float beta, float *y, blasint incy)
void CNAME(enum CBLAS_ORDER order, enum CBLAS_TRANSPOSE TransA, blasint m, blasint n, FLOAT alpha, IFLOAT *a, blasint lda, IFLOAT *x, blasint incx, FLOAT beta, FLOAT *y, blasint incy)
{
blasint lenx, leny;
int trans;
@@ -113,8 +122,8 @@ void CNAME(enum CBLAS_ORDER order, enum CBLAS_TRANSPOSE TransA, blasint m, blasi
int nthreads;
#endif

int (*sbgemv[])(BLASLONG, BLASLONG, float, bfloat16 *, BLASLONG, bfloat16 * , BLASLONG, float, float *, BLASLONG) = {
SBGEMV_N, SBGEMV_T,
int (*gemv[])(BLASLONG, BLASLONG, FLOAT, IFLOAT *, BLASLONG, IFLOAT * , BLASLONG, FLOAT, FLOAT *, BLASLONG) = {
GEMV_N, GEMV_T,
};

PRINT_DEBUG_CNAME;
@@ -166,8 +175,17 @@ void CNAME(enum CBLAS_ORDER order, enum CBLAS_TRANSPOSE TransA, blasint m, blasi
leny = m;
}

if (alpha == ZERO) {
if (beta != ONE) SCAL_K(leny, 0, 0, beta, y, blasabs(incy), NULL, 0, NULL, 0);
#ifdef BGEMM
float alpha_float, beta_float;
SBF16TOS_K(1, &alpha, 1, &alpha_float, 1);
SBF16TOS_K(1, &beta, 1, &beta_float, 1);
#else
float alpha_float = alpha;
float beta_float = beta;
#endif

if (alpha_float == ZERO) {
if (beta_float != ONE) SCAL_K(leny, 0, 0, beta, y, blasabs(incy), NULL, 0, NULL, 0);
return;
}

@@ -185,10 +203,10 @@ void CNAME(enum CBLAS_ORDER order, enum CBLAS_TRANSPOSE TransA, blasint m, blasi

if (nthreads == 1) {
#endif
(sbgemv[(int)trans])(m, n, alpha, a, lda, x, incx, beta, y, incy);
(gemv[(int)trans])(m, n, alpha, a, lda, x, incx, beta, y, incy);
#ifdef SMP
} else {
(sbgemv_thread[(int)trans])(m, n, alpha, a, lda, x, incx, beta, y, incy, nthreads);
(gemv_thread[(int)trans])(m, n, alpha, a, lda, x, incx, beta, y, incy, nthreads);
}
#endif



+ 9
- 1
interface/scal.c View File

@@ -1,4 +1,5 @@
/*********************************************************************/
/* Copyright 2025 The OpenBLAS Project. */
/* Copyright 2009, 2010 The University of Texas at Austin. */
/* All rights reserved. */
/* */
@@ -68,7 +69,14 @@ void CNAME(blasint n, FLOAT alpha, FLOAT *x, blasint incx){

if (incx <= 0 || n <= 0) return;

if (alpha == ONE) return;
#ifdef BGEMM
float alpha_float;
SBF16TOS_K(1, &alpha, 1, &alpha_float, 1);
#else
float alpha_float = alpha;
#endif

if (alpha_float == ONE) return;

IDEBUG_START;



+ 49
- 0
kernel/CMakeLists.txt View File

@@ -1,3 +1,30 @@
###############################################################################
# Copyright (c) 2025, 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_directories(${PROJECT_SOURCE_DIR})

@@ -94,6 +121,7 @@ function (build_core TARGET_CORE KDIR TSUFFIX KERNEL_DEFINITIONS)

# sbdot
if (BUILD_BFLOAT16)
GenerateNamedObjects("${KERNELDIR}/${BSCALKERNEL}" "BGEMM" "scal_k" false "" "" false "BFLOAT16")
GenerateNamedObjects("${KERNELDIR}/${SBDOTKERNEL}" "SBDOT" "dot_k" false "" "" false "BFLOAT16")
GenerateNamedObjects("${KERNELDIR}/${BF16TOKERNEL}" "SINGLE" "f16tos_k" false "" "" false "BFLOAT16")
GenerateNamedObjects("${KERNELDIR}/${BF16TOKERNEL}" "DOUBLE" "bf16tod_k" false "" "" false "DOUBLE")
@@ -195,6 +223,8 @@ function (build_core TARGET_CORE KDIR TSUFFIX KERNEL_DEFINITIONS)
GenerateNamedObjects("${KERNELDIR}/${SGEMVTKERNEL}" "TRANS" "gemv_t" false "" "" false "SINGLE")
endif ()
if (BUILD_BFLOAT16)
GenerateNamedObjects("${KERNELDIR}/${BGEMVNKERNEL}" "BGEMM" "gemv_n" false "" "" false "BFLOAT16")
GenerateNamedObjects("${KERNELDIR}/${BGEMVTKERNEL}" "BGEMM" "gemv_t" false "" "" false "BFLOAT16")
GenerateNamedObjects("${KERNELDIR}/${SBGEMVNKERNEL}" "" "gemv_n" false "" "" false "BFLOAT16")
GenerateNamedObjects("${KERNELDIR}/${SBGEMVTKERNEL}" "" "gemv_t" false "" "" false "BFLOAT16")
endif ()
@@ -211,6 +241,9 @@ function (build_core TARGET_CORE KDIR TSUFFIX KERNEL_DEFINITIONS)
if (X86_64 OR ARM64)
set(USE_DIRECT_SGEMM true)
endif()
if (UC_TARGET_CORE MATCHES ARMV9SME)
set (HAVE_SME true)
endif ()

if (USE_DIRECT_SGEMM)
# if (NOT DEFINED SGEMMDIRECTKERNEL)
@@ -222,9 +255,11 @@ function (build_core TARGET_CORE KDIR TSUFFIX KERNEL_DEFINITIONS)
GenerateNamedObjects("${KERNELDIR}/${SGEMMDIRECTPERFORMANT}" "" "gemm_direct_performant" false "" "" false SINGLE)
elseif (ARM64)
set (SGEMMDIRECTKERNEL sgemm_direct_arm64_sme1.c)
set (SGEMMDIRECTKERNEL_ALPHA_BETA sgemm_direct_alpha_beta_arm64_sme1.c)
set (SGEMMDIRECTSMEKERNEL sgemm_direct_sme1.S)
set (SGEMMDIRECTPREKERNEL sgemm_direct_sme1_preprocess.S)
GenerateNamedObjects("${KERNELDIR}/${SGEMMDIRECTKERNEL}" "" "gemm_direct" false "" "" false SINGLE)
GenerateNamedObjects("${KERNELDIR}/${SGEMMDIRECTKERNEL_ALPHA_BETA}" "" "gemm_direct_alpha_beta" false "" "" false SINGLE)
if (HAVE_SME)
GenerateNamedObjects("${KERNELDIR}/${SGEMMDIRECTSMEKERNEL}" "" "gemm_direct_sme1" false "" "" false SINGLE)
GenerateNamedObjects("${KERNELDIR}/${SGEMMDIRECTPREKERNEL}" "" "gemm_direct_sme1_preprocess" false "" "" false SINGLE)
@@ -336,6 +371,20 @@ function (build_core TARGET_CORE KDIR TSUFFIX KERNEL_DEFINITIONS)
endif ()

if (BUILD_BFLOAT16)
if (BGEMMINCOPY)
GenerateNamedObjects("${KERNELDIR}/${BGEMMINCOPY}" "BGEMM" "${BGEMMINCOPYOBJ}" false "" "" true "BFLOAT16")
endif ()
if (BGEMMITCOPY)
GenerateNamedObjects("${KERNELDIR}/${BGEMMITCOPY}" "BGEMM" "${BGEMMITCOPYOBJ}" false "" "" true "BFLOAT16")
endif ()
if (BGEMMONCOPY)
GenerateNamedObjects("${KERNELDIR}/${BGEMMONCOPY}" "BGEMM" "${BGEMMONCOPYOBJ}" false "" "" true "BFLOAT16")
endif ()
if (BGEMMOTCOPY)
GenerateNamedObjects("${KERNELDIR}/${BGEMMOTCOPY}" "BGEMM" "${BGEMMOTCOPYOBJ}" false "" "" true "BFLOAT16")
endif ()
GenerateNamedObjects("${KERNELDIR}/${BGEMMKERNEL}" "BGEMM" "gemm_kernel" false "" "" false "BFLOAT16")
GenerateNamedObjects("${KERNELDIR}/${BGEMM_BETA}" "BGEMM" "gemm_beta" false "" "" false "BFLOAT16")
if (SBGEMMINCOPY)
GenerateNamedObjects("${KERNELDIR}/${SBGEMMINCOPY}" "" "${SBGEMMINCOPYOBJ}" false "" "" true "BFLOAT16")
endif ()


+ 36
- 0
kernel/Makefile.L1 View File

@@ -1,3 +1,31 @@
###############################################################################
# Copyright (c) 2025 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.
###############################################################################

FMAFLAG=
ifndef OLDGCC
ifdef HAVE_FMA3
@@ -271,6 +299,10 @@ XDOTKERNEL = zdot.S
endif

ifeq ($(BUILD_BFLOAT16),1)
ifndef BSCALKERNEL
BSCALKERNEL = ../generic/scal.c
endif

ifndef SBDOTKERNEL
SBDOTKERNEL = ../x86_64/sbdot.c
endif
@@ -551,6 +583,8 @@ XBLASOBJS += \
xscal_k$(TSUFFIX).$(SUFFIX) xswap_k$(TSUFFIX).$(SUFFIX) xsum_k$(TSUFFIX).$(SUFFIX)

ifeq ($(BUILD_BFLOAT16),1)
BBLASOBJS += \
bscal_k$(TSUFFIX).$(SUFFIX)
SBBLASOBJS += \
sbdot_k$(TSUFFIX).$(SUFFIX)
SBEXTOBJS += \
@@ -778,6 +812,8 @@ $(KDIR)qdot_k$(TSUFFIX).$(SUFFIX) $(KDIR)qdot_k$(TPSUFFIX).$(PSUFFIX) : $(KERNEL
$(CC) -c $(CFLAGS) -UCOMPLEX -DXDOUBLE $< -o $@

ifeq ($(BUILD_BFLOAT16),1)
$(KDIR)bscal_k$(TSUFFIX).$(SUFFIX) $(KDIR)bscal_k$(TPSUFFIX).$(PSUFFIX) : $(KERNELDIR)/$(BSCALKERNEL)
$(CC) -c $(CFLAGS) -UCOMPLEX -UDOUBLE $< -o $@
$(KDIR)sbdot_k$(TSUFFIX).$(SUFFIX) $(KDIR)sbdot_k$(TPSUFFIX).$(PSUFFIX) : $(KERNELDIR)/$(SBDOTKERNEL)
$(CC) -c $(CFLAGS) -UCOMPLEX $< -o $@
$(KDIR)sbstobf16_k$(TSUFFIX).$(SUFFIX) : $(KERNELDIR)/$(TOBF16KERNEL)


+ 43
- 0
kernel/Makefile.L2 View File

@@ -1,3 +1,31 @@
###############################################################################
# Copyright (c) 2025 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.
###############################################################################

FMAFLAG=
ifndef OLDGCC
ifdef HAVE_FMA3
@@ -56,6 +84,14 @@ XGEMVTKERNEL = zgemv_t.S
endif

ifeq ($(BUILD_BFLOAT16),1)
ifndef BGEMVNKERNEL
BGEMVNKERNEL = ../generic/gemv_n.c
endif

ifndef BGEMVTKERNEL
BGEMVTKERNEL = ../generic/gemv_t.c
endif

ifndef SBGEMVNKERNEL
SBGEMVNKERNEL = ../x86_64/sbgemv_n.c
endif
@@ -255,6 +291,9 @@ XBLASOBJS += \
xgeru_k$(TSUFFIX).$(SUFFIX) xgerc_k$(TSUFFIX).$(SUFFIX) xgerv_k$(TSUFFIX).$(SUFFIX) xgerd_k$(TSUFFIX).$(SUFFIX)

ifeq ($(BUILD_BFLOAT16),1)
BBLASOBJS += \
bgemv_n$(TSUFFIX).$(SUFFIX) \
bgemv_t$(TSUFFIX).$(SUFFIX)
SBBLASOBJS += \
sbgemv_n$(TSUFFIX).$(SUFFIX) \
sbgemv_t$(TSUFFIX).$(SUFFIX)
@@ -513,5 +552,9 @@ $(KDIR)sbgemv_n$(TSUFFIX).$(SUFFIX) $(KDIR)sbgemv_n$(TPSUFFIX).$(PSUFFIX) : $(KE
$(CC) -c $(CFLAGS) -UCOMPLEX $< -o $@
$(KDIR)sbgemv_t$(TSUFFIX).$(SUFFIX) $(KDIR)sbgemv_t$(TPSUFFIX).$(PSUFFIX) : $(KERNELDIR)/$(SBGEMVTKERNEL)
$(CC) -c $(CFLAGS) -UCOMPLEX $< -o $@
$(KDIR)bgemv_n$(TSUFFIX).$(SUFFIX) $(KDIR)bgemv_n$(TPSUFFIX).$(PSUFFIX) : $(KERNELDIR)/$(BGEMVNKERNEL)
$(CC) -c $(CFLAGS) -DBGEMM -UCOMPLEX $< -o $@
$(KDIR)bgemv_t$(TSUFFIX).$(SUFFIX) $(KDIR)bgemv_t$(TPSUFFIX).$(PSUFFIX) : $(KERNELDIR)/$(BGEMVTKERNEL)
$(CC) -c $(CFLAGS) -DBGEMM -UCOMPLEX $< -o $@
endif


+ 91
- 4
kernel/Makefile.L3 View File

@@ -1,3 +1,30 @@
###############################################################################
# Copyright (c) 2025, 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.
###############################################################################
USE_GEMM3M = 0
OS := $(shell uname)

@@ -105,11 +132,29 @@ ifeq ($(TARGET_CORE), ARMV9SME)
HAVE_SME = 1
endif
SGEMMDIRECTKERNEL = sgemm_direct_arm64_sme1.c
SGEMMDIRECTKERNEL_ALPHA_BETA = sgemm_direct_alpha_beta_arm64_sme1.c
endif
endif
endif

ifeq ($(BUILD_BFLOAT16), 1)
ifndef BGEMMKERNEL
BGEMM_BETA = ../generic/gemm_beta.c
BGEMMKERNEL = ../generic/gemmkernel_2x2.c
BGEMMINCOPY = ../generic/gemm_ncopy_2.c
BGEMMITCOPY = ../generic/gemm_tcopy_2.c
BGEMMONCOPY = ../generic/gemm_ncopy_2.c
BGEMMOTCOPY = ../generic/gemm_tcopy_2.c
BGEMMINCOPYOBJ = bgemm_incopy$(TSUFFIX).$(SUFFIX)
BGEMMITCOPYOBJ = bgemm_itcopy$(TSUFFIX).$(SUFFIX)
BGEMMONCOPYOBJ = bgemm_oncopy$(TSUFFIX).$(SUFFIX)
BGEMMOTCOPYOBJ = bgemm_otcopy$(TSUFFIX).$(SUFFIX)
endif
BKERNELOBJS += \
bgemm_kernel$(TSUFFIX).$(SUFFIX) \
$(BGEMMINCOPYOBJ) $(BGEMMITCOPYOBJ) \
$(BGEMMONCOPYOBJ) $(BGEMMOTCOPYOBJ)

ifndef SBGEMMKERNEL
SBGEMM_BETA = ../generic/gemm_beta.c
SBGEMMKERNEL = ../generic/gemmkernel_2x2.c
@@ -164,7 +209,8 @@ SKERNELOBJS += \
endif
ifeq ($(ARCH), arm64)
SKERNELOBJS += \
sgemm_direct$(TSUFFIX).$(SUFFIX)
sgemm_direct$(TSUFFIX).$(SUFFIX) \
sgemm_direct_alpha_beta$(TSUFFIX).$(SUFFIX)
ifdef HAVE_SME
SKERNELOBJS += \
sgemm_direct_sme1$(TSUFFIX).$(SUFFIX) \
@@ -210,6 +256,7 @@ XKERNELOBJS += \
$(XGEMMONCOPYOBJ) $(XGEMMOTCOPYOBJ)

ifeq ($(BUILD_BFLOAT16),1)
BBLASOBJS += $(BKERNELOBJS)
SBBLASOBJS += $(SBKERNELOBJS)
endif
ifeq ($(BUILD_HFLOAT16),1)
@@ -223,6 +270,7 @@ ZBLASOBJS += $(ZKERNELOBJS)
XBLASOBJS += $(XKERNELOBJS)

ifeq ($(BUILD_BFLOAT16),1)
BBLASOBJS += bgemm_beta$(TSUFFIX).$(SUFFIX)
SBBLASOBJS += sbgemm_beta$(TSUFFIX).$(SUFFIX)
endif
ifeq ($(BUILD_HFLOAT16),1)
@@ -628,6 +676,10 @@ ZBLASOBJS += \
endif

ifeq ($(BUILD_BFLOAT16), 1)
BGEMMINCOPYOBJ_P = $(BGEMMINCOPYOBJ:.$(SUFFIX)=.$(PSUFFIX))
BGEMMITCOPYOBJ_P = $(BGEMMITCOPYOBJ:.$(SUFFIX)=.$(PSUFFIX))
BGEMMONCOPYOBJ_P = $(BGEMMONCOPYOBJ:.$(SUFFIX)=.$(PSUFFIX))
BGEMMOTCOPYOBJ_P = $(BGEMMOTCOPYOBJ:.$(SUFFIX)=.$(PSUFFIX))
SBGEMMINCOPYOBJ_P = $(SBGEMMINCOPYOBJ:.$(SUFFIX)=.$(PSUFFIX))
SBGEMMITCOPYOBJ_P = $(SBGEMMITCOPYOBJ:.$(SUFFIX)=.$(PSUFFIX))
SBGEMMONCOPYOBJ_P = $(SBGEMMONCOPYOBJ:.$(SUFFIX)=.$(PSUFFIX))
@@ -667,6 +719,8 @@ XGEMMONCOPYOBJ_P = $(XGEMMONCOPYOBJ:.$(SUFFIX)=.$(PSUFFIX))
XGEMMOTCOPYOBJ_P = $(XGEMMOTCOPYOBJ:.$(SUFFIX)=.$(PSUFFIX))

ifeq ($(BUILD_BFLOAT16),1)
$(KDIR)bgemm_beta$(TSUFFIX).$(SUFFIX) : $(KERNELDIR)/$(BGEMM_BETA)
$(CC) $(CFLAGS) -c -DBFLOAT16 -DBGEMM -UDOUBLE -UCOMPLEX $< -o $@
$(KDIR)sbgemm_beta$(TSUFFIX).$(SUFFIX) : $(KERNELDIR)/$(SBGEMM_BETA)
$(CC) $(CFLAGS) -c -DBFLOAT16 -UDOUBLE -UCOMPLEX $< -o $@
endif
@@ -698,9 +752,22 @@ ifeq ($(ARCH), E2K)
USE_TRMM = 1
endif


ifeq ($(BUILD_BFLOAT16), 1)

$(KDIR)$(BGEMMONCOPYOBJ) : $(KERNELDIR)/$(BGEMMONCOPY)
$(CC) $(CFLAGS) -c -DBFLOAT16 -DBGEMM -UDOUBLE -UCOMPLEX $< -o $@

$(KDIR)$(BGEMMOTCOPYOBJ) : $(KERNELDIR)/$(BGEMMOTCOPY)
$(CC) $(CFLAGS) -c -DBFLOAT16 -DBGEMM -UDOUBLE -UCOMPLEX $< -o $@

ifneq ($(BGEMM_UNROLL_M), $(BGEMM_UNROLL_N))
$(KDIR)$(BGEMMINCOPYOBJ) : $(KERNELDIR)/$(BGEMMINCOPY)
$(CC) $(CFLAGS) -c -DBFLOAT16 -DBGEMM -UDOUBLE -UCOMPLEX $< -o $@

$(KDIR)$(BGEMMITCOPYOBJ) : $(KERNELDIR)/$(BGEMMITCOPY)
$(CC) $(CFLAGS) -c -DBFLOAT16 -DBGEMM -UDOUBLE -UCOMPLEX $< -o $@
endif

$(KDIR)$(SBGEMMONCOPYOBJ) : $(KERNELDIR)/$(SBGEMMONCOPY)
$(CC) $(CFLAGS) -c -DBFLOAT16 -UDOUBLE -UCOMPLEX $< -o $@

@@ -904,6 +971,8 @@ endif
ifeq ($(ARCH), arm64)
$(KDIR)sgemm_direct$(TSUFFIX).$(SUFFIX) : $(KERNELDIR)/$(SGEMMDIRECTKERNEL)
$(CC) $(CFLAGS) -c -UDOUBLE -UCOMPLEX $< -o $@
$(KDIR)sgemm_direct_alpha_beta$(TSUFFIX).$(SUFFIX) : $(KERNELDIR)/$(SGEMMDIRECTKERNEL_ALPHA_BETA)
$(CC) $(CFLAGS) -c -UDOUBLE -UCOMPLEX $< -o $@
ifdef HAVE_SME
$(KDIR)sgemm_direct_sme1$(TSUFFIX).$(SUFFIX) :
$(CC) $(CFLAGS) -c $(KERNELDIR)/sgemm_direct_sme1.S -UDOUBLE -UCOMPLEX -o $@
@@ -914,7 +983,8 @@ endif
endif

ifeq ($(BUILD_BFLOAT16), 1)

$(KDIR)bgemm_kernel$(TSUFFIX).$(SUFFIX) : $(KERNELDIR)/$(BGEMMKERNEL)
$(CC) $(CFLAGS) -c -DBFLOAT16 -DBGEMM -UDOUBLE -UCOMPLEX $< -o $@
$(KDIR)sbgemm_kernel$(TSUFFIX).$(SUFFIX) : $(KERNELDIR)/$(SBGEMMKERNEL) $(SBGEMMDEPEND)
$(CC) $(CFLAGS) -c -DBFLOAT16 -UDOUBLE -UCOMPLEX $< -o $@
endif
@@ -2908,6 +2978,8 @@ $(KDIR)sgemm_beta$(TSUFFIX).$(PSUFFIX) : $(KERNELDIR)/$(SGEMM_BETA)
$(CC) $(PFLAGS) -c -UDOUBLE -UCOMPLEX $< -o $@

ifeq ($(BUILD_BFLOAT16),1)
$(KDIR)bgemm_beta$(TSUFFIX).$(PSUFFIX) : $(KERNELDIR)/$(BGEMM_BETA)
$(CC) $(PFLAGS) -c -DBFLOAT16 -DBGEMM -UDOUBLE -UCOMPLEX $< -o $@
$(KDIR)sbgemm_beta$(TSUFFIX).$(PSUFFIX) : $(KERNELDIR)/$(SBGEMM_BETA)
$(CC) $(PFLAGS) -c -DBFLOAT16 -UDOUBLE -UCOMPLEX $< -o $@
endif
@@ -2934,6 +3006,20 @@ $(KDIR)xgemm_beta$(TSUFFIX).$(PSUFFIX) : $(KERNELDIR)/$(XGEMM_BETA)


ifeq ($(BUILD_BFLOAT16), 1)
$(BGEMMONCOPYOBJ_P) : $(KERNELDIR)/$(BGEMMONCOPY)
$(CC) $(PFLAGS) -c -DBFLOAT16 -DBGEMM -UDOUBLE -UCOMPLEX $< -o $@

$(BGEMMOTCOPYOBJ_P) : $(KERNELDIR)/$(BGEMMOTCOPY)
$(CC) $(PFLAGS) -c -DBFLOAT16 -DBGEMM -UDOUBLE -UCOMPLEX $< -o $@

ifneq ($(BGEMM_UNROLL_M), $(BGEMM_UNROLL_N))
$(BGEMMINCOPYOBJ_P) : $(KERNELDIR)/$(BGEMMINCOPY)
$(CC) $(PFLAGS) -c -DBFLOAT16 -DBGEMM -UDOUBLE -UCOMPLEX $< -o $@

$(BGEMMITCOPYOBJ_P) : $(KERNELDIR)/$(BGEMMITCOPY)
$(CC) $(PFLAGS) -c -DBFLOAT16 -DBGEMM -UDOUBLE -UCOMPLEX $< -o $@
endif

$(SBGEMMONCOPYOBJ_P) : $(KERNELDIR)/$(SBGEMMONCOPY)
$(CC) $(PFLAGS) -c -DBFLOAT16 -UDOUBLE -UCOMPLEX $< -o $@

@@ -2946,7 +3032,6 @@ $(SBGEMMINCOPYOBJ_P) : $(KERNELDIR)/$(SBGEMMINCOPY)

$(SBGEMMITCOPYOBJ_P) : $(KERNELDIR)/$(SBGEMMITCOPY)
$(CC) $(PFLAGS) -c -DBFLOAT16 -UDOUBLE -UCOMPLEX $< -o $@

endif
endif

@@ -3073,6 +3158,8 @@ endif


ifeq ($(BUILD_BFLOAT16), 1)
$(KDIR)bgemm_kernel$(TSUFFIX).$(PSUFFIX) : $(KERNELDIR)/$(BGEMMKERNEL) $(BGEMMDEPEND)
$(CC) $(PFLAGS) -c -DBFLOAT16 -DBGEMM -UDOUBLE -UCOMPLEX $< -o $@
$(KDIR)sbgemm_kernel$(TSUFFIX).$(PSUFFIX) : $(KERNELDIR)/$(SBGEMMKERNEL) $(SBGEMMDEPEND)
$(CC) $(PFLAGS) -c -DBFLOAT16 -UDOUBLE -UCOMPLEX $< -o $@
endif


+ 3
- 0
kernel/arm64/KERNEL.A64FX View File

@@ -4,3 +4,6 @@ SGEMVNKERNEL = gemv_n_sve_v4x3.c
DGEMVNKERNEL = gemv_n_sve_v4x3.c
SGEMVTKERNEL = gemv_t_sve_v4x3.c
DGEMVTKERNEL = gemv_t_sve_v4x3.c

DDOTKERNEL = dot_sve_v8.c
SDOTKERNEL = dot_sve_v8.c

+ 42
- 1
kernel/arm64/KERNEL.NEOVERSEV1 View File

@@ -1,3 +1,31 @@
###############################################################################
# Copyright (c) 2025, 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 $(KERNELDIR)/KERNEL.ARMV8SVE

SGEMVNKERNEL = gemv_n_sve_v1x3.c
@@ -5,6 +33,19 @@ DGEMVNKERNEL = gemv_n_sve_v1x3.c
SGEMVTKERNEL = gemv_t_sve_v1x3.c
DGEMVTKERNEL = gemv_t_sve_v1x3.c
ifeq ($(BUILD_BFLOAT16), 1)
BGEMM_BETA = bgemm_beta_neon.c
BGEMMKERNEL = bgemm_kernel_$(BGEMM_UNROLL_M)x$(BGEMM_UNROLL_N)_neoversev1.c
ifneq ($(BGEMM_UNROLL_M), $(BGEMM_UNROLL_N))
BGEMMINCOPY = sbgemm_ncopy_$(SBGEMM_UNROLL_M)_neoversev1.c
BGEMMITCOPY = sbgemm_tcopy_$(SBGEMM_UNROLL_M)_neoversev1.c
BGEMMINCOPYOBJ = bgemm_incopy$(TSUFFIX).$(SUFFIX)
BGEMMITCOPYOBJ = bgemm_itcopy$(TSUFFIX).$(SUFFIX)
endif
BGEMMONCOPY = sbgemm_ncopy_$(BGEMM_UNROLL_N)_neoversev1.c
BGEMMOTCOPY = sbgemm_tcopy_$(BGEMM_UNROLL_N)_neoversev1.c
BGEMMONCOPYOBJ = bgemm_oncopy$(TSUFFIX).$(SUFFIX)
BGEMMOTCOPYOBJ = bgemm_otcopy$(TSUFFIX).$(SUFFIX)

SBGEMM_BETA = sbgemm_beta_neoversev1.c
SBGEMMKERNEL = sbgemm_kernel_$(SBGEMM_UNROLL_M)x$(SBGEMM_UNROLL_N)_neoversev1.c
ifneq ($(SBGEMM_UNROLL_M), $(SBGEMM_UNROLL_N))
@@ -21,4 +62,4 @@ SBGEMMOTCOPYOBJ = sbgemm_otcopy$(TSUFFIX).$(SUFFIX)
SBGEMVNKERNEL = sbgemv_n_neon.c
SBGEMVTKERNEL = sbgemv_t_bfdot.c

endif
endif

+ 107
- 0
kernel/arm64/bgemm_beta_neon.c View File

@@ -0,0 +1,107 @@
/***************************************************************************
* Copyright (c) 2025, 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 "common.h"

#include <arm_neon.h>

int CNAME(BLASLONG m, BLASLONG n, BLASLONG dummy1, FLOAT beta_in, IFLOAT *dummy2,
BLASLONG dummy3, IFLOAT *dummy4, BLASLONG dummy5, FLOAT *c,
BLASLONG ldc) {
BLASLONG i, j;
BLASLONG chunk, remain;
bfloat16_t *ptr_c, *ptr_c0;

bfloat16x8_t x0, z0;
float32x4_t y0, y1;
float x;
bfloat16_t z;

bfloat16_t zero_bf16 = vcvth_bf16_f32(0.0f);
bfloat16x8_t zeros = vdupq_n_bf16(zero_bf16);

bfloat16_t beta_bf16;
memcpy(&beta_bf16, &beta_in, sizeof(bfloat16_t));
float beta = vcvtah_f32_bf16(beta_bf16);
float32x4_t beta_neon = vdupq_n_f32(beta);

ptr_c = (bfloat16_t *)c;
chunk = m >> 3;
remain = m & 7;

if (beta == 0.0f){
for (j = 0; j < n; j ++){
ptr_c0 = ptr_c;
ptr_c += ldc;

for (i = 0; i < chunk; i ++){
vst1q_bf16(ptr_c0, zeros);
ptr_c0 += 8;
}

for (i = 0; i < remain; i ++){
ptr_c0[0] = zero_bf16;
ptr_c0 ++;
}
}
} else {
for (j = 0; j < n; j ++){
ptr_c0 = ptr_c;
ptr_c += ldc;

for (i = 0; i < chunk; i ++){
x0 = vld1q_bf16(ptr_c0);

y0 = vcvtq_low_f32_bf16(x0);
y1 = vcvtq_high_f32_bf16(x0);

y0 = vmulq_f32(y0, beta_neon);
y1 = vmulq_f32(y1, beta_neon);

z0 = vcvtq_low_bf16_f32(y0);
z0 = vcvtq_high_bf16_f32(z0, y1);
vst1q_bf16(ptr_c0, z0);

ptr_c0 += 8;
}

for (i = 0; i < remain; i ++){
x = vcvtah_f32_bf16(ptr_c0[0]);
z = vcvth_bf16_f32(x * beta);

ptr_c0[0] = z;
ptr_c0 ++;
}
}
}
return 0;
};

+ 50
- 0
kernel/arm64/bgemm_kernel_4x4_neoversev1.c View File

@@ -0,0 +1,50 @@
/***************************************************************************
* Copyright (c) 2025, 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 <arm_sve.h>

#include "common.h"

#define ALPHA_ONE
#include "bgemm_kernel_4x4_neoversev1_impl.c"
#undef ALPHA_ONE
#undef UPDATE_C
#include "bgemm_kernel_4x4_neoversev1_impl.c"

int CNAME(BLASLONG m, BLASLONG n, BLASLONG k, FLOAT alpha, IFLOAT *A, IFLOAT *B,
FLOAT *C, BLASLONG ldc) {
bfloat16_t alpha_bf16;
memcpy(&alpha_bf16, &alpha, sizeof(bfloat16_t));
float alpha_f32 = vcvtah_f32_bf16(alpha_bf16);

if (alpha_f32 == 1.0f)
return bgemm_kernel_neoversev1_alpha_one(m, n, k, alpha, A, B, C, ldc);
else
return bgemm_kernel_neoversev1_alpha(m, n, k, alpha, A, B, C, ldc);
return 0;
}

+ 429
- 0
kernel/arm64/bgemm_kernel_4x4_neoversev1_impl.c View File

@@ -0,0 +1,429 @@
/***************************************************************************
* Copyright (c) 2025, 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 <arm_sve.h>

#include "common.h"

#define INIT_C(M, N) mc##M##N = svdup_f32(0);

#define MATMUL(M, N) mc##M##N = svbfmmla(mc##M##N, ma##M, mb##N);

#define INIT_C_4x4 \
do { \
INIT_C(0, 0); \
INIT_C(0, 1); \
INIT_C(1, 0); \
INIT_C(1, 1); \
} while (0);

#ifdef ALPHA_ONE
#define UPDATE_C(PG16, PG32, PTR, TMP32, TMP16, SRC32) \
do { \
TMP32 = svreinterpret_f32_u32(svld1uh_u32((PG16), (uint16_t*)PTR)); \
TMP32 = svadd_z((PG32), SRC32, TMP32); \
TMP16 = svcvt_bf16_f32_z((PG32), TMP32); \
TMP16 = svuzp1_bf16(TMP16, TMP16); \
svst1_bf16((PG16), (PTR), TMP16); \
} while (0)
#else
#define UPDATE_C(PG16, PG32, PTR, TMP32, TMP16, SRC32) \
do { \
TMP32 = svreinterpret_f32_u32(svld1uh_u32((PG16), (uint16_t*)PTR)); \
TMP32 = svmad_z((PG32), svalpha, SRC32, TMP32); \
TMP16 = svcvt_bf16_f32_z((PG32), TMP32); \
TMP16 = svuzp1_bf16(TMP16, TMP16); \
svst1_bf16((PG16), (PTR), TMP16); \
} while (0)
#endif

#define ZIP_EVEN_ELEMENTS(PG, mc0, mc1, tmp, vc) \
do { \
(tmp) = svuzp1_f32((mc0), (mc1)); \
(vc) = svcompact_f32((PG), (tmp)); \
} while (0)

#define ZIP_ODD_ELEMENTS(PG, mc0, mc1, tmp, vc) \
do { \
(tmp) = svuzp2_f32((mc0), (mc1)); \
(vc) = svcompact_f32((PG), (tmp)); \
} while (0)

#define ACCUMULATE_LAST4_TO_FIRST4(M, N, TMP) \
do { \
TMP = svext_f32(mc##M##N, mc##M##N, 4); \
mc##M##N = svadd_f32_z(svptrue_b32(), mc##M##N, (TMP)); \
} while (0)

#ifdef ALPHA_ONE
int bgemm_kernel_neoversev1_alpha_one(BLASLONG m, BLASLONG n, BLASLONG k,
FLOAT alpha, IFLOAT *A, IFLOAT *B,
FLOAT *C, BLASLONG ldc)
#else
int bgemm_kernel_neoversev1_alpha(BLASLONG m, BLASLONG n, BLASLONG k,
FLOAT alpha, IFLOAT *A, IFLOAT *B, FLOAT *C,
BLASLONG ldc)
#endif
{
BLASLONG pad_k = (k + 7) & ~7;
svbfloat16_t ma0, ma1, mb0, mb1;
svfloat32_t mc00, mc01, mc10, mc11, vc0, vc1, vc2, vc3;
svfloat32_t tmp;
#ifndef ALPHA_ONE
bfloat16_t alpha_bf16;
memcpy(&alpha_bf16, &alpha, sizeof(bfloat16_t));
svfloat32_t svalpha = svdup_f32(vcvtah_f32_bf16(alpha_bf16));
#endif

svbool_t pg16_all = svptrue_b16();

svbool_t pg32_first_1 = svwhilelt_b32(0, 1);
svbool_t pg32_first_2 = svwhilelt_b32(0, 2);
svbool_t pg32_first_4 = svwhilelt_b32(0, 4);

svbool_t pg16_first_1 = svwhilelt_b16(0, 1);
svbool_t pg16_first_2 = svwhilelt_b16(0, 2);
svbool_t pg16_first_4 = svwhilelt_b16(0, 4);

svbool_t pg32_select_first_2_per_quadword = svdupq_b32(1, 1, 0, 0);

bfloat16_t *ptr_a = (bfloat16_t *)A;
bfloat16_t *ptr_b = (bfloat16_t *)B;
bfloat16_t *ptr_c = (bfloat16_t *)C;

bfloat16_t *ptr_a0;
bfloat16_t *ptr_b0;
bfloat16_t *ptr_c0, *ptr_c1, *ptr_c2, *ptr_c3;

svfloat32_t tmp32;
svbfloat16_t tmp16;

for (BLASLONG j = 0; j < n / 4; j++) {
ptr_c0 = ptr_c;
ptr_c1 = ptr_c0 + ldc;
ptr_c2 = ptr_c1 + ldc;
ptr_c3 = ptr_c2 + ldc;
ptr_c += 4 * ldc;
ptr_a = (bfloat16_t *)A;

for (BLASLONG i = 0; i < m / 4; i++) {
ptr_a0 = ptr_a;
ptr_a += 4 * pad_k;

ptr_b0 = ptr_b;

INIT_C_4x4;

for (BLASLONG p = 0; p < pad_k; p += 8) {
ma0 = svld1_bf16(pg16_all, ptr_a0);
ma1 = svld1_bf16(pg16_all, ptr_a0 + 16);

mb0 = svld1_bf16(pg16_all, ptr_b0);
mb1 = svld1_bf16(pg16_all, ptr_b0 + 16);

MATMUL(0, 0);
MATMUL(0, 1);
MATMUL(1, 0);
MATMUL(1, 1);

ptr_a0 += 32;
ptr_b0 += 32;
}

ACCUMULATE_LAST4_TO_FIRST4(0, 0, tmp);
ACCUMULATE_LAST4_TO_FIRST4(0, 1, tmp);
ACCUMULATE_LAST4_TO_FIRST4(1, 0, tmp);
ACCUMULATE_LAST4_TO_FIRST4(1, 1, tmp);

ZIP_EVEN_ELEMENTS(pg32_select_first_2_per_quadword, mc00, mc10, tmp, vc0);
ZIP_ODD_ELEMENTS(pg32_select_first_2_per_quadword, mc00, mc10, tmp, vc1);

ZIP_EVEN_ELEMENTS(pg32_select_first_2_per_quadword, mc01, mc11, tmp, vc2);
ZIP_ODD_ELEMENTS(pg32_select_first_2_per_quadword, mc01, mc11, tmp, vc3);

UPDATE_C(pg16_first_4, pg32_first_4, ptr_c0, tmp32, tmp16, vc0);
UPDATE_C(pg16_first_4, pg32_first_4, ptr_c1, tmp32, tmp16, vc1);
UPDATE_C(pg16_first_4, pg32_first_4, ptr_c2, tmp32, tmp16, vc2);
UPDATE_C(pg16_first_4, pg32_first_4, ptr_c3, tmp32, tmp16, vc3);

ptr_c0 += 4;
ptr_c1 += 4;
ptr_c2 += 4;
ptr_c3 += 4;
}

if (m & 2) {
ptr_a0 = ptr_a;
ptr_a += 2 * pad_k;

ptr_b0 = ptr_b;
INIT_C(0, 0);
INIT_C(0, 1);
for (BLASLONG p = 0; p < pad_k; p += 8) {
ma0 = svld1_bf16(pg16_all, ptr_a0);
mb0 = svld1_bf16(pg16_all, ptr_b0);
mb1 = svld1_bf16(pg16_all, ptr_b0 + 16);

MATMUL(0, 0);
MATMUL(0, 1);

ptr_a0 += 16;
ptr_b0 += 32;
}

ACCUMULATE_LAST4_TO_FIRST4(0, 0, tmp);
ACCUMULATE_LAST4_TO_FIRST4(0, 1, tmp);

vc0 = svuzp1(mc00, mc00);
vc1 = svuzp2(mc00, mc00);
vc2 = svuzp1(mc01, mc01);
vc3 = svuzp2(mc01, mc01);

UPDATE_C(pg16_first_2, pg32_first_2, ptr_c0, tmp32, tmp16, vc0);
UPDATE_C(pg16_first_2, pg32_first_2, ptr_c1, tmp32, tmp16, vc1);
UPDATE_C(pg16_first_2, pg32_first_2, ptr_c2, tmp32, tmp16, vc2);
UPDATE_C(pg16_first_2, pg32_first_2, ptr_c3, tmp32, tmp16, vc3);

ptr_c0 += 2;
ptr_c1 += 2;
ptr_c2 += 2;
ptr_c3 += 2;
}

if (m & 1) {
ptr_a0 = ptr_a;
ptr_b0 = ptr_b;

INIT_C(0, 0);
INIT_C(0, 1);
for (BLASLONG p = 0; p < pad_k; p += 8) {
ma0 = svld1_bf16(pg16_all, ptr_a0);
mb0 = svld1_bf16(pg16_all, ptr_b0);
mb1 = svld1_bf16(pg16_all, ptr_b0 + 16);

MATMUL(0, 0);
MATMUL(0, 1);

ptr_a0 += 16;
ptr_b0 += 32;
}

ACCUMULATE_LAST4_TO_FIRST4(0, 0, tmp);
ACCUMULATE_LAST4_TO_FIRST4(0, 1, tmp);

// use compact is more straightforward
vc1 = svuzp2(mc00, mc00);
vc3 = svuzp2(mc01, mc01);

UPDATE_C(pg16_first_1, pg32_first_1, ptr_c0, tmp32, tmp16, mc00);
UPDATE_C(pg16_first_1, pg32_first_1, ptr_c1, tmp32, tmp16, vc1);
UPDATE_C(pg16_first_1, pg32_first_1, ptr_c2, tmp32, tmp16, mc01);
UPDATE_C(pg16_first_1, pg32_first_1, ptr_c3, tmp32, tmp16, vc3);
}

ptr_b += 4 * pad_k;
}

if (n & 2) {
ptr_c0 = ptr_c;
ptr_c1 = ptr_c0 + ldc;
ptr_c += 2 * ldc;
ptr_a = (bfloat16_t *)A;

for (BLASLONG i = 0; i < m / 4; i++) {
ptr_a0 = ptr_a;
ptr_a += 4 * pad_k;

ptr_b0 = ptr_b;

INIT_C(0, 0);
INIT_C(1, 0);

for (BLASLONG p = 0; p < pad_k; p += 8) {
ma0 = svld1_bf16(pg16_all, ptr_a0);
ma1 = svld1_bf16(pg16_all, ptr_a0 + 16);

mb0 = svld1_bf16(pg16_all, ptr_b0);

MATMUL(0, 0);
MATMUL(1, 0);

ptr_a0 += 32;
ptr_b0 += 16;
}

ACCUMULATE_LAST4_TO_FIRST4(0, 0, tmp);
ACCUMULATE_LAST4_TO_FIRST4(1, 0, tmp);

ZIP_EVEN_ELEMENTS(pg32_select_first_2_per_quadword, mc00, mc10, tmp, vc0);
ZIP_ODD_ELEMENTS(pg32_select_first_2_per_quadword, mc00, mc10, tmp, vc2);

UPDATE_C(pg16_first_4, pg32_first_4, ptr_c0, tmp32, tmp16, vc0);
UPDATE_C(pg16_first_4, pg32_first_4, ptr_c1, tmp32, tmp16, vc2);

ptr_c0 += 4;
ptr_c1 += 4;
}

if (m & 2) {
ptr_a0 = ptr_a;
ptr_a += 2 * pad_k;
ptr_b0 = ptr_b;

INIT_C(0, 0);

for (BLASLONG p = 0; p < pad_k; p += 8) {
ma0 = svld1_bf16(pg16_all, ptr_a0);
mb0 = svld1_bf16(pg16_all, ptr_b0);

MATMUL(0, 0);

ptr_a0 += 16;
ptr_b0 += 16;
}

ACCUMULATE_LAST4_TO_FIRST4(0, 0, tmp);
vc0 = svuzp1(mc00, mc00);
vc1 = svuzp2(mc00, mc00);

UPDATE_C(pg16_first_2, pg32_first_2, ptr_c0, tmp32, tmp16, vc0);
UPDATE_C(pg16_first_2, pg32_first_2, ptr_c1, tmp32, tmp16, vc1);

ptr_c0 += 2;
ptr_c1 += 2;
}

if (m & 1) {
ptr_a0 = ptr_a;
ptr_b0 = ptr_b;
INIT_C(0, 0);
for (BLASLONG p = 0; p < pad_k; p += 8) {
ma0 = svld1_bf16(pg16_all, ptr_a0);
mb0 = svld1_bf16(pg16_all, ptr_b0);
MATMUL(0, 0);
ptr_a0 += 16;
ptr_b0 += 16;
}

ACCUMULATE_LAST4_TO_FIRST4(0, 0, tmp);
vc1 = svuzp2(mc00, mc00);

UPDATE_C(pg16_first_1, pg32_first_1, ptr_c0, tmp32, tmp16, mc00);
UPDATE_C(pg16_first_1, pg32_first_1, ptr_c1, tmp32, tmp16, vc1);
}

ptr_b += 2 * pad_k;
}

if (n & 1) { // TODO: this case seems a overhead. find out whether it's in our
// case.
ptr_c0 = ptr_c;
ptr_a = (bfloat16_t *)A;

for (BLASLONG i = 0; i < m / 4; i++) {
ptr_a0 = ptr_a;
ptr_a += 4 * pad_k;

ptr_b0 = ptr_b;

INIT_C(0, 0);
INIT_C(1, 0);

for (BLASLONG p = 0; p < pad_k; p += 8) {
ma0 = svld1_bf16(pg16_all, ptr_a0);
ma1 = svld1_bf16(pg16_all, ptr_a0 + 16);

mb0 = svld1_bf16(pg16_all, ptr_b0);

MATMUL(0, 0);
MATMUL(1, 0);

ptr_a0 += 32;
ptr_b0 += 16;
}

ACCUMULATE_LAST4_TO_FIRST4(0, 0, tmp);
ACCUMULATE_LAST4_TO_FIRST4(1, 0, tmp);

ZIP_EVEN_ELEMENTS(pg32_select_first_2_per_quadword, mc00, mc10, tmp, vc0);

UPDATE_C(pg16_first_4, pg32_first_4, ptr_c0, tmp32, tmp16, vc0);

ptr_c0 += 4;
}

if (m & 2) {
ptr_a0 = ptr_a;
ptr_a += 2 * pad_k;
ptr_b0 = ptr_b;

INIT_C(0, 0);

for (BLASLONG p = 0; p < pad_k; p += 8) {
ma0 = svld1_bf16(pg16_all, ptr_a0);
mb0 = svld1_bf16(pg16_all, ptr_b0);

MATMUL(0, 0);

ptr_a0 += 16;
ptr_b0 += 16;
}

ACCUMULATE_LAST4_TO_FIRST4(0, 0, tmp);

vc0 = svuzp1(mc00, mc00);

UPDATE_C(pg16_first_2, pg32_first_2, ptr_c0, tmp32, tmp16, vc0);

ptr_c0 += 2;
}

if (m & 1) {
ptr_a0 = ptr_a;
ptr_b0 = ptr_b;

INIT_C(0, 0);
for (BLASLONG p = 0; p < pad_k; p += 8) {

ma0 = svld1_bf16(pg16_all, ptr_a0);
mb0 = svld1_bf16(pg16_all, ptr_b0);

MATMUL(0, 0);
ptr_a0 += 16;
ptr_b0 += 16;
}

ACCUMULATE_LAST4_TO_FIRST4(0, 0, tmp);

UPDATE_C(pg16_first_1, pg32_first_1, ptr_c0, tmp32, tmp16, mc00);
}
}

return 0;
}

+ 4
- 0
kernel/arm64/dot.c View File

@@ -40,8 +40,12 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endif

#ifdef USE_SVE
#ifdef DOT_KERNEL_SVE
#include DOT_KERNEL_SVE
#else
#include "dot_kernel_sve.c"
#endif
#endif
#include "dot_kernel_asimd.c"

#if defined(SMP)


+ 146
- 0
kernel/arm64/dot_kernel_sve_v8.c View File

@@ -0,0 +1,146 @@
/***************************************************************************
Copyright (c) 2025, 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 <arm_sve.h>
#include "common.h"

#ifdef DOUBLE
#define SV_COUNT svcntd
#define SV_TYPE svfloat64_t
#define SV_TRUE svptrue_b64
#define SV_WHILE svwhilelt_b64_s64
#define SV_DUP svdup_f64
#else
#define SV_COUNT svcntw
#define SV_TYPE svfloat32_t
#define SV_TRUE svptrue_b32
#define SV_WHILE svwhilelt_b32_s64
#define SV_DUP svdup_f32
#endif

static FLOAT dot_kernel_sve(BLASLONG n, FLOAT* x, FLOAT* y)
{
SV_TYPE temp0_vec = SV_DUP(0.0);
SV_TYPE temp1_vec = SV_DUP(0.0);
SV_TYPE temp2_vec = SV_DUP(0.0);
SV_TYPE temp3_vec = SV_DUP(0.0);
SV_TYPE temp4_vec = SV_DUP(0.0);
SV_TYPE temp5_vec = SV_DUP(0.0);
SV_TYPE temp6_vec = SV_DUP(0.0);
SV_TYPE temp7_vec = SV_DUP(0.0);

BLASLONG i = 0;
BLASLONG sve_size = SV_COUNT();

while ((i + sve_size * 8 - 1) < n) {
FLOAT *x0_ptr = x + i;
SV_TYPE x0_vec = svld1_vnum(SV_TRUE(), x0_ptr, 0);
SV_TYPE x1_vec = svld1_vnum(SV_TRUE(), x0_ptr, 1);
SV_TYPE x2_vec = svld1_vnum(SV_TRUE(), x0_ptr, 2);
SV_TYPE x3_vec = svld1_vnum(SV_TRUE(), x0_ptr, 3);
SV_TYPE x4_vec = svld1_vnum(SV_TRUE(), x0_ptr, 4);
SV_TYPE x5_vec = svld1_vnum(SV_TRUE(), x0_ptr, 5);
SV_TYPE x6_vec = svld1_vnum(SV_TRUE(), x0_ptr, 6);
SV_TYPE x7_vec = svld1_vnum(SV_TRUE(), x0_ptr, 7);

FLOAT *y0_ptr = y + i;
SV_TYPE y0_vec = svld1_vnum(SV_TRUE(), y0_ptr, 0);
SV_TYPE y1_vec = svld1_vnum(SV_TRUE(), y0_ptr, 1);
SV_TYPE y2_vec = svld1_vnum(SV_TRUE(), y0_ptr, 2);
SV_TYPE y3_vec = svld1_vnum(SV_TRUE(), y0_ptr, 3);
SV_TYPE y4_vec = svld1_vnum(SV_TRUE(), y0_ptr, 4);
SV_TYPE y5_vec = svld1_vnum(SV_TRUE(), y0_ptr, 5);
SV_TYPE y6_vec = svld1_vnum(SV_TRUE(), y0_ptr, 6);
SV_TYPE y7_vec = svld1_vnum(SV_TRUE(), y0_ptr, 7);

temp0_vec = svmla_x(SV_TRUE(), temp0_vec, x0_vec, y0_vec);
temp1_vec = svmla_x(SV_TRUE(), temp1_vec, x1_vec, y1_vec);
temp2_vec = svmla_x(SV_TRUE(), temp2_vec, x2_vec, y2_vec);
temp3_vec = svmla_x(SV_TRUE(), temp3_vec, x3_vec, y3_vec);
temp4_vec = svmla_x(SV_TRUE(), temp4_vec, x4_vec, y4_vec);
temp5_vec = svmla_x(SV_TRUE(), temp5_vec, x5_vec, y5_vec);
temp6_vec = svmla_x(SV_TRUE(), temp6_vec, x6_vec, y6_vec);
temp7_vec = svmla_x(SV_TRUE(), temp7_vec, x7_vec, y7_vec);

i += sve_size * 8;
}

if (i < n) {
svbool_t pg0 = SV_WHILE(i + sve_size * 0, n);
svbool_t pg1 = SV_WHILE(i + sve_size * 1, n);
svbool_t pg2 = SV_WHILE(i + sve_size * 2, n);
svbool_t pg3 = SV_WHILE(i + sve_size * 3, n);
svbool_t pg4 = SV_WHILE(i + sve_size * 4, n);
svbool_t pg5 = SV_WHILE(i + sve_size * 5, n);
svbool_t pg6 = SV_WHILE(i + sve_size * 6, n);
svbool_t pg7 = SV_WHILE(i + sve_size * 7, n);

FLOAT *x0_ptr = x + i;
SV_TYPE x0_vec = svld1_vnum(pg0, x0_ptr, 0);
SV_TYPE x1_vec = svld1_vnum(pg1, x0_ptr, 1);
SV_TYPE x2_vec = svld1_vnum(pg2, x0_ptr, 2);
SV_TYPE x3_vec = svld1_vnum(pg3, x0_ptr, 3);
SV_TYPE x4_vec = svld1_vnum(pg4, x0_ptr, 4);
SV_TYPE x5_vec = svld1_vnum(pg5, x0_ptr, 5);
SV_TYPE x6_vec = svld1_vnum(pg6, x0_ptr, 6);
SV_TYPE x7_vec = svld1_vnum(pg7, x0_ptr, 7);

FLOAT *y0_ptr = y + i;
SV_TYPE y0_vec = svld1_vnum(pg0, y0_ptr, 0);
SV_TYPE y1_vec = svld1_vnum(pg1, y0_ptr, 1);
SV_TYPE y2_vec = svld1_vnum(pg2, y0_ptr, 2);
SV_TYPE y3_vec = svld1_vnum(pg3, y0_ptr, 3);
SV_TYPE y4_vec = svld1_vnum(pg4, y0_ptr, 4);
SV_TYPE y5_vec = svld1_vnum(pg5, y0_ptr, 5);
SV_TYPE y6_vec = svld1_vnum(pg6, y0_ptr, 6);
SV_TYPE y7_vec = svld1_vnum(pg7, y0_ptr, 7);

temp0_vec = svmla_m(pg0, temp0_vec, x0_vec, y0_vec);
temp1_vec = svmla_m(pg1, temp1_vec, x1_vec, y1_vec);
temp2_vec = svmla_m(pg2, temp2_vec, x2_vec, y2_vec);
temp3_vec = svmla_m(pg3, temp3_vec, x3_vec, y3_vec);
temp4_vec = svmla_m(pg4, temp4_vec, x4_vec, y4_vec);
temp5_vec = svmla_m(pg5, temp5_vec, x5_vec, y5_vec);
temp6_vec = svmla_m(pg6, temp6_vec, x6_vec, y6_vec);
temp7_vec = svmla_m(pg7, temp7_vec, x7_vec, y7_vec);
}

temp0_vec = svadd_x(SV_TRUE(), temp0_vec, temp1_vec);
temp2_vec = svadd_x(SV_TRUE(), temp2_vec, temp3_vec);
temp4_vec = svadd_x(SV_TRUE(), temp4_vec, temp5_vec);
temp6_vec = svadd_x(SV_TRUE(), temp6_vec, temp7_vec);
temp0_vec = svadd_x(SV_TRUE(), temp0_vec, temp2_vec);
temp4_vec = svadd_x(SV_TRUE(), temp4_vec, temp6_vec);
temp0_vec = svadd_x(SV_TRUE(), temp0_vec, temp4_vec);

return svaddv(SV_TRUE(), temp0_vec);
}

+ 34
- 0
kernel/arm64/dot_sve_v8.c View File

@@ -0,0 +1,34 @@
/***************************************************************************
Copyright (c) 2025, 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.
*****************************************************************************/

#define DOT_KERNEL_SVE "dot_kernel_sve_v8.c"
#include "dot.c"

+ 57
- 39
kernel/arm64/gemv_n_sve_v1x3.c View File

@@ -52,17 +52,17 @@ int CNAME(BLASLONG m, BLASLONG n, BLASLONG dummy1, FLOAT alpha, FLOAT *a,
BLASLONG lda, FLOAT *x, BLASLONG inc_x, FLOAT *y, BLASLONG inc_y,
FLOAT *buffer)
{
BLASLONG i;
BLASLONG ix,iy;
BLASLONG j;
FLOAT *a_ptr;
BLASLONG i, j;
BLASLONG ix = 0;
BLASLONG iy;
FLOAT *a_ptr = a;
FLOAT temp;

ix = 0;
a_ptr = a;

if (inc_y == 1) {
BLASLONG width = (n + 3 - 1) / 3;
BLASLONG width = n / 3; // Only process full 3-column blocks
BLASLONG sve_size = SV_COUNT();
svbool_t pg_full = SV_TRUE();
svbool_t pg_tail = SV_WHILE(0, m % sve_size);

FLOAT *a0_ptr = a_ptr + lda * width * 0;
FLOAT *a1_ptr = a_ptr + lda * width * 1;
@@ -73,57 +73,75 @@ int CNAME(BLASLONG m, BLASLONG n, BLASLONG dummy1, FLOAT alpha, FLOAT *a,
FLOAT *x2_ptr = x + inc_x * width * 2;

for (j = 0; j < width; j++) {
svbool_t pg00 = ((j + width * 0) < n) ? SV_TRUE() : svpfalse();
svbool_t pg01 = ((j + width * 1) < n) ? SV_TRUE() : svpfalse();
svbool_t pg02 = ((j + width * 2) < n) ? SV_TRUE() : svpfalse();
SV_TYPE temp0_vec = SV_DUP(alpha * x0_ptr[ix]);
SV_TYPE temp1_vec = SV_DUP(alpha * x1_ptr[ix]);
SV_TYPE temp2_vec = SV_DUP(alpha * x2_ptr[ix]);

SV_TYPE temp0_vec = ((j + width * 0) < n) ? SV_DUP(alpha * x0_ptr[ix]) : SV_DUP(0.0);
SV_TYPE temp1_vec = ((j + width * 1) < n) ? SV_DUP(alpha * x1_ptr[ix]) : SV_DUP(0.0);
SV_TYPE temp2_vec = ((j + width * 2) < n) ? SV_DUP(alpha * x2_ptr[ix]) : SV_DUP(0.0);
i = 0;
BLASLONG sve_size = SV_COUNT();
while ((i + sve_size * 1 - 1) < m) {
SV_TYPE y0_vec = svld1_vnum(SV_TRUE(), y + i, 0);
while ((i + sve_size - 1) < m) {
SV_TYPE y0_vec = svld1(pg_full, y + i);

SV_TYPE a00_vec = svld1_vnum(pg00, a0_ptr + i, 0);
SV_TYPE a01_vec = svld1_vnum(pg01, a1_ptr + i, 0);
SV_TYPE a02_vec = svld1_vnum(pg02, a2_ptr + i, 0);
SV_TYPE a00_vec = svld1(pg_full, a0_ptr + i);
SV_TYPE a01_vec = svld1(pg_full, a1_ptr + i);
SV_TYPE a02_vec = svld1(pg_full, a2_ptr + i);

y0_vec = svmla_m(pg00, y0_vec, temp0_vec, a00_vec);
y0_vec = svmla_m(pg01, y0_vec, temp1_vec, a01_vec);
y0_vec = svmla_m(pg02, y0_vec, temp2_vec, a02_vec);
y0_vec = svmla_x(pg_full, y0_vec, temp0_vec, a00_vec);
y0_vec = svmla_x(pg_full, y0_vec, temp1_vec, a01_vec);
y0_vec = svmla_x(pg_full, y0_vec, temp2_vec, a02_vec);

svst1_vnum(SV_TRUE(), y + i, 0, y0_vec);
i += sve_size * 1;
svst1(pg_full, y + i, y0_vec);
i += sve_size;
}

if (i < m) {
svbool_t pg0 = SV_WHILE(i + sve_size * 0, m);

pg00 = svand_z(SV_TRUE(), pg0, pg00);
pg01 = svand_z(SV_TRUE(), pg0, pg01);
pg02 = svand_z(SV_TRUE(), pg0, pg02);
SV_TYPE y0_vec = svld1(pg_tail, y + i);

SV_TYPE y0_vec = svld1_vnum(pg0, y + i, 0);
SV_TYPE a00_vec = svld1(pg_tail, a0_ptr + i);
SV_TYPE a01_vec = svld1(pg_tail, a1_ptr + i);
SV_TYPE a02_vec = svld1(pg_tail, a2_ptr + i);

SV_TYPE a00_vec = svld1_vnum(pg00, a0_ptr + i, 0);
SV_TYPE a01_vec = svld1_vnum(pg01, a1_ptr + i, 0);
SV_TYPE a02_vec = svld1_vnum(pg02, a2_ptr + i, 0);
y0_vec = svmla_m(pg_tail, y0_vec, temp0_vec, a00_vec);
y0_vec = svmla_m(pg_tail, y0_vec, temp1_vec, a01_vec);
y0_vec = svmla_m(pg_tail, y0_vec, temp2_vec, a02_vec);

y0_vec = svmla_m(pg00, y0_vec, temp0_vec, a00_vec);
y0_vec = svmla_m(pg01, y0_vec, temp1_vec, a01_vec);
y0_vec = svmla_m(pg02, y0_vec, temp2_vec, a02_vec);

svst1_vnum(pg0, y + i, 0, y0_vec);
svst1(pg_tail, y + i, y0_vec);
}
a0_ptr += lda;
a1_ptr += lda;
a2_ptr += lda;
ix += inc_x;
}
// Handle remaining n % 3 columns
for (j = width * 3; j < n; j++) {
FLOAT *a_col = a + j * lda;
temp = alpha * x[j * inc_x];
SV_TYPE temp_vec = SV_DUP(temp);

i = 0;
while ((i + sve_size - 1) < m) {
SV_TYPE y_vec = svld1(pg_full, y + i);

SV_TYPE a_vec = svld1(pg_full, a_col + i);

y_vec = svmla_x(pg_full, y_vec, temp_vec, a_vec);

svst1(pg_full, y + i, y_vec);
i += sve_size;
}
if (i < m) {
SV_TYPE y_vec = svld1(pg_tail, y + i);

SV_TYPE a_vec = svld1(pg_tail, a_col + i);

y_vec = svmla_m(pg_tail, y_vec, temp_vec, a_vec);

svst1(pg_tail, y + i, y_vec);
}
}
return(0);
}

// Fallback scalar loop
for (j = 0; j < n; j++) {
temp = alpha * x[ix];
iy = 0;


+ 199
- 0
kernel/arm64/sgemm_direct_alpha_beta_arm64_sme1.c View File

@@ -0,0 +1,199 @@
/*
Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
SPDX-License-Identifier: BSD-3-Clause-Clear
*/
#include "common.h"
#include <stdlib.h>
#include <inttypes.h>
#include <math.h>
#include "sme_abi.h"
#if defined(HAVE_SME)
#if defined(__ARM_FEATURE_SME) && defined(__clang__) && __clang_major__ >= 16
#include <arm_sme.h>
#endif
/* Function prototypes */
extern void sgemm_direct_sme1_preprocess(uint64_t nbr, uint64_t nbc,\
const float * restrict a, float * a_mod) __asm__("sgemm_direct_sme1_preprocess");
/* Function Definitions */
static uint64_t sve_cntw() {
uint64_t cnt;
asm volatile(
"rdsvl %[res], #1\n"
"lsr %[res], %[res], #2\n"
: [res] "=r" (cnt) ::
);
return cnt;
}
#if defined(__ARM_FEATURE_SME) && defined(__ARM_FEATURE_LOCALLY_STREAMING) && defined(__clang__) && __clang_major__ >= 16
// Outer product kernel.
// Computes a 2SVL x 2SVL block of C, utilizing all four FP32 tiles of ZA.
__attribute__((always_inline)) inline void
kernel_2x2(const float *A, const float *B, float *C, size_t shared_dim,
size_t ldc, size_t block_rows, size_t block_cols, float alpha, float beta)
__arm_out("za") __arm_streaming {
const uint64_t svl = svcntw();
size_t ldb = ldc;
// Predicate set-up
svbool_t pg = svptrue_b32();
svbool_t pg_a_0 = svwhilelt_b32_u64(0, block_rows);
svbool_t pg_a_1 = svwhilelt_b32_u64(svl, block_rows);
svbool_t pg_b_0 = svwhilelt_b32_u64(0, block_cols);
svbool_t pg_b_1 = svwhilelt_b32_u64(svl, block_cols);
#define pg_c_0 pg_b_0
#define pg_c_1 pg_b_1
svzero_za();
svfloat32_t beta_vec = svdup_f32(beta);
// Load C to ZA
for (size_t i = 0; i < MIN(svl, block_rows); i++) {
svfloat32_t row_c_0 = svld1(pg_c_0, &C[i * ldc]);
row_c_0 = svmul_x(pg, beta_vec, row_c_0);
svwrite_hor_za32_f32_m(/*tile*/0, /*slice*/i, pg_c_0, row_c_0);
svfloat32_t row_c_1 = svld1(pg_c_1, &C[i * ldc + svl]);
row_c_1 = svmul_x(pg, beta_vec, row_c_1);
svwrite_hor_za32_f32_m(/*tile*/1, /*slice*/i, pg_c_1, row_c_1);
}
for (size_t i = svl; i < block_rows; i++) {
svfloat32_t row_c_0 = svld1(pg_c_0, &C[i * ldc]);
row_c_0 = svmul_x(pg, beta_vec, row_c_0);
svwrite_hor_za32_f32_m(/*tile*/2, /*slice*/i, pg_c_0, row_c_0);
svfloat32_t row_c_1 = svld1(pg_c_1, &C[i * ldc + svl]);
row_c_1 = svmul_x(pg, beta_vec, row_c_1);
svwrite_hor_za32_f32_m(/*tile*/3, /*slice*/i, pg_c_1, row_c_1);
}
svfloat32_t alpha_vec = svdup_f32(alpha);
// Iterate through shared dimension (K)
for (size_t k = 0; k < shared_dim; k++) {
// Load column of A
svfloat32_t col_a_0 = svld1(pg_a_0, &A[k * svl]);
col_a_0 = svmul_x(pg, alpha_vec, col_a_0);
svfloat32_t col_a_1 = svld1(pg_a_1, &A[(k + shared_dim) * svl]);
col_a_1 = svmul_x(pg, alpha_vec, col_a_1);
// Load row of B
svfloat32_t row_b_0 = svld1(pg_b_0, &B[k * ldb]);
svfloat32_t row_b_1 = svld1(pg_b_1, &B[k * ldb + svl]);
// Perform outer product
svmopa_za32_m(/*tile*/0, pg, pg, col_a_0, row_b_0);
svmopa_za32_m(/*tile*/1, pg, pg, col_a_0, row_b_1);
svmopa_za32_m(/*tile*/2, pg, pg, col_a_1, row_b_0);
svmopa_za32_m(/*tile*/3, pg, pg, col_a_1, row_b_1);
}
// Store to C from ZA
for (size_t i = 0; i < MIN(svl, block_rows); i++) {
svst1_hor_za32(/*tile*/0, /*slice*/i, pg_c_0, &C[i * ldc]);
svst1_hor_za32(/*tile*/1, /*slice*/i, pg_c_1, &C[i * ldc + svl]);
}
for (size_t i = svl; i < block_rows; i++) {
svst1_hor_za32(/*tile*/2, /*slice*/i, pg_c_0, &C[i * ldc]);
svst1_hor_za32(/*tile*/3, /*slice*/i, pg_c_1, &C[i * ldc + svl]);
}
}
__arm_new("za") __arm_locally_streaming
void sgemm_direct_alpha_beta_sme1_2VLx2VL(uint64_t m, uint64_t k, uint64_t n, const float* alpha,\
const float *ba, const float *restrict bb, const float* beta,\
float *restrict C) {
const uint64_t num_rows = m;
const uint64_t num_cols = n;
const float *restrict a_ptr = ba;
const float *restrict b_ptr = bb;
float *restrict c_ptr = C;
const uint64_t svl = svcntw();
const uint64_t ldc = n;
// Block over rows of C (panels of A)
uint64_t row_idx = 0;
// 2x2 loop
uint64_t row_batch = 2*svl;
// Block over row dimension of C
for (; row_idx < num_rows; row_idx += row_batch) {
row_batch = MIN(row_batch, num_rows - row_idx);
uint64_t col_idx = 0;
uint64_t col_batch = 2*svl;
// Block over column dimension of C
for (; col_idx < num_cols; col_idx += col_batch) {
col_batch = MIN(col_batch, num_cols - col_idx);
kernel_2x2(&a_ptr[row_idx * k], &b_ptr[col_idx],
&c_ptr[row_idx * ldc + col_idx], k,
ldc, row_batch, col_batch, *alpha, *beta);
}
}
return;
}
#else
void sgemm_direct_alpha_beta_sme1_2VLx2VL(uint64_t m, uint64_t k, uint64_t n, const float* alpha,\
const float *ba, const float *restrict bb, const float* beta,\
float *restrict C){}
#endif
/*void sgemm_kernel_direct (BLASLONG M, BLASLONG N, BLASLONG K,\
float * __restrict A, BLASLONG strideA, float * __restrict B,\
BLASLONG strideB , float * __restrict R, BLASLONG strideR)
*/
void CNAME (BLASLONG M, BLASLONG N, BLASLONG K, float alpha, float * __restrict A,\
BLASLONG strideA, float * __restrict B, BLASLONG strideB ,\
float beta, float * __restrict R, BLASLONG strideR){
uint64_t m_mod, vl_elms;
vl_elms = sve_cntw();
m_mod = ceil((double)M/(double)vl_elms) * vl_elms;
float *A_mod = (float *) malloc(m_mod*K*sizeof(float));
/* Prevent compiler optimization by reading from memory instead
* of reading directly from vector (z) registers.
* */
asm volatile("" : : :"p0", "p1", "p2", "p3", "p4", "p5", "p6", "p7",
"p8", "p9", "p10", "p11", "p12", "p13", "p14", "p15",
"z0", "z1", "z2", "z3", "z4", "z5", "z6", "z7",
"z8", "z9", "z10", "z11", "z12", "z13", "z14", "z15",
"z16", "z17", "z18", "z19", "z20", "z21", "z22", "z23",
"z24", "z25", "z26", "z27", "z28", "z29", "z30", "z31");
/* Pre-process the left matrix to make it suitable for
matrix sum of outer-product calculation
*/
sgemm_direct_sme1_preprocess(M, K, A, A_mod);
asm volatile("" : : :"p0", "p1", "p2", "p3", "p4", "p5", "p6", "p7",
"p8", "p9", "p10", "p11", "p12", "p13", "p14", "p15",
"z0", "z1", "z2", "z3", "z4", "z5", "z6", "z7",
"z8", "z9", "z10", "z11", "z12", "z13", "z14", "z15",
"z16", "z17", "z18", "z19", "z20", "z21", "z22", "z23",
"z24", "z25", "z26", "z27", "z28", "z29", "z30", "z31");
/* Calculate C = alpha*A*B + beta*C */
sgemm_direct_alpha_beta_sme1_2VLx2VL(M, K, N, &alpha, A_mod, B, &beta, R);
free(A_mod);
}
#else
void CNAME (BLASLONG M, BLASLONG N, BLASLONG K, float alpha, float * __restrict A,\
BLASLONG strideA, float * __restrict B, BLASLONG strideB ,\
float beta, float * __restrict R, BLASLONG strideR){}
#endif

+ 46
- 0
kernel/arm64/sme_abi.h View File

@@ -0,0 +1,46 @@
/***************************************************************************
* Copyright (c) 2024, 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.
* *****************************************************************************/

#pragma once

#include <stdlib.h>

/**
* * These are SME ABI routines for saving & restoring SME state.
* * They are typically provided by a compiler runtime library such
* * as libgcc or compiler-rt, but support for these routines is not
* * yet available on all platforms.
* *
* * Define these as aborting stubs so that we loudly fail on nested
* * usage of SME state.
* *
* * These are defined as weak symbols so that a compiler runtime can
* * override them if supported.
* */
__attribute__((weak)) void __arm_tpidr2_save() { abort(); }
__attribute__((weak)) void __arm_tpidr2_restore() { abort(); }


+ 64
- 0
kernel/generic/bf16_macros.h View File

@@ -0,0 +1,64 @@
/***************************************************************************
* Copyright (c) 2025, 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.
* *****************************************************************************/

#if defined(BFLOAT16) && defined(BFLOAT16CONVERSION)
static float
bfloat16tof32 (bfloat16 value)
{
blasint one = 1;
float result;
sbf16tos_(&one, &value, &one, &result, &one);
return result;
}

#ifdef BGEMM
static bfloat16 f32tobfloat16(float value) {
blasint one = 1;
bfloat16 result;
sbstobf16_(&one, &value, &one, &result, &one);
return result;
}
#endif

#ifdef BGEMM
#define ALPHA bfloat16tof32(alpha)
#define BETA bfloat16tof32(beta)
#define BF16TOF32(x) (bfloat16tof32(x))
#define F32TOBF16(x) (f32tobfloat16(x))
#else
#define ALPHA alpha
#define BETA beta
#define BF16TOF32(x) (bfloat16tof32(x))
#define F32TOBF16(x) x
#endif
#else
#define ALPHA alpha
#define BETA beta
#define BF16TOF32(x) x
#define F32TOBF16(x) x
#endif

+ 50
- 19
kernel/generic/gemm_beta.c View File

@@ -1,5 +1,6 @@
/*********************************************************************/
/* Copyright 2009, 2010 The University of Texas at Austin. */
/* Copyright 2025 The OpenBLAS Project. */
/* All rights reserved. */
/* */
/* Redistribution and use in source and binary forms, with or */
@@ -38,11 +39,41 @@

#include "common.h"

#if defined(BFLOAT16) && defined(BGEMM) && defined(BFLOAT16CONVERSION)
static float
bfloat16tof32 (bfloat16 f16)
{
float result = 0;
unsigned short* q = (unsigned short*)(&result);
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
q[0] = f16;
#else
q[1] = f16;
#endif
return result;
}
static bfloat16
f32tobfloat16(float f32)
{
unsigned short* q = (unsigned short*)(&f32);
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
return q[0];
#else
return q[1];
#endif
}

#define BF16TOF32(x) (bfloat16tof32(x))
#define F32TOBF16(x) (f32tobfloat16(x))
#else
#define BF16TOF32(x) x
#define F32TOBF16(x) x
#endif

int CNAME(BLASLONG m, BLASLONG n, BLASLONG dummy1, FLOAT beta,
IFLOAT *dummy2, BLASLONG dummy3, IFLOAT *dummy4, BLASLONG dummy5,
FLOAT *c, BLASLONG ldc){


BLASLONG i, j;
BLASLONG chunk, remain;
FLOAT *c_offset1, *c_offset;
@@ -54,18 +85,18 @@ int CNAME(BLASLONG m, BLASLONG n, BLASLONG dummy1, FLOAT beta,
c_offset1 = c_offset;
c_offset += ldc;
for(i=chunk; i>0; i--){
*(c_offset1 + 0) = ZERO;
*(c_offset1 + 1) = ZERO;
*(c_offset1 + 2) = ZERO;
*(c_offset1 + 3) = ZERO;
*(c_offset1 + 4) = ZERO;
*(c_offset1 + 5) = ZERO;
*(c_offset1 + 6) = ZERO;
*(c_offset1 + 7) = ZERO;
*(c_offset1 + 0) = F32TOBF16(ZERO);
*(c_offset1 + 1) = F32TOBF16(ZERO);
*(c_offset1 + 2) = F32TOBF16(ZERO);
*(c_offset1 + 3) = F32TOBF16(ZERO);
*(c_offset1 + 4) = F32TOBF16(ZERO);
*(c_offset1 + 5) = F32TOBF16(ZERO);
*(c_offset1 + 6) = F32TOBF16(ZERO);
*(c_offset1 + 7) = F32TOBF16(ZERO);
c_offset1 += 8;
}
for(i=remain; i>0; i--){
*c_offset1 = ZERO;
*c_offset1 = F32TOBF16(ZERO);
c_offset1 ++;
}
}
@@ -74,18 +105,18 @@ int CNAME(BLASLONG m, BLASLONG n, BLASLONG dummy1, FLOAT beta,
c_offset1 = c_offset;
c_offset += ldc;
for(i=chunk; i>0; i--){
*(c_offset1 + 0) *= beta;
*(c_offset1 + 1) *= beta;
*(c_offset1 + 2) *= beta;
*(c_offset1 + 3) *= beta;
*(c_offset1 + 4) *= beta;
*(c_offset1 + 5) *= beta;
*(c_offset1 + 6) *= beta;
*(c_offset1 + 7) *= beta;
*(c_offset1 + 0) = F32TOBF16(BF16TOF32(beta) * BF16TOF32(c_offset1[0]));
*(c_offset1 + 1) = F32TOBF16(BF16TOF32(beta) * BF16TOF32(c_offset1[1]));
*(c_offset1 + 2) = F32TOBF16(BF16TOF32(beta) * BF16TOF32(c_offset1[2]));
*(c_offset1 + 3) = F32TOBF16(BF16TOF32(beta) * BF16TOF32(c_offset1[3]));
*(c_offset1 + 4) = F32TOBF16(BF16TOF32(beta) * BF16TOF32(c_offset1[4]));
*(c_offset1 + 5) = F32TOBF16(BF16TOF32(beta) * BF16TOF32(c_offset1[5]));
*(c_offset1 + 6) = F32TOBF16(BF16TOF32(beta) * BF16TOF32(c_offset1[6]));
*(c_offset1 + 7) = F32TOBF16(BF16TOF32(beta) * BF16TOF32(c_offset1[7]));
c_offset1 += 8;
}
for(i=remain; i>0; i--){
*c_offset1 *= beta;
*c_offset1 = F32TOBF16(BF16TOF32(beta) * BF16TOF32(c_offset1[0]));
c_offset1 ++;
}
}


+ 52
- 35
kernel/generic/gemmkernel_2x2.c View File

@@ -1,21 +1,34 @@
/***************************************************************************
* Copyright (c) 2025, 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 "common.h"
#if defined(BFLOAT16) && defined(BFLOAT16CONVERSION)
static float
bfloat16tof32 (bfloat16 f16)
{
float result = 0;
unsigned short* q = (unsigned short*)(&result);
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
q[0] = f16;
#else
q[1] = f16;
#endif
return result;
}
#define BF16TOF32(x) (bfloat16tof32(x))
#else
#define BF16TOF32(x) x
#endif
#include "bf16_macros.h"

int CNAME(BLASLONG bm,BLASLONG bn,BLASLONG bk,FLOAT alpha,IFLOAT* ba,IFLOAT* bb,FLOAT* C,BLASLONG ldc
#ifdef TRMMKERNEL
,BLASLONG offset
@@ -25,7 +38,11 @@ int CNAME(BLASLONG bm,BLASLONG bn,BLASLONG bk,FLOAT alpha,IFLOAT* ba,IFLOAT* bb,
BLASLONG i,j,k;
FLOAT *C0,*C1;
IFLOAT *ptrba,*ptrbb;
#ifdef BGEMM
float res0,res1,res2,res3;
#else
FLOAT res0,res1,res2,res3;
#endif
IFLOAT load0,load1,load2,load3,load4,load5,load6,load7;
for (j=0; j<bn/2; j+=1)
{
@@ -89,14 +106,14 @@ int CNAME(BLASLONG bm,BLASLONG bn,BLASLONG bk,FLOAT alpha,IFLOAT* ba,IFLOAT* bb,
ptrba = ptrba+2;
ptrbb = ptrbb+2;
}
res0 = res0*alpha;
C0[0] = C0[0]+res0;
res1 = res1*alpha;
C0[1] = C0[1]+res1;
res2 = res2*alpha;
C1[0] = C1[0]+res2;
res3 = res3*alpha;
C1[1] = C1[1]+res3;
res0 = res0*ALPHA;
C0[0] = F32TOBF16(BF16TOF32(C0[0])+res0);
res1 = res1*ALPHA;
C0[1] = F32TOBF16(BF16TOF32(C0[1])+res1);
res2 = res2*ALPHA;
C1[0] = F32TOBF16(BF16TOF32(C1[0])+res2);
res3 = res3*ALPHA;
C1[1] = F32TOBF16(BF16TOF32(C1[1])+res3);
C0 = C0+2;
C1 = C1+2;
}
@@ -115,10 +132,10 @@ int CNAME(BLASLONG bm,BLASLONG bn,BLASLONG bk,FLOAT alpha,IFLOAT* ba,IFLOAT* bb,
ptrba = ptrba+1;
ptrbb = ptrbb+2;
}
res0 = res0*alpha;
C0[0] = C0[0]+res0;
res1 = res1*alpha;
C1[0] = C1[0]+res1;
res0 = res0*ALPHA;
C0[0] = F32TOBF16(BF16TOF32(C0[0])+res0);
res1 = res1*ALPHA;
C1[0] = F32TOBF16(BF16TOF32(C1[0])+res1);
C0 = C0+1;
C1 = C1+1;
}
@@ -146,10 +163,10 @@ int CNAME(BLASLONG bm,BLASLONG bn,BLASLONG bk,FLOAT alpha,IFLOAT* ba,IFLOAT* bb,
ptrba = ptrba+2;
ptrbb = ptrbb+1;
}
res0 = res0*alpha;
C0[0] = C0[0]+res0;
res1 = res1*alpha;
C0[1] = C0[1]+res1;
res0 = res0*ALPHA;
C0[0] = F32TOBF16(BF16TOF32(C0[0])+res0);
res1 = res1*ALPHA;
C0[1] = F32TOBF16(BF16TOF32(C0[1])+res1);
C0 = C0+2;
}
for (i=0; i<(bm&1); i+=1)
@@ -164,8 +181,8 @@ int CNAME(BLASLONG bm,BLASLONG bn,BLASLONG bk,FLOAT alpha,IFLOAT* ba,IFLOAT* bb,
ptrba = ptrba+1;
ptrbb = ptrbb+1;
}
res0 = res0*alpha;
C0[0] = C0[0]+res0;
res0 = res0*ALPHA;
C0[0] = F32TOBF16(BF16TOF32(C0[0])+res0);
C0 = C0+1;
}
k = (bk<<0);


+ 70
- 0
kernel/generic/gemv_n.c View File

@@ -0,0 +1,70 @@
/***************************************************************************
Copyright (c) 2013-2014, 2025 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 "common.h"
#include "bf16_macros.h"

int CNAME(BLASLONG m, BLASLONG n, FLOAT alpha, IFLOAT *a, BLASLONG lda, IFLOAT *x, BLASLONG inc_x, FLOAT beta, FLOAT *y, BLASLONG inc_y)
{
BLASLONG i;
BLASLONG ix, iy;
BLASLONG j;
FLOAT *a_ptr;
#ifdef BGEMM
float temp;
#else
FLOAT temp;
#endif

iy = 0;
for (BLASLONG i = 0; i < m; i++)
{
temp = 0.0;

ix = 0;
a_ptr = a;
for (BLASLONG j = 0; j < n; j++)
{
temp += BF16TOF32(a_ptr[i]) * BF16TOF32(x[ix]);
ix += inc_x;
a_ptr += lda;
}

if (BETA == ZERO)
{
y[iy] = F32TOBF16(ALPHA * temp);
}
else
{
y[iy] = F32TOBF16(ALPHA * temp + BETA * BF16TOF32(y[iy]));
}

iy += inc_y;
}

return (0);
}

+ 60
- 0
kernel/generic/gemv_t.c View File

@@ -0,0 +1,60 @@
/***************************************************************************
Copyright (c) 2013, 2025 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 "common.h"
#include "bf16_macros.h"

int CNAME(BLASLONG m, BLASLONG n, FLOAT alpha, IFLOAT *a, BLASLONG lda, IFLOAT *x, BLASLONG inc_x, FLOAT beta, FLOAT *y, BLASLONG inc_y)
{
BLASLONG i;
BLASLONG ix, iy;
BLASLONG j;
FLOAT *a_ptr;
#ifdef BGEMM
float temp;
#else
FLOAT temp;
#endif

iy = 0;
a_ptr = a;

for (j = 0; j < n; j++)
{
temp = 0.0;
ix = 0;
for (i = 0; i < m; i++)
{
temp += BF16TOF32(a_ptr[i]) * BF16TOF32(x[ix]);
ix += inc_x;
}
y[iy] += F32TOBF16(ALPHA * temp);
iy += inc_y;
a_ptr += lda;
}
return (0);
}

+ 106
- 0
kernel/generic/scal.c View File

@@ -0,0 +1,106 @@
/***************************************************************************
Copyright (c) 2013, 2025 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 "common.h"

int CNAME(BLASLONG n, BLASLONG dummy0, BLASLONG dummy1, FLOAT da, FLOAT *x, BLASLONG inc_x, FLOAT *y, BLASLONG inc_y, FLOAT *dummy, BLASLONG dummy2)
{
BLASLONG i = 0, j = 0;
#if defined(BFLOAT16)
float x_float, da_float;
SBF16TOS_K(1, &da, 1, &da_float, 1);
#else
float x_float;
float da_float = da;
#endif

if ((n <= 0) || (inc_x <= 0))
return (0);

if (dummy2 == 0)
{
while (j < n)
{

if (da_float == 0.0)
x_float = 0.0;
else
{
#if defined(BFLOAT16)
SBF16TOS_K(1, &x[i], 1, &x_float, 1);
#else
float x_float = x[i];
#endif
x_float = da_float * x_float;
}

#if defined(BFLOAT16)
SBSTOBF16_K(1, &x_float, 1, &x[i], 1);
#else
x[i] = x_float;
#endif

i += inc_x;
j++;
}
}
else
{

while (j < n)
{
#if defined(BFLOAT16)
SBF16TOS_K(1, &x[i], 1, &x_float, 1);
#else
float x_float = x[i];
#endif
if (da == 0.0)
if (!isnan(x_float) && !isinf(x_float))
{
x_float = 0.0;
}
else
{
x_float = NAN;
}
else
{
x_float = da_float * x_float;
}

#if defined(BFLOAT16)
SBSTOBF16_K(1, &x_float, 1, &x[i], 1);
#else
x[i] = x_float;
#endif

i += inc_x;
j++;
}
}
return 0;
}

+ 42
- 3
kernel/setparam-ref.c View File

@@ -1,6 +1,6 @@
/*********************************************************************/
/* Copyright 2009, 2010 The University of Texas at Austin. */
/* Copyright 2023 The OpenBLAS Project. */
/* Copyright 2023, 2025 The OpenBLAS Project. */
/* All rights reserved. */
/* */
/* Redistribution and use in source and binary forms, with or */
@@ -57,6 +57,15 @@ gotoblas_t TABLE_NAME = {
GEMM_DEFAULT_OFFSET_A, GEMM_DEFAULT_OFFSET_B, GEMM_DEFAULT_ALIGN,

#ifdef BUILD_BFLOAT16
0, 0, 0,
BGEMM_DEFAULT_UNROLL_M, BGEMM_DEFAULT_UNROLL_N,
#ifdef BGEMM_DEFAULT_UNROLL_MN
BGEMM_DEFAULT_UNROLL_MN,
#else
MAX(BGEMM_DEFAULT_UNROLL_M, BGEMM_DEFAULT_UNROLL_N),
#endif
BGEMM_ALIGN_K,

0, 0, 0,
SBGEMM_DEFAULT_UNROLL_M, SBGEMM_DEFAULT_UNROLL_N,
#ifdef SBGEMM_DEFAULT_UNROLL_MN
@@ -74,10 +83,18 @@ gotoblas_t TABLE_NAME = {
isamax_kTS, isamin_kTS, ismax_kTS, ismin_kTS,
snrm2_kTS, sasum_kTS, ssum_kTS, scopy_kTS, sbdot_kTS,
dsdot_kTS,
srot_kTS, srotm_kTS, saxpy_kTS, sscal_kTS, sswap_kTS,
sbgemv_nTS, sbgemv_tTS, sger_kTS,
srot_kTS, srotm_kTS, bscal_kTS, saxpy_kTS, sscal_kTS, sswap_kTS,
bgemv_nTS, bgemv_tTS, sbgemv_nTS, sbgemv_tTS, sger_kTS,
ssymv_LTS, ssymv_UTS,

bgemm_kernelTS, bgemm_betaTS,
#if BGEMM_DEFAULT_UNROLL_M != BGEMM_DEFAULT_UNROLL_N
bgemm_incopyTS, bgemm_itcopyTS,
#else
bgemm_oncopyTS, bgemm_otcopyTS,
#endif
bgemm_oncopyTS, bgemm_otcopyTS,

sbgemm_kernelTS, sbgemm_betaTS,
#if SBGEMM_DEFAULT_UNROLL_M != SBGEMM_DEFAULT_UNROLL_N
sbgemm_incopyTS, sbgemm_itcopyTS,
@@ -198,6 +215,7 @@ gotoblas_t TABLE_NAME = {
#endif
#ifdef ARCH_ARM64
sgemm_directTS,
sgemm_direct_alpha_betaTS,
#endif

sgemm_kernelTS, sgemm_betaTS,
@@ -913,6 +931,7 @@ gotoblas_t TABLE_NAME = {
static void init_parameter(void) {
#if (BUILD_BFLOAT16)
TABLE_NAME.sbgemm_p = SBGEMM_DEFAULT_P;
TABLE_NAME.bgemm_p = BGEMM_DEFAULT_P;
#endif
#if (BUILD_SINGLE==1) || (BUILD_COMPLEX==1)
TABLE_NAME.sgemm_p = SGEMM_DEFAULT_P;
@@ -929,6 +948,7 @@ static void init_parameter(void) {

#if (BUILD_BFLOAT16)
TABLE_NAME.sbgemm_q = SBGEMM_DEFAULT_Q;
TABLE_NAME.bgemm_q = BGEMM_DEFAULT_Q;
#endif
#if BUILD_SINGLE == 1 || (BUILD_COMPLEX==1)
TABLE_NAME.sgemm_q = SGEMM_DEFAULT_Q;
@@ -945,6 +965,7 @@ static void init_parameter(void) {

#if (BUILD_BFLOAT16)
TABLE_NAME.sbgemm_r = SBGEMM_DEFAULT_R;
TABLE_NAME.bgemm_r = BGEMM_DEFAULT_R;
#endif
#if BUILD_SINGLE == 1 || (BUILD_COMPLEX==1)
TABLE_NAME.sgemm_r = SGEMM_DEFAULT_R;
@@ -1100,10 +1121,12 @@ static void init_parameter(void) {

#ifdef BUILD_BFLOAT16
TABLE_NAME.sbgemm_p = SBGEMM_DEFAULT_P;
TABLE_NAME.bgemm_p = BGEMM_DEFAULT_P;
#endif

#ifdef BUILD_BFLOAT16
TABLE_NAME.sbgemm_r = SBGEMM_DEFAULT_R;
TABLE_NAME.bgemm_r = BGEMM_DEFAULT_R;
#endif

#if defined(LA464)
@@ -1202,6 +1225,7 @@ static void init_parameter(void) {

#ifdef BUILD_BFLOAT16
TABLE_NAME.sbgemm_q = SBGEMM_DEFAULT_Q;
TABLE_NAME.bgemm_q = BGEMM_DEFAULT_Q;
#endif
}
#else // (ARCH_LOONGARCH64)
@@ -1210,6 +1234,7 @@ static void init_parameter(void) {

#ifdef BUILD_BFLOAT16
TABLE_NAME.sbgemm_p = SBGEMM_DEFAULT_P;
TABLE_NAME.bgemm_p = BGEMM_DEFAULT_P;
#endif
TABLE_NAME.sgemm_p = SGEMM_DEFAULT_P;
TABLE_NAME.dgemm_p = DGEMM_DEFAULT_P;
@@ -1218,6 +1243,7 @@ static void init_parameter(void) {

#ifdef BUILD_BFLOAT16
TABLE_NAME.sbgemm_r = SBGEMM_DEFAULT_R;
TABLE_NAME.bgemm_r = BGEMM_DEFAULT_R;
#endif
TABLE_NAME.sgemm_r = SGEMM_DEFAULT_R;
TABLE_NAME.dgemm_r = DGEMM_DEFAULT_R;
@@ -1227,6 +1253,7 @@ static void init_parameter(void) {

#ifdef BUILD_BFLOAT16
TABLE_NAME.sbgemm_q = SBGEMM_DEFAULT_Q;
TABLE_NAME.bgemm_q = BGEMM_DEFAULT_Q;
#endif
TABLE_NAME.sgemm_q = SGEMM_DEFAULT_Q;
TABLE_NAME.dgemm_q = DGEMM_DEFAULT_Q;
@@ -1239,6 +1266,7 @@ static void init_parameter(void) {
static void init_parameter(void) {
#ifdef BUILD_BFLOAT16
TABLE_NAME.sbgemm_p = SBGEMM_DEFAULT_P;
TABLE_NAME.bgemm_p = BGEMM_DEFAULT_P;
#endif
TABLE_NAME.sgemm_p = SGEMM_DEFAULT_P;
TABLE_NAME.dgemm_p = DGEMM_DEFAULT_P;
@@ -1247,6 +1275,7 @@ static void init_parameter(void) {

#ifdef BUILD_BFLOAT16
TABLE_NAME.sbgemm_r = SBGEMM_DEFAULT_R;
TABLE_NAME.bgemm_r = BGEMM_DEFAULT_R;
#endif
TABLE_NAME.sgemm_r = SGEMM_DEFAULT_R;
TABLE_NAME.dgemm_r = DGEMM_DEFAULT_R;
@@ -1256,6 +1285,7 @@ static void init_parameter(void) {

#ifdef BUILD_BFLOAT16
TABLE_NAME.sbgemm_q = SBGEMM_DEFAULT_Q;
TABLE_NAME.bgemm_q = BGEMM_DEFAULT_Q;
#endif
TABLE_NAME.sgemm_q = SGEMM_DEFAULT_Q;
TABLE_NAME.dgemm_q = DGEMM_DEFAULT_Q;
@@ -1269,6 +1299,7 @@ static void init_parameter(void) {

#ifdef BUILD_BFLOAT16
TABLE_NAME.sbgemm_p = SBGEMM_DEFAULT_P;
TABLE_NAME.bgemm_p = BGEMM_DEFAULT_P;
#endif
#ifdef BUILD_HFLOAT16
TABLE_NAME.shgemm_p = SHGEMM_DEFAULT_P;
@@ -1280,6 +1311,7 @@ static void init_parameter(void) {

#ifdef BUILD_BFLOAT16
TABLE_NAME.sbgemm_r = SBGEMM_DEFAULT_R;
TABLE_NAME.bgemm_r = BGEMM_DEFAULT_R;
#endif
#ifdef BUILD_HFLOAT16
TABLE_NAME.shgemm_r = SHGEMM_DEFAULT_R;
@@ -1292,6 +1324,7 @@ static void init_parameter(void) {

#ifdef BUILD_BFLOAT16
TABLE_NAME.sbgemm_q = SBGEMM_DEFAULT_Q;
TABLE_NAME.bgemm_q = BGEMM_DEFAULT_Q;
#endif
#ifdef BUILD_HFLOAT16
TABLE_NAME.shgemm_q = SHGEMM_DEFAULT_Q;
@@ -1442,6 +1475,8 @@ static void init_parameter(void) {
#ifdef BUILD_BFLOAT16
TABLE_NAME.sbgemm_p = SBGEMM_DEFAULT_P;
TABLE_NAME.sbgemm_q = SBGEMM_DEFAULT_Q;
TABLE_NAME.bgemm_p = BGEMM_DEFAULT_P;
TABLE_NAME.bgemm_q = BGEMM_DEFAULT_Q;
#endif
#ifdef BUILD_HFLOAT16
TABLE_NAME.shgemm_p = SHGEMM_DEFAULT_P;
@@ -2040,6 +2075,10 @@ static void init_parameter(void) {
((TABLE_NAME.sbgemm_p * TABLE_NAME.sbgemm_q * 4 + TABLE_NAME.offsetA
+ TABLE_NAME.align) & ~TABLE_NAME.align)
) / (TABLE_NAME.sbgemm_q * 4) - 15) & ~15);
TABLE_NAME.bgemm_r = (((BUFFER_SIZE -
((TABLE_NAME.bgemm_p * TABLE_NAME.bgemm_q * 4 + TABLE_NAME.offsetA
+ TABLE_NAME.align) & ~TABLE_NAME.align)
) / (TABLE_NAME.bgemm_q * 4) - 15) & ~15);
#endif

#if BUILD_HFLOAT16==1


+ 6
- 0
lapack-netlib/LAPACKE/src/lapacke_dtrsen.c View File

@@ -78,6 +78,12 @@ lapack_int LAPACKE_dtrsen( int matrix_layout, char job, char compq,
info = LAPACK_WORK_MEMORY_ERROR;
goto exit_level_0;
}
} else {
iwork = (lapack_int*)LAPACKE_malloc( sizeof(lapack_int) );
if( iwork == NULL ) {
info = LAPACK_WORK_MEMORY_ERROR;
goto exit_level_0;
}
}
work = (double*)LAPACKE_malloc( sizeof(double) * lwork );
if( work == NULL ) {


+ 7
- 0
lapack-netlib/LAPACKE/src/lapacke_strsen.c View File

@@ -77,7 +77,14 @@ lapack_int LAPACKE_strsen( int matrix_layout, char job, char compq,
info = LAPACK_WORK_MEMORY_ERROR;
goto exit_level_0;
}
} else {
iwork = (lapack_int*)LAPACKE_malloc( sizeof(lapack_int) );
if( iwork == NULL ) {
info = LAPACK_WORK_MEMORY_ERROR;
goto exit_level_0;
}
}

work = (float*)LAPACKE_malloc( sizeof(float) * lwork );
if( work == NULL ) {
info = LAPACK_WORK_MEMORY_ERROR;


+ 1
- 1
lapack/CMakeLists.txt View File

@@ -52,7 +52,7 @@ GenerateNamedObjects("laswp/generic/laswp_k_4.c" "" "laswp_plus" false "" "" fa
GenerateNamedObjects("laswp/generic/laswp_k_4.c" "MINUS" "laswp_minus" false "" "" false 3)

foreach (float_type ${FLOAT_TYPES})
if (${float_type} STREQUAL "HALF")
if (${float_type} STREQUAL "BFLOAT16")
continue()
endif()
GenerateNamedObjects("getrf/getrf_single.c" "UNIT" "getrf_single" false "" "" false ${float_type})


+ 3
- 2
lapack/potrf/potrf_parallel.c View File

@@ -1,5 +1,6 @@
/*********************************************************************/
/* Copyright 2009, 2010 The University of Texas at Austin. */
/* Copyright 2025 The OpenBLAS Project. */
/* All rights reserved. */
/* */
/* Redistribution and use in source and binary forms, with or */
@@ -405,8 +406,8 @@ static int thread_driver(blas_arg_t *args, FLOAT *sa, FLOAT *sb){
#elif defined(DOUBLE)
mode = BLAS_DOUBLE | BLAS_REAL;
mask = MAX(DGEMM_UNROLL_M, DGEMM_UNROLL_N) - 1;
#elif defined(HALF)
mode = BLAS_HALF | BLAS_REAL;
#elif defined(BFLOAT16)
mode = BLAS_BFLOAT16 | BLAS_REAL;
mask = MAX(SBGEMM_UNROLL_M, SBGEMM_UNROLL_N) - 1;
#else
mode = BLAS_SINGLE | BLAS_REAL;


+ 16
- 1
param.h View File

@@ -1,5 +1,5 @@
/*****************************************************************************
Copyright (c) 2011-2023, The OpenBLAS Project
Copyright (c) 2011-2023, 2025 The OpenBLAS Project
All rights reserved.

Redistribution and use in source and binary forms, with or without
@@ -79,6 +79,14 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define SHGEMM_DEFAULT_R 240
#define SHGEMM_DEFAULT_Q 12288

#define BGEMM_DEFAULT_UNROLL_N 4
#define BGEMM_DEFAULT_UNROLL_M 8
#define BGEMM_DEFAULT_UNROLL_MN 32
#define BGEMM_DEFAULT_P 256
#define BGEMM_DEFAULT_R 256
#define BGEMM_DEFAULT_Q 256
#define BGEMM_ALIGN_K 1 // must be 2^x

#define SBGEMM_DEFAULT_UNROLL_N 4
#define SBGEMM_DEFAULT_UNROLL_M 8
#define SBGEMM_DEFAULT_UNROLL_MN 32
@@ -3585,6 +3593,13 @@ is a big desktop or server with abundant cache rather than a phone or embedded d
#define GEMM_PREFERED_SIZE 8
#endif

#undef BGEMM_ALIGN_K
#undef BGEMM_DEFAULT_UNROLL_M
#undef BGEMM_DEFAULT_UNROLL_N
#define BGEMM_ALIGN_K 8
#define BGEMM_DEFAULT_UNROLL_N 4
#define BGEMM_DEFAULT_UNROLL_M 4

#undef SBGEMM_ALIGN_K
#undef SBGEMM_DEFAULT_UNROLL_M
#undef SBGEMM_DEFAULT_UNROLL_N


+ 73
- 6
test/Makefile View File

@@ -1,3 +1,31 @@
###############################################################################
# Copyright (c) 2025, 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.
###############################################################################
TOPDIR = ..
include ../Makefile.system
ifeq ($(F_COMPILER),GFORTRAN)
@@ -6,6 +34,7 @@ ifneq (, $(filter $(CORE),LOONGSON3R3 LOONGSON3R4))
endif
override FFLAGS += -fno-tree-vectorize
endif
override CFLAGS += -std=c11 -Wall -Werror

SUPPORT_GEMM3M = 0

@@ -90,6 +119,10 @@ endif
endif
endif

ifeq ($(BUILD_BFLOAT16), 1)
BB2 = test_bgemv
B2 = test_sbgemv
endif
ifeq ($(BUILD_SINGLE),1)
S2=sblat2
endif
@@ -103,11 +136,17 @@ ifeq ($(BUILD_COMPLEX16),1)
Z2=zblat2
endif

level2: $(S2) $(D2) $(C2) $(Z2)
level2: $(BB2) $(B2) $(S2) $(D2) $(C2) $(Z2)


ifneq ($(CROSS), 1)
rm -f ?BLAT2.SUMM
ifeq ($(BUILD_BFLOAT16),1)
OPENBLAS_NUM_THREADS=1 OMP_NUM_THREADS=1 ./test_bgemv > BBLAT2.SUMM
@$(GREP) -q FATAL BBLAT2.SUMM && cat BBLAT2.SUMM || exit 0
OPENBLAS_NUM_THREADS=1 OMP_NUM_THREADS=1 ./test_sbgemv > SBBLAT2.SUMM
@$(GREP) -q FATAL SBBLAT2.SUMM && cat SBBLAT2.SUMM || exit 0
endif
ifeq ($(BUILD_SINGLE),1)
OPENBLAS_NUM_THREADS=1 OMP_NUM_THREADS=1 ./sblat2 < ./sblat2.dat
@$(GREP) -q FATAL SBLAT2.SUMM && cat SBLAT2.SUMM || exit 0
@@ -127,6 +166,12 @@ endif
ifdef SMP
rm -f ?BLAT2.SUMM
ifeq ($(USE_OPENMP), 1)
ifeq ($(BUILD_BFLOAT16),1)
OMP_NUM_THREADS=2 ./test_bgemv > BBLAT2.SUMM
@$(GREP) -q FATAL BBLAT2.SUMM && cat BBLAT2.SUMM || exit 0
OMP_NUM_THREADS=2 ./test_sbgemv > SBBLAT2.SUMM
@$(GREP) -q FATAL SBBLAT2.SUMM && cat SBBLAT2.SUMM || exit 0
endif
ifeq ($(BUILD_SINGLE),1)
OMP_NUM_THREADS=2 ./sblat2 < ./sblat2.dat
@$(GREP) -q FATAL SBLAT2.SUMM && cat SBLAT2.SUMM || exit 0
@@ -144,6 +189,12 @@ ifeq ($(BUILD_COMPLEX16),1)
@$(GREP) -q FATAL ZBLAT2.SUMM && cat ZBLAT2.SUMM || exit 0
endif
else
ifeq ($(BUILD_BFLOAT16),1)
OMP_NUM_THREADS=2 ./test_bgemv > BBLAT2.SUMM
@$(GREP) -q FATAL BBLAT2.SUMM && cat BBLAT2.SUMM || exit 0
OMP_NUM_THREADS=2 ./test_sbgemv > SBBLAT2.SUMM
@$(GREP) -q FATAL SBBLAT2.SUMM && cat SBBLAT2.SUMM || exit 0
endif
ifeq ($(BUILD_SINGLE),1)
OPENBLAS_NUM_THREADS=2 ./sblat2 < ./sblat2.dat
@$(GREP) -q FATAL SBLAT2.SUMM && cat SBLAT2.SUMM || exit 0
@@ -165,7 +216,8 @@ endif
endif

ifeq ($(BUILD_BFLOAT16),1)
B3= test_sbgemm
BF3= test_bgemm
B3 = test_sbgemm
endif
ifeq ($(BUILD_SINGLE),1)
S3=sblat3
@@ -192,7 +244,7 @@ endif
ifeq ($(SUPPORT_GEMM3M),1)
level3: $(B3) $(S3) $(D3) $(C3) $(Z3) level3_3m
else
level3: $(B3) $(S3) $(D3) $(C3) $(Z3)
level3: $(BF3) $(B3) $(S3) $(D3) $(C3) $(Z3)
endif

ifneq ($(CROSS), 1)
@@ -200,6 +252,8 @@ ifneq ($(CROSS), 1)
ifeq ($(BUILD_BFLOAT16),1)
OPENBLAS_NUM_THREADS=1 OMP_NUM_THREADS=1 ./test_sbgemm > SBBLAT3.SUMM
@$(GREP) -q FATAL SBBLAT3.SUMM && cat SBBLAT3.SUMM || exit 0
OPENBLAS_NUM_THREADS=1 OMP_NUM_THREADS=1 ./test_bgemm > BBLAT3.SUMM
@$(GREP) -q FATAL BBLAT3.SUMM && cat BBLAT3.SUMM || exit 0
endif
ifeq ($(BUILD_SINGLE),1)
OPENBLAS_NUM_THREADS=1 OMP_NUM_THREADS=1 ./sblat3 < ./sblat3.dat
@@ -223,6 +277,8 @@ ifeq ($(USE_OPENMP), 1)
ifeq ($(BUILD_BFLOAT16),1)
OMP_NUM_THREADS=2 ./test_sbgemm > SBBLAT3.SUMM
@$(GREP) -q FATAL SBBLAT3.SUMM && cat SBBLAT3.SUMM || exit 0
OMP_NUM_THREADS=2 ./test_bgemm > BBLAT3.SUMM
@$(GREP) -q FATAL BBLAT3.SUMM && cat BBLAT3.SUMM || exit 0
endif
ifeq ($(BUILD_SINGLE),1)
OMP_NUM_THREADS=2 ./sblat3 < ./sblat3.dat
@@ -244,6 +300,8 @@ else
ifeq ($(BUILD_BFLOAT16),1)
OPENBLAS_NUM_THREADS=2 ./test_sbgemm > SBBLAT3.SUMM
@$(GREP) -q FATAL SBBLAT3.SUMM && cat SBBLAT3.SUMM || exit 0
OPENBLAS_NUM_THREADS=2 ./test_bgemm > BBLAT3.SUMM
@$(GREP) -q FATAL BBLAT3.SUMM && cat BBLAT3.SUMM || exit 0
endif
ifeq ($(BUILD_SINGLE),1)
OPENBLAS_NUM_THREADS=2 ./sblat3 < ./sblat3.dat
@@ -367,8 +425,17 @@ zblat3 : zblat3.$(SUFFIX) ../$(LIBNAME)
endif

ifeq ($(BUILD_BFLOAT16),1)
test_sbgemm : compare_sgemm_sbgemm.c ../$(LIBNAME)
$(CC) $(CLDFLAGS) -o test_sbgemm compare_sgemm_sbgemm.c ../$(LIBNAME) $(EXTRALIB) $(CEXTRALIB)
test_bgemm : compare_sgemm_bgemm.c test_helpers.h ../$(LIBNAME)
$(CC) $(CLDFLAGS) -DIBFLOAT16 -DOBFLOAT16 -o test_bgemm compare_sgemm_bgemm.c ../$(LIBNAME) $(EXTRALIB) $(CEXTRALIB)

test_bgemv : compare_sgemv_bgemv.c ../$(LIBNAME)
$(CC) $(CLDFLAGS) -DIBFLOAT16 -DOBFLOAT16 -o test_bgemv compare_sgemv_bgemv.c ../$(LIBNAME) $(EXTRALIB) $(CEXTRALIB)

test_sbgemm : compare_sgemm_sbgemm.c test_helpers.h ../$(LIBNAME)
$(CC) $(CLDFLAGS) -DIBFLOAT16 -o test_sbgemm compare_sgemm_sbgemm.c ../$(LIBNAME) $(EXTRALIB) $(CEXTRALIB)

test_sbgemv : compare_sgemv_sbgemv.c ../$(LIBNAME)
$(CC) $(CLDFLAGS) -DIBFLOAT16 -o test_sbgemv compare_sgemv_sbgemv.c ../$(LIBNAME) $(EXTRALIB) $(CEXTRALIB)
endif

ifeq ($(BUILD_COMPLEX),1)
@@ -387,7 +454,7 @@ clean:
@rm -f *.$(SUFFIX) *.$(PSUFFIX) gmon.$(SUFFIX)ut *.SUMM *.cxml *.exe *.pdb *.dwf \
sblat1 dblat1 cblat1 zblat1 \
sblat2 dblat2 cblat2 zblat2 \
test_sbgemm sblat3 dblat3 cblat3 zblat3 \
test_bgemm test_bgemv test_sbgemm test_sbgemv sblat3 dblat3 cblat3 zblat3 \
sblat1p dblat1p cblat1p zblat1p \
sblat2p dblat2p cblat2p zblat2p \
sblat3p dblat3p cblat3p zblat3p \


+ 155
- 0
test/compare_sgemm_bgemm.c View File

@@ -0,0 +1,155 @@
/***************************************************************************
Copyright (c) 2025 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 "../common.h"
#include <stdint.h>
#include <stdio.h>

#include "test_helpers.h"

#define SGEMM BLASFUNC(sgemm)
#define BGEMM BLASFUNC(bgemm)
#define BGEMM_LARGEST 256

int
main (int argc, char *argv[])
{
blasint m, n, k;
int i, j, l;
blasint x, y;
blasint one = 1;
int ret = 0;
int loop = BGEMM_LARGEST;
char transA = 'N', transB = 'N';
float alpha = 1.0, beta = 0.0;
bfloat16 alpha_bf16;
sbstobf16_(&one, &alpha, &one, &alpha_bf16, &one);
bfloat16 beta_bf16;
sbstobf16_(&one, &beta, &one, &beta_bf16, &one);

for (x = 0; x <= loop; x++)
{
if ((x > 100) && (x != BGEMM_LARGEST)) continue;
m = k = n = x;
float *A = (float *)malloc_safe(m * k * sizeof(FLOAT));
float *B = (float *)malloc_safe(k * n * sizeof(FLOAT));
float *C = (float *)malloc_safe(m * n * sizeof(FLOAT));
bfloat16 *AA = (bfloat16 *)malloc_safe(m * k * sizeof(bfloat16));
bfloat16 *BB = (bfloat16 *)malloc_safe(k * n * sizeof(bfloat16));
bfloat16 *CC = (bfloat16 *)malloc_safe(k * n * sizeof(bfloat16));
FLOAT *DD = (FLOAT *)malloc_safe(m * n * sizeof(FLOAT));
if ((A == NULL) || (B == NULL) || (C == NULL) || (AA == NULL) || (BB == NULL) ||
(DD == NULL) || (CC == NULL))
return 1;

for (j = 0; j < m; j++)
{
for (i = 0; i < k; i++)
{
A[j * k + i] = ((FLOAT) rand () / (FLOAT) RAND_MAX) + 0.5;
sbstobf16_(&one, &A[j*k+i], &one, &AA[j * k + i], &one);
}
}
for (j = 0; j < n; j++)
{
for (i = 0; i < k; i++)
{
B[j * k + i] = ((FLOAT) rand () / (FLOAT) RAND_MAX) + 0.5;
sbstobf16_(&one, &B[j*k+i], &one, &BB[j * k + i], &one);
}
}
for (y = 0; y < 4; y++)
{
if ((y == 0) || (y == 2)) {
transA = 'N';
} else {
transA = 'T';
}
if ((y == 0) || (y == 1)) {
transB = 'N';
} else {
transB = 'T';
}

memset(CC, 0, m * n * sizeof(bfloat16));
memset(DD, 0, m * n * sizeof(FLOAT));
memset(C, 0, m * n * sizeof(FLOAT));

SGEMM (&transA, &transB, &m, &n, &k, &alpha, A,
&m, B, &k, &beta, C, &m);
BGEMM (&transA, &transB, &m, &n, &k, &alpha_bf16, (bfloat16*) AA,
&m, (bfloat16*)BB, &k, &beta_bf16, (bfloat16*)CC, &m);

for (i = 0; i < n; i++)
for (j = 0; j < m; j++)
{
for (l = 0; l < k; l++)
if (transA == 'N' && transB == 'N')
{
DD[i * m + j] +=
float16to32 (AA[l * m + j]) * float16to32 (BB[l + k * i]);
} else if (transA == 'T' && transB == 'N')
{
DD[i * m + j] +=
float16to32 (AA[k * j + l]) * float16to32 (BB[l + k * i]);
} else if (transA == 'N' && transB == 'T')
{
DD[i * m + j] +=
float16to32 (AA[l * m + j]) * float16to32 (BB[i + l * n]);
} else if (transA == 'T' && transB == 'T')
{
DD[i * m + j] +=
float16to32 (AA[k * j + l]) * float16to32 (BB[i + l * n]);
}
if (!is_close(float16to32(CC[i * m + j]), truncate_float32_to_bfloat16(C[i * m + j]), 0.01, 0.001)) {
printf("Mismatch at i=%d, j=%d, k=%d: CC=%.6f, C=%.6f\n",
i, j, k, float16to32(CC[i * m + j]), truncate_float32_to_bfloat16(C[i * m + j]));
ret++;
}

if (!is_close(float16to32(CC[i * m + j]), truncate_float32_to_bfloat16(DD[i * m + j]), 0.0001, 0.00001)) {
printf("Mismatch at i=%d, j=%d, k=%d: CC=%.6f, DD=%.6f\n",
i, j, k, float16to32(CC[i * m + j]), truncate_float32_to_bfloat16(DD[i * m + j]));
ret++;
}
}
}
free(A);
free(B);
free(C);
free(AA);
free(BB);
free(CC);
free(DD);
}

if (ret != 0) {
fprintf (stderr, "FATAL ERROR BGEMM - Return code: %d\n", ret);
}

return ret;
}

+ 11
- 150
test/compare_sgemm_sbgemm.c View File

@@ -27,72 +27,15 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <stdio.h>
#include <stdint.h>
#include "../common.h"

#include "test_helpers.h"

#define SGEMM BLASFUNC(sgemm)
#define SBGEMM BLASFUNC(sbgemm)
#define SGEMV BLASFUNC(sgemv)
#define SBGEMV BLASFUNC(sbgemv)
typedef union
{
unsigned short v;
#if defined(_AIX)
struct __attribute__((packed))
#else
struct
#endif
{
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
unsigned short s:1;
unsigned short e:8;
unsigned short m:7;
#else
unsigned short m:7;
unsigned short e:8;
unsigned short s:1;
#endif
} bits;
} bfloat16_bits;

typedef union
{
float v;
#if defined(_AIX)
struct __attribute__((packed))
#else
struct
#endif
{
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
uint32_t s:1;
uint32_t e:8;
uint32_t m:23;
#else
uint32_t m:23;
uint32_t e:8;
uint32_t s:1;
#endif
} bits;
} float32_bits;

float
float16to32 (bfloat16_bits f16)
{
float32_bits f32;
f32.bits.s = f16.bits.s;
f32.bits.e = f16.bits.e;
f32.bits.m = (uint32_t) f16.bits.m << 16;
return f32.v;
}

#define SBGEMM_LARGEST 256

void *malloc_safe(size_t size)
{
if (size == 0)
return malloc(1);
else
return malloc(size);
}

int
main (int argc, char *argv[])
{
@@ -111,14 +54,13 @@ main (int argc, char *argv[])
float *A = (float *)malloc_safe(m * k * sizeof(FLOAT));
float *B = (float *)malloc_safe(k * n * sizeof(FLOAT));
float *C = (float *)malloc_safe(m * n * sizeof(FLOAT));
bfloat16_bits *AA = (bfloat16_bits *)malloc_safe(m * k * sizeof(bfloat16_bits));
bfloat16_bits *BB = (bfloat16_bits *)malloc_safe(k * n * sizeof(bfloat16_bits));
bfloat16 *AA = (bfloat16 *)malloc_safe(m * k * sizeof(bfloat16));
bfloat16 *BB = (bfloat16 *)malloc_safe(k * n * sizeof(bfloat16));
float *DD = (float *)malloc_safe(m * n * sizeof(FLOAT));
float *CC = (float *)malloc_safe(m * n * sizeof(FLOAT));
if ((A == NULL) || (B == NULL) || (C == NULL) || (AA == NULL) || (BB == NULL) ||
(DD == NULL) || (CC == NULL))
return 1;
bfloat16 atmp,btmp;
blasint one=1;

for (j = 0; j < m; j++)
@@ -126,8 +68,7 @@ main (int argc, char *argv[])
for (i = 0; i < k; i++)
{
A[j * k + i] = ((FLOAT) rand () / (FLOAT) RAND_MAX) + 0.5;
sbstobf16_(&one, &A[j*k+i], &one, &atmp, &one);
AA[j * k + i].v = atmp;
sbstobf16_(&one, &A[j*k+i], &one, &AA[j * k + i], &one);
}
}
for (j = 0; j < n; j++)
@@ -135,8 +76,7 @@ main (int argc, char *argv[])
for (i = 0; i < k; i++)
{
B[j * k + i] = ((FLOAT) rand () / (FLOAT) RAND_MAX) + 0.5;
sbstobf16_(&one, &B[j*k+i], &one, &btmp, &one);
BB[j * k + i].v = btmp;
sbstobf16_(&one, &B[j*k+i], &one, &BB[j * k + i], &one);
}
}
for (y = 0; y < 4; y++)
@@ -182,10 +122,12 @@ main (int argc, char *argv[])
DD[i * m + j] +=
float16to32 (AA[k * j + l]) * float16to32 (BB[i + l * n]);
}
if (fabs (CC[i * m + j] - C[i * m + j]) > 1.0)
if (!is_close(CC[i * m + j], C[i * m + j], 0.01, 0.001)) {
ret++;
if (fabs (CC[i * m + j] - DD[i * m + j]) > 1.0)
}
if (!is_close(CC[i * m + j], DD[i * m + j], 0.001, 0.0001)) {
ret++;
}
}
}
free(A);
@@ -199,88 +141,7 @@ main (int argc, char *argv[])

if (ret != 0) {
fprintf (stderr, "FATAL ERROR SBGEMM - Return code: %d\n", ret);
return ret;
}

for (beta = 0; beta < 3; beta += 1) {
for (alpha = 0; alpha < 3; alpha += 1) {
for (l = 0; l < 2; l++) { // l = 1 to test inc_x & inc_y not equal to one.
for (x = 1; x <= loop; x++)
{
k = (x == 0) ? 0 : l + 1;
float *A = (float *)malloc_safe(x * x * sizeof(FLOAT));
float *B = (float *)malloc_safe(x * sizeof(FLOAT) << l);
float *C = (float *)malloc_safe(x * sizeof(FLOAT) << l);
bfloat16_bits *AA = (bfloat16_bits *)malloc_safe(x * x * sizeof(bfloat16_bits));
bfloat16_bits *BB = (bfloat16_bits *)malloc_safe(x * sizeof(bfloat16_bits) << l);
float *DD = (float *)malloc_safe(x * sizeof(FLOAT));
float *CC = (float *)malloc_safe(x * sizeof(FLOAT) << l);
if ((A == NULL) || (B == NULL) || (C == NULL) || (AA == NULL) || (BB == NULL) ||
(DD == NULL) || (CC == NULL))
return 1;
bfloat16 atmp, btmp;
blasint one = 1;

for (j = 0; j < x; j++)
{
for (i = 0; i < x; i++)
{
A[j * x + i] = ((FLOAT) rand () / (FLOAT) RAND_MAX) + 0.5;
sbstobf16_(&one, &A[j*x+i], &one, &atmp, &one);
AA[j * x + i].v = atmp;
}
B[j << l] = ((FLOAT) rand () / (FLOAT) RAND_MAX) + 0.5;
sbstobf16_(&one, &B[j << l], &one, &btmp, &one);
BB[j << l].v = btmp;
CC[j << l] = C[j << l] = ((FLOAT) rand () / (FLOAT) RAND_MAX) + 0.5;
}

for (y = 0; y < 2; y++)
{
if (y == 0) {
transA = 'N';
} else {
transA = 'T';
}

memset(CC, 0, x * sizeof(FLOAT) << l);
memset(DD, 0, x * sizeof(FLOAT));
memset(C, 0, x * sizeof(FLOAT) << l);

SGEMV (&transA, &x, &x, &alpha, A, &x, B, &k, &beta, C, &k);
SBGEMV (&transA, &x, &x, &alpha, (bfloat16*) AA, &x, (bfloat16*) BB, &k, &beta, CC, &k);

for (int i = 0; i < x; i ++) DD[i] *= beta;

for (j = 0; j < x; j++)
for (i = 0; i < x; i++)
if (transA == 'N') {
DD[i] += alpha * float16to32 (AA[j * x + i]) * float16to32 (BB[j << l]);
} else if (transA == 'T') {
DD[j] += alpha * float16to32 (AA[j * x + i]) * float16to32 (BB[i << l]);
}

for (j = 0; j < x; j++) {
if (fabs (CC[j << l] - C[j << l]) > 1.0)
ret++;
if (fabs (CC[j << l] - DD[j]) > 1.0)
ret++;
}
}
free(A);
free(B);
free(C);
free(AA);
free(BB);
free(DD);
free(CC);
} // x
} // l
} // alpha
} // beta

if (ret != 0)
fprintf (stderr, "FATAL ERROR SBGEMV - Return code: %d\n", ret);
return ret;
}

+ 149
- 0
test/compare_sgemv_bgemv.c View File

@@ -0,0 +1,149 @@
/***************************************************************************
Copyright (c) 2020,2025 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 <stdio.h>
#include <stdint.h>
#include "../common.h"

#include "test_helpers.h"

#define SGEMV BLASFUNC(sgemv)
#define BGEMV BLASFUNC(bgemv)
#define BGEMV_LARGEST 256

int main(int argc, char *argv[])
{
blasint k;
int i, j, l;
blasint x, y;
blasint one = 1;
int ret = 0;
int loop = BGEMV_LARGEST;
char transA = 'N';
float alpha = 1.0, beta = 0.0;
bfloat16 alpha_bf16, beta_bf16;

for (beta = 0; beta < 3; beta += 1)
{
for (alpha = 0; alpha < 3; alpha += 1)
{
for (l = 0; l < 2; l++)
{ // l = 1 to test inc_x & inc_y not equal to one.
for (x = 1; x <= loop; x++)
{
k = (x == 0) ? 0 : l + 1;
float *A = (float *)malloc_safe(x * x * sizeof(FLOAT));
float *B = (float *)malloc_safe(x * sizeof(FLOAT) << l);
float *C = (float *)malloc_safe(x * sizeof(FLOAT) << l);
bfloat16 *AA = (bfloat16 *)malloc_safe(x * x * sizeof(bfloat16));
bfloat16 *BB = (bfloat16 *)malloc_safe(x * sizeof(bfloat16) << l);
bfloat16 *CC = (bfloat16 *)malloc_safe(x * sizeof(bfloat16) << l);
float *DD = (float *)malloc_safe(x * sizeof(FLOAT));
if ((A == NULL) || (B == NULL) || (C == NULL) || (AA == NULL) || (BB == NULL) ||
(CC == NULL) || (DD == NULL))
return 1;

for (j = 0; j < x; j++)
{
for (i = 0; i < x; i++)
{
A[j * x + i] = ((FLOAT)rand() / (FLOAT)RAND_MAX) + 0.5;
sbstobf16_(&one, &A[j * x + i], &one, &AA[j * x + i], &one);
}
B[j << l] = ((FLOAT)rand() / (FLOAT)RAND_MAX) + 0.5;
sbstobf16_(&one, &B[j << l], &one, &BB[j << l], &one);

C[j << l] = ((FLOAT)rand() / (FLOAT)RAND_MAX) + 0.5;
sbstobf16_(&one, &B[j << l], &one, &CC[j << l], &one);
}

for (y = 0; y < 2; y++)
{
if (y == 0)
{
transA = 'N';
}
else
{
transA = 'T';
}

memset(C, 0, x * sizeof(FLOAT) << l);
memset(CC, 0, x * sizeof(bfloat16) << l);
memset(DD, 0, x * sizeof(FLOAT));

sbstobf16_(&one, &alpha, &one, &alpha_bf16, &one);
sbstobf16_(&one, &beta, &one, &beta_bf16, &one);
SGEMV(&transA, &x, &x, &alpha, A, &x, B, &k, &beta, C, &k);
BGEMV(&transA, &x, &x, &alpha_bf16, AA, &x, BB, &k, &beta_bf16, CC, &k);

for (int i = 0; i < x; i++)
DD[i] *= beta;

for (j = 0; j < x; j++)
for (i = 0; i < x; i++)
if (transA == 'N')
{
DD[i] += alpha * float16to32(AA[j * x + i]) * float16to32(BB[j << l]);
}
else if (transA == 'T')
{
DD[j] += alpha * float16to32(AA[j * x + i]) * float16to32(BB[i << l]);
}

for (j = 0; j < x; j++)
{
if (!is_close(float16to32(CC[j << l]), truncate_float32_to_bfloat16(C[j << l]), 0.01, 0.001))
{
printf("Mismatch at trans=%c, alpha=%.2f, beta=%.2f, i=%d, j=%d, k=%d: CC=%.6f, C=%.6f\n",
transA, alpha, beta, i, j, k, float16to32(CC[j << l]), truncate_float32_to_bfloat16(C[j << l]));
ret++;
}
if (!is_close(float16to32(CC[j << l]), truncate_float32_to_bfloat16(DD[j]), 0.001, 0.0001))
{
printf("Mismatch at trans=%c, alpha=%.2f, beta=%.2f, i=%d, j=%d, k=%d: CC=%.6f, C=%.6f\n",
transA, alpha, beta, i, j, k, float16to32(CC[j << l]), truncate_float32_to_bfloat16(DD[j]));
ret++;
}
}
}

free(A);
free(B);
free(C);
free(AA);
free(BB);
free(CC);
free(DD);
} // x
} // l
} // alpha
} // beta

if (ret != 0)
fprintf(stderr, "FATAL ERROR BGEMV - Return code: %d\n", ret);
return ret;
}

+ 128
- 0
test/compare_sgemv_sbgemv.c View File

@@ -0,0 +1,128 @@
/***************************************************************************
Copyright (c) 2020,2025 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 <stdio.h>
#include <stdint.h>
#include "../common.h"

#include "test_helpers.h"

#define SGEMV BLASFUNC(sgemv)
#define SBGEMV BLASFUNC(sbgemv)
#define SBGEMV_LARGEST 256

int
main (int argc, char *argv[])
{
blasint k;
int i, j, l;
blasint x, y;
int ret = 0;
int loop = SBGEMV_LARGEST;
char transA = 'N';
float alpha = 1.0, beta = 0.0;

for (beta = 0; beta < 3; beta += 1) {
for (alpha = 0; alpha < 3; alpha += 1) {
for (l = 0; l < 2; l++) { // l = 1 to test inc_x & inc_y not equal to one.
for (x = 1; x <= loop; x++)
{
k = (x == 0) ? 0 : l + 1;
float *A = (float *)malloc_safe(x * x * sizeof(FLOAT));
float *B = (float *)malloc_safe(x * sizeof(FLOAT) << l);
float *C = (float *)malloc_safe(x * sizeof(FLOAT) << l);
bfloat16 *AA = (bfloat16 *)malloc_safe(x * x * sizeof(bfloat16));
bfloat16 *BB = (bfloat16 *)malloc_safe(x * sizeof(bfloat16) << l);
float *CC = (float *)malloc_safe(x * sizeof(FLOAT) << l);
float *DD = (float *)malloc_safe(x * sizeof(FLOAT));
if ((A == NULL) || (B == NULL) || (C == NULL) || (AA == NULL) || (BB == NULL) ||
(DD == NULL) || (CC == NULL))
return 1;
blasint one = 1;

for (j = 0; j < x; j++)
{
for (i = 0; i < x; i++)
{
A[j * x + i] = ((FLOAT) rand () / (FLOAT) RAND_MAX) + 0.5;
sbstobf16_(&one, &A[j*x+i], &one, &AA[j * x + i], &one);
}
B[j << l] = ((FLOAT) rand () / (FLOAT) RAND_MAX) + 0.5;
sbstobf16_(&one, &B[j << l], &one, &BB[j << l], &one);
CC[j << l] = C[j << l] = ((FLOAT) rand () / (FLOAT) RAND_MAX) + 0.5;
}

for (y = 0; y < 2; y++)
{
if (y == 0) {
transA = 'N';
} else {
transA = 'T';
}

memset(CC, 0, x * sizeof(FLOAT) << l);
memset(DD, 0, x * sizeof(FLOAT));
memset(C, 0, x * sizeof(FLOAT) << l);

SGEMV (&transA, &x, &x, &alpha, A, &x, B, &k, &beta, C, &k);
SBGEMV (&transA, &x, &x, &alpha, (bfloat16*) AA, &x, (bfloat16*) BB, &k, &beta, CC, &k);

for (int i = 0; i < x; i ++) DD[i] *= beta;

for (j = 0; j < x; j++)
for (i = 0; i < x; i++)
if (transA == 'N') {
DD[i] += alpha * float16to32 (AA[j * x + i]) * float16to32 (BB[j << l]);
} else if (transA == 'T') {
DD[j] += alpha * float16to32 (AA[j * x + i]) * float16to32 (BB[i << l]);
}

for (j = 0; j < x; j++) {
if (!is_close(CC[j << l], C[j << l], 0.01, 0.001)) {
ret++;
}
if (!is_close(CC[j << l], DD[j], 0.001, 0.0001)) {
ret++;
}
}
}
free(A);
free(B);
free(C);
free(AA);
free(BB);
free(DD);
free(CC);
} // x
} // l
} // alpha
} // beta

if (ret != 0)
fprintf (stderr, "FATAL ERROR SBGEMV - Return code: %d\n", ret);
return ret;
}

+ 66
- 0
test/test_helpers.h View File

@@ -0,0 +1,66 @@
/***************************************************************************
Copyright (c) 2025 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.
*****************************************************************************/

#ifndef TEST_HELPERS_H
#define TEST_HELPERS_H
#include <stdbool.h>

#include "../common.h"

#ifdef IBFLOAT16
static float float16to32(bfloat16 value)
{
blasint one = 1;
float result;
sbf16tos_(&one, &value, &one, &result, &one);
return result;
}
#endif

#ifdef OBFLOAT16
static float truncate_float32_to_bfloat16(float value) {
blasint one = 1;
bfloat16 tmp;
float result;
sbstobf16_(&one, &value, &one, &tmp, &one);
sbf16tos_(&one, &tmp, &one, &result, &one);
return result;
}
#endif

static void *malloc_safe(size_t size) {
if (size == 0)
return malloc(1);
else
return malloc(size);
}

static bool is_close(float a, float b, float rtol, float atol) {
return fabs(a - b) <= (atol + rtol*fabs(b));
}

#endif

Loading…
Cancel
Save