Public bug reported:

[ Impact ]

On arm64, Ubuntu 26.04's OpenBLAS (0.3.32+ds-5) skips three CBLAS calls 
entirely on non-SME kernel sets.
These calls leave the output matrix unchanged and report no error:

 * cblas_strsm and cblas_strmm with CblasRowMajor, CblasLeft and CblasNonUnit, 
when lda == m and ldb == n;
 * cblas_ssymm with CblasRowMajor and CblasLeft, when lda == m, ldb == n and 
ldc == n.

These are ordinary, tightly packed row-major arrays of C and C++ code. The same 
calls with padded leading
dimensions compute correctly. A program solving a triangular system with 
cblas_strsm silently keeps the
right-hand side as its "solution".

The faulty entry-point code is shared by the pthread, openmp and serial 
flavours. The local before/after
package build and runtime tests used pthread. The census exercised all 13 
non-SME kernel sets: nine natively
on an Apple M5 VM and four SVE sets under qemu-aarch64 -cpu max, using 
OPENBLAS_CORETYPE. This tests the
different kernel selections; it is not a set of measurements on 13 physical CPU 
models. The additional
ARMV9SME set has separate faults which this patch does not fix, as described 
below.

The fault is in the CBLAS entry points. OpenBLAS 0.3.31 added an SME
fast path for these three routines, behind

    if (strcmp(gotoblas_corename(), "armv9sme") == 0)
      if (args.m == 0 || args.n == 0) return;
    if (order == CblasRowMajor && ... && m == lda && n == ldb) { <SME kernel>; 
return; }

The core test governs only the quick return, so the fast path runs on every 
core. On every core except ARMV9SME,
the "SME kernel" is an empty function. Upstream issue #5763 was fixed in 0.3.33 
by PR #5767, which moved the
quick return in front of the core test. This proposal backports those two 
one-line moves
(d/p/arm64-cblas-sme-direct-gate.patch).

Not affected by this dispatch defect:

 * the Fortran interface (strsm_, strmm_, ssymm_);
 * the double and complex CBLAS variants;
 * column-major or padded arrays;
 * other architectures (the SME fast path is arm64-only).

[ Test Plan ]

On an arm64 machine or VM running resolute, with the attached cblas-sme-
direct.c:

    sudo apt install libopenblas-pthread-dev gcc
    sudo update-alternatives --set libopenblas.so.0-aarch64-linux-gnu 
/usr/lib/aarch64-linux-gnu/openblas-pthread/libopenblas.so.0
    apt-cache policy libopenblas0-pthread
    gcc -O2 cblas-sme-direct.c -o cblas-sme-direct -lopenblas -lm
    ./cblas-sme-direct; echo "exit $?"
    OPENBLAS_CORETYPE=ARMV8 ./cblas-sme-direct; echo "exit $?"

The program checks 10 calls (STRSM and STRMM: Upper/Lower x NoTrans/Trans; 
SSYMM: Upper/Lower) against a
double-precision reference, first tightly packed and then with every leading 
dimension one larger.

With 0.3.32+ds-5, or with the sdot-only 0.3.32+ds-5ubuntu0.1, the forced ARMV8 
run fails all 10 tight calls and
passes all 10 padded calls. Natural dispatch gives the same result on non-SME 
kernel sets:

    cblas_strsm Upper NoTrans    tight  WRONG (30 of 30 elements; [0][0] = 1, 
want 0.990145)
    ...
    cblas_strsm Upper NoTrans    padded ok
    ...
    FAIL: 10 of 20 calls wrong
    exit 1

After this SRU is available in resolute-proposed, enable that pocket following
https://wiki.ubuntu.com/Testing/EnableProposed, then install and verify the 
package version:

    sudo apt install -t resolute-proposed libopenblas0-pthread 
libopenblas-pthread-dev
    apt-cache policy libopenblas0-pthread    # Expected SRU version: 
0.3.32+ds-5ubuntu0.2
    sudo update-alternatives --set libopenblas.so.0-aarch64-linux-gnu 
/usr/lib/aarch64-linux-gnu/openblas-pthread/libopenblas.so.0
    ./cblas-sme-direct; echo "exit $?"
    OPENBLAS_CORETYPE=ARMV8 ./cblas-sme-direct; echo "exit $?"

The forced ARMV8 run, and natural dispatch on non-SME kernel sets, must
now print:

    PASS: 0 of 20 calls wrong
    exit 0

On ARMV9SME, the natural-dispatch invocation intentionally prints SKIP and 
exits 77 before and after this
update. That is not a successful numerical test. The forced ARMV8 invocation 
still performs the required
before/after check. This patch leaves the ARMV9SME direct path unchanged.

Repeat the before/after runs for openmp and serial. For each flavour, install 
its corresponding runtime and
development packages from the pocket being tested, check the installed runtime 
version with apt-cache policy,
and explicitly select it before executing the program. For example, for the 
proposed openmp build:

    sudo apt install -t resolute-proposed libopenblas0-openmp 
libopenblas-openmp-dev
    apt-cache policy libopenblas0-openmp    # Expected SRU version: 
0.3.32+ds-5ubuntu0.2
    sudo update-alternatives --set libopenblas.so.0-aarch64-linux-gnu 
/usr/lib/aarch64-linux-gnu/openblas-openmp/libopenblas.so.0
    ./cblas-sme-direct; echo "exit $?"
    OPENBLAS_CORETYPE=ARMV8 ./cblas-sme-direct; echo "exit $?"

Use libopenblas0-serial, libopenblas-serial-dev and 
/usr/lib/aarch64-linux-gnu/openblas-serial/libopenblas.so.0
for the serial flavour. Record the selected flavour and version with each 
result.

The proposed package also adds an arm64 autopkgtest, cblas-sme-direct, in three 
stanzas, one per flavour.
It runs the program on the core that dispatch selects, then forces ARMV8 and, 
where the CPU allows,
NEOVERSEN1. ARMV9SME's natural-dispatch exit 77 is handled inside the test 
wrapper; the forced-core checks
still run. Local pthread runs fail against 0.3.32+ds-5 and pass against the 
proposed source build. Under
qemu -cpu max, natural dispatch skips on ARMV9SME, while forced ARMV8 fails 
before the fix and passes after it.

[ Where problems could occur ]

 * Behaviour changes in the tight row-major Left calls listed above on non-SME 
kernel sets. They now use the
   regular Level-3 driver, which the padded and column-major calls already use. 
A regression would show up as
   a wrong STRSM/STRMM/SSYMM result for those shapes. The autopkgtest compares 
them against a reference.
 * Programs that were unknowingly relying on the no-op will see their output 
matrix change. Run time rises
   from the erroneous immediate return to the normal cost of the call.
 * The quick return for m == 0 or n == 0 now comes before the core test in the 
CBLAS functions of every
   precision in trsm.c/symm.c. The same condition already returned a few lines 
later. Invalid-argument
   handling still occurs first.
 * trsm.c and symm.c are compiled on every architecture, so every binary is 
rebuilt. Off arm64 the SME block
   is compiled out and the only source change is the quick-return move. The 
object comparison was on arm64.
 * Two upstream deletion hunks are deliberately omitted: the shared Fortran 
quick returns in symm.c and
   trsm.c are retained. Removing the trsm.c return caused upstream #5810 and 
was reversed in PR #5813.
   The Fortran objects strsm.o, strmm.o and ssymm.o have identical .text with 
and without this patch in the
   local comparison.
 * ARMV9SME calls still take the SME path and remain wrong in this GCC build 
for separate reasons. The new
   autopkgtest skips its natural-dispatch run there and tests the forced 
non-SME paths. Passing this test
   does not establish correctness of the ARMV9SME kernels.
 * The proposed 0.3.32+ds-5ubuntu0.2 debdiff is based on the sdot-only 
0.3.32+ds-5ubuntu0.1 (LP: #2169719).
   Sponsorship and upload of this second SRU will wait until that exact base is 
published to resolute-updates.
   The patches touch different files, and the sdot-v0 autopkgtest still passes 
on the local combined build.
   If the base changes before then, the second SRU must be regenerated and 
reviewed against the new base.

[ Other Info ]

 * Upstream: https://github.com/OpenMathLib/OpenBLAS/issues/5763, fixed by
   https://github.com/OpenMathLib/OpenBLAS/pull/5767 (commits 74486799bb0c and 
59cfea08592d), released in 0.3.33.
 * Development release: stonking's 0.3.33+ds-3 already contains the fix. The 
same program passes there on
   non-SME kernel selections, so no development-series upload is needed for 
this defect.
 * Affected supported series: resolute. noble (0.3.26) and jammy (0.3.20) 
predate the fast path, which arrived
   in 0.3.31.
 * Deviation from upstream: the third hunk of 59cfea08 (symm.c) and commit 
fd862d43 (trsm.c) are omitted because
   both remove a quick return shared with the Fortran interface. Upstream 
restored the trsm.c return in
   0.3.34 (PR #5813) after #5810. The retained changes are upstream's two 
quick-return moves.
 * Source comparison: the shipped pthread cblas_strsm, cblas_strmm and 
cblas_ssymm functions match a rebuild
   of the 0.3.32+ds-5 source with the package flags after masking link-time 
address fields. The package's
   faulty dispatch therefore agrees with the source being patched.
 * Separate from this SRU: on ARMV9SME, tightly packed row-major SGEMM with 
alpha != 1 or beta != 0, SSYMM,
   SSYRK, SSYR2K and STRMM/STRSM are wrong in the tested GCC build. The census 
identified two causes:
   C SME kernels are compiled as empty stubs while the interface still calls 
them; STRSM reaches the STRMM
   kernel (fixed upstream in 0.3.34 by PR #5898). These are outside this 
backport.

** Affects: openblas (Ubuntu)
     Importance: Undecided
         Status: New


** Tags: arm64 patch resolute

-- 
You received this bug notification because you are a member of Ubuntu
Bugs, which is subscribed to Ubuntu.
https://bugs.launchpad.net/bugs/2169788

Title:
  cblas_strsm, cblas_strmm and cblas_ssymm return without computing on
  arm64 (row-major, tightly packed)

To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/openblas/+bug/2169788/+subscriptions


-- 
ubuntu-bugs mailing list
[email protected]
https://lists.ubuntu.com/mailman/listinfo/ubuntu-bugs

Reply via email to