Skip to content

guards missing in wasm/KERNEL file? #5993

Description

@MMesch

Hi all,

I am currently exploring SIMD usage via OpenBLAS enabled numpy in WASM. I am working on improving the performance of the binaries provided in emscripten-forge. I specifically looked at ddot/sdot triggered by np.correlate usage. I was a bit surprised not to see more performance improvements through OpenBLAS compiled with simd flag to WASM. To explore deeper, I took the produced binary and did an object dump:

SO=lib/libopenblas_wasm128-r0.3.34.so
file $SO                          
# WebAssembly (wasm) binary version 0x1 (MVP module)

# 2. Confirm the shipped library's compile-time config (single command)
nix shell nixpkgs#binutils -c strings $SO | grep -E '^OpenBLAS 0\.'
# OpenBLAS 0.3.34 NO_AFFINITY WASM128_GENERIC

# 3. Locate the DOT / AXPY kernel symbols
nix shell nixpkgs#wabt -c wasm-objdump -x $SO | grep -E ' <(ddot_k|daxpy_k)>' | head
# - func[1480] sig=83 <daxpy_k>
# - func[1482] sig=91 <ddot_k>
# - func[1480] <daxpy_k> -> "daxpy_k"
# - func[1482] <ddot_k> -> "ddot_k"
# - func[1480] size=365 <daxpy_k>
# - func[1482] size=198 <ddot_k>

# 4. Full disassembly + relevant instructions
nix shell nixpkgs#wabt -c wasm-objdump -d $SO > /tmp/openblas.dis
for name in ddot_k daxpy_k sdsdot_k; do
  s=$(grep -n " <${name}>:" /tmp/openblas.dis | head -1 | cut -d: -f1)
  e=$(awk -v s=$((s+1)) 'NR>=s && /func\[[0-9]+\] </ {print NR; exit}' /tmp/openblas.dis)
  echo "=== ${name} (bytes: $((e-s)) lines) ==="
  sed -n "${s},${e}p" /tmp/openblas.dis \
    | grep -oE '\|[[:space:]]+[a-z0-9._]+' | awk '{print $2}' \
    | grep -E '^(f32|f64|v128|f[36][24]x[24]|i[0-9]+x[0-9]+)\.' | sort | uniq -c | sort -rn
done

#=== ddot_k (bytes: 110 lines) ===
#      6 f64.load
#      3 f64.mul
#      3 f64.add
#      1 f64.const
#=== daxpy_k (bytes: 197 lines) ===
#      6 f64.load
#      3 f64.store
#      3 f64.mul
#      3 f64.add
#      2 v128.load
#      1 v128.store
#      1 f64x2.splat
#      1 f64x2.mul
#      1 f64x2.add
#      1 f64.eq
#      1 f64.const
#=== sdsdot_k (bytes: 423 lines) ===
#     20 f64x2.promote_low_f32x4
#     16 f64x2.add
#     12 f64.promote_f32
#     12 f32.load
#     10 v128.load
#     10 i8x16.shuffle
#     10 f64x2.mul
#      9 f64.add
#      6 f64.mul
#      4 f64x2.extract_lane
#      1 f64.const

ddot, contrary to other functions, doesn't have any v128 instructions, indicating it's not SIMD accelerated and pure scalar. This is weird on the other hand because it seems that the CPU-variant kernel file https://github.com/OpenMathLib/OpenBLAS/blob/develop/kernel/wasm/KERNEL.WASM128_GENERIC#L58-L59 does point to a SIMD accelerated path https://github.com/OpenMathLib/OpenBLAS/blob/develop/kernel/generic/dot.c#L50 .

Exploring this further it seems that the generic KERNEL file in the wasm folder: https://github.com/OpenMathLib/OpenBLAS/blob/develop/kernel/wasm/KERNEL#L62-L63 points to RISCV which is not SIMD accelerated https://github.com/OpenMathLib/OpenBLAS/blob/develop/kernel/riscv64/dot.c .

Now, exploring further, it seems that, unexpectedly the generic KERNEL file overrides the specific KERNEL.WASM128_GENERIC one, a generic pattern throughout the codebase: https://github.com/OpenMathLib/OpenBLAS/blob/develop/kernel/Makefile#L119-L121

To get the correct behavior defined in the specific KERNEL.WASM128_GENERIC file, you would thus need to guard every line in the generic KERNEL file. And indeed, this seems to be done, for example, in the case of arm: https://github.com/OpenMathLib/OpenBLAS/blob/develop/kernel/arm/KERNEL .

However, for WASM this seems not to be done for many kernels. So my questions:

  • Is the above story correct? I am unsure since this is really my first interaction with the OpenBLAS codebase.
  • Should we guard everything in the wasm/KERNEL file to enable SIMD accelerated kernels for dot in WASM? Was this simply forgotten or is there a deeper reason?
  • Shouldn't this happen for other architectures as well? Most seem guarded appropriately but not all of them.
  • What's the reason for not simply reversing import order in general and safe the guards?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions