Skip to content

Add RVV implementation for decode_bf16_simd - #5641

Open
Xlawy wants to merge 2 commits into
facebookresearch:mainfrom
Xlawy:rvv-bf16-decode
Open

Xlawy wants to merge 2 commits into
facebookresearch:mainfrom
Xlawy:rvv-bf16-decode

Conversation

@Xlawy

@Xlawy Xlawy commented Sep 15, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Add a RISC-V Vector (RVV) implementation to decode_bf16_simd().

The RVV path preserves the existing bit-level conversion semantics:

  1. load BF16 values as unsigned 16-bit integers;
  2. zero-extend them to unsigned 32-bit integers;
  3. shift left by 16 bits;
  4. reinterpret the resulting bits as FP32.

Inputs shorter than 16 elements retain the scalar path to avoid short-vector overhead. Larger inputs use fixed-VL RVV chunks followed by a runtime-VL tail.

Validation

Tested on native RISC-V hardware with GCC 15.3.0 and -march=rv64gcv -mabi=lp64d, based on Faiss commit b5a14632a6f2bfdc824c86d683b9d6e9205c2604.

Correctness:

  • exhaustively tested all 65,536 BF16 bit patterns;
  • tested 31 input sizes, including zero, short inputs, vector boundaries, tails, and large arrays;
  • checked guard elements for output overwrites;
  • zero correctness failures.

Representative microbenchmark speedups over the scalar implementation:

Elements Speedup
7 1.01x
16 1.58x
31 2.43x
64 3.46x
128 3.88x
1024 4.38x
4096 4.37x
65536 4.30x

Scope

This change only modifies faiss/utils/bf16.h. It is independent of the active ScalarQuantizer RVV changes in PRs #5535 and #5539.

Notes

  • The n == 1 fast path and the n < 16 scalar loop exist because at VLEN=128 an e16m1 chunk covers only 8 elements, and for very short inputs the vsetvl/load/extend/store sequence costs more than the equivalent scalar work. The measured crossover is at 16 elements.
  • The bulk loop uses a hoisted vsetvlmax_e16m1() so vsetvl is not re-executed per iteration; only the final partial chunk calls vsetvl again.
  • vuint16m1 → vuint32m2 uses vzext.vf2 (LMUL widening), so the 32-bit shift and the FP32 store run at m2. This keeps register pressure low while doubling the elements per chunk.
  • No rounding or saturation is involved: BF16 → FP32 is an exact bit widening, so the vector path is bit-identical to the scalar path for every input, including NaN payloads and subnormals.
  • The guard is #elif defined(__riscv_vector) inside the existing arch dispatch, so the AVX2/AVX512 paths are untouched and a build without RVV falls through to the scalar loop unchanged.

Co-authored-by: ihb2032 hebome@foxmail.com
Co-authored-by: lyd1992 liuyudong@iscas.ac.cn
Co-authored-by: Yuansheng yuansheng@isrc.iscas.ac.cn

@meta-cla meta-cla Bot added the CLA Signed label Sep 15, 2026
Vectorize BF16-to-FP32 decoding with RVV while preserving the existing
bit-level conversion semantics. Load unsigned 16-bit values, zero-extend
to unsigned 32-bit integers, shift left by 16 bits, and reinterpret the
result as FP32.

Use e16m1 loads and widen to u32m2 with vzext.vf2 before shifting and
storing FP32 values. Compute the maximum vector length once for the
bulk loop and use a runtime vector length for the final partial chunk.

Keep inputs shorter than 16 elements on the scalar path to avoid
short-vector overhead, including the single-element fast path.

Guard the implementation with __riscv_vector inside the existing
architecture dispatch. Limit the change to faiss/utils/bf16.h and
preserve the existing x86 and non-RVV paths.

Validate on native RISC-V hardware with GCC 15.3.0 and
-march=rv64gcv -mabi=lp64d, based on Faiss commit
b5a1463. Exhaustively check all 65,536
BF16 bit patterns and test 31 input sizes covering empty inputs,
short inputs, vector boundaries, tails, and large arrays. Observe
no correctness failures or output guard overwrites.

The conversion requires no rounding or saturation and preserves every
input bit pattern, including NaN payloads and subnormals.

Representative microbenchmarks show 1.58x speedup at 16 elements,
3.88x at 128 elements, and 4.30x at 65,536 elements over the scalar
implementation on the tested host.

Co-authored-by: ihb2032 <hebome@foxmail.com>
Co-authored-by: lyd1992 <liuyudong@iscas.ac.cn>
Co-authored-by: Yuansheng <yuansheng@isrc.iscas.ac.cn>
@meta-codesync

meta-codesync Bot commented Sep 23, 2026

Copy link
Copy Markdown
Contributor

@mnorris11 has imported this pull request. If you are a Meta employee, you can view this in D121445956.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants