Skip to content

Add RVV vectorized FP32 kernel to CPU Adam - #8817

Open
zhangjian29 wants to merge 3 commits into
deepspeedai:masterfrom
zte-riscv:add-rvv-cpuamda-kernel
Open

zhangjian29 wants to merge 3 commits into
deepspeedai:masterfrom
zte-riscv:add-rvv-cpuamda-kernel

Conversation

@zhangjian29

Copy link
Copy Markdown

Description

On riscv64 hosts with the RISC-V Vector (RVV 1.0) extension, DeepSpeed CPU Adam currently falls back to the scalar Step_1 tail because neither the op builder's simd_width() nor the kernel dispatch recognizes the V extension. This PR adds an RVV FP32 tier to CPU Adam, mirroring the existing SVE backend, so RVV-capable CPUs get a ~4x single-core speedup on the optimizer step.

  • csrc/includes/rvv.h: an RVV 1.0 FP32 Adam kernel. The hot loop processes one m4 block per iteration — at VLEN=128 each block covers a full 64-byte cache line per stream — and runs entirely at the loop-invariant vlmax; a single vsetvl truncates the trailing block, so any tensor length is covered with no scalar tail. The arithmetic order matches the scalar and SVE kernels, keeping every tier within the existing test tolerance. Scalar hyperparameters ride the vf-form intrinsics, so only epsilon occupies a vector register.
  • cpu_adam.h / cpu_adam_impl.cpp: Step_RVV dispatch alongside Step_AVX and Step_SVE; only the FP32 param/FP32 state pair is vectorized, other dtype pairs keep the scalar path (same policy as SVE).
  • op_builder/builder.py: detect the V extension from the /proc/cpuinfo isa line with a per-character token test (a substring test misreads rv64imafdcvh as having V), build with -D__RVV__ -march=rv64gcv on riscv64, and normalize py-cpuinfo's RISCV_64 arch string so the riscv64 branch actually fires. Hosts without V are unaffected (rv64gc).
  • docs/_tutorials/zero-offload.md: document the automatic RVV tier.

Validation

Hardware/software: SG2044 60-core RISC-V server, VLEN=128, gcc-14.3, torch 2.15 CPU-only build.

Correctness: pytest tests/unit/ops/adam/test_cpu_adam.py → 48 passed, 1 skipped, 0 failed. The suite compares CPU Adam against the PyTorch fused-Adam reference across fp32/fp16 and multiple sizes; the fp16 equality tests pass (this tier keeps non-fp32 dtype pairs on the scalar path).

Key log:

48 passed, 1 skipped, 3 warnings in 1283.18s (0:21:23)

Performance (single core, OMP_NUM_THREADS=1 taskset -c 0, 100 steps):

Size Scalar baseline RVV (this PR) Speedup
1B params 13.07 s/step 3.15 s/step ~4.2x
2B params 26.13 s/step 6.31 s/step ~4.1x

Key log:

Elapsed Time is  3.1488167250156405
Elapsed Time is  6.313579152822495

DeepSpeed CPU Adam falls back to the scalar Step_1 tail on riscv64 because
neither the builder's simd_width() nor the kernel dispatch recognizes the
RISC-V vector extension. Add the FP32 RVV tier, mirroring the SVE backend:

- csrc/includes/rvv.h: FP32 Adam kernel using RVV 1.0 intrinsics. The hot
  loop processes one m4 block per iteration, so at VLEN=128 each block
  covers a full 64-byte cache line per stream and the loop runs entirely
  at the loop-invariant vlmax. A single vsetvl truncates the trailing
  block, so any tensor length is covered with no scalar tail. The
  operation order matches the scalar and SVE kernels, keeping all tiers
  within the existing test tolerance. Scalar hyperparameters ride the
  vf-form intrinsics, so of all the loop constants only epsilon occupies a
  vector register.
- cpu_adam.h / cpu_adam_impl.cpp: Step_RVV dispatch alongside Step_AVX and
  Step_SVE; only the FP32 param/FP32 state pair is vectorized, other dtype
  pairs keep the scalar path (same policy as SVE).
- op_builder/builder.py: detect the V extension from the /proc/cpuinfo isa
  line with a per-character token test (a substring test misreads
  rv64imafdcvh as having V) and build with -D__RVV__ -march=rv64gcv on
  riscv64 (rv64gc without V, so non-vector hardware is unaffected). Also
  normalize py-cpuinfo's "RISCV_64" arch string, without which the riscv64
  branch never fires and the build silently falls back to -march=native.
- docs/_tutorials/zero-offload.md: document the automatic RVV tier.

Measured on a SpacemiT 60-core server (VLEN=128, gcc-14), single core:
1B step 3.15s, 2B step 6.31s (scalar baseline 13.07s/26.13s, ~4.2x).
pytest unit/ops/adam/test_cpu_adam.py: 48 passed / 1 skipped / 0 failed.

Signed-off-by: 张健10355098 <zhang.jian60@zte.com.cn>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-13T12:15:22.673893Z 8b7461f PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8b7461f168

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread op_builder/builder.py Outdated
@zhangjian29
zhangjian29 requested a review from tohtana as a code owner October 13, 2026 13:05
@zhangjian29

zhangjian29 commented Oct 13, 2026 •

Copy link
Copy Markdown
Author

Addressed the P1 on _riscv_has_vector (op_builder/builder.py) in 3d382b6.

The base ISA segment is now tokenized into per-extension tokens ([a-z] optionally followed by a <major>p<minor> version, e.g. v0p7, i2p0-style). Only an unversioned v (ratified 1.0 on shipping devicetrees) or an explicit version >= 1.0 enables the vector path; a draft rv64imafdcv0p7 now falls back to the scalar -march=rv64gc / __SCALAR__ build instead of compiling V 1.0 encodings the CPU cannot execute. Added a hermetic unit test (test_riscv_has_vector_parses_isa_line) covering rv64gcv, rv64gcv1p0, fully-versioned strings with bare v, no-V, _zvfh, and v0p7, plus an unreadable-cpuinfo case.

An ISA string like rv64imafdcv0p7 (draft V 0.7) passed the single-letter
set test, so cpu_arch() built with -march=rv64gcv and simd_width() set
__RVV__, emitting ratified V 1.0 encodings such a CPU cannot execute.
Tokenize the base segment into per-extension version tokens and only
enable the vector path for an unversioned V or an explicit version >= 1.0,
keeping the scalar rv64gc build otherwise.

Signed-off-by: 张健10355098 <zhang.jian60@zte.com.cn>
@zhangjian29
zhangjian29 force-pushed the add-rvv-cpuamda-kernel branch from 3d382b6 to 2f8a2af Compare October 13, 2026 13:18
@delock
delock self-requested a review October 13, 2026 14:48
@hwchen2017
hwchen2017 requested a balanced review from Copilot October 13, 2026 17:09

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Unversioned draft RVV hardware can be misdetected as RVV 1.0, producing incompatible instructions.

1 open finding
What changed in this PR

Adds RVV 1.0 FP32 acceleration to CPU Adam on supported RISC-V systems.

Changes:

  • Implements and dispatches an RVV-vectorized Adam kernel.
  • Adds RISC-V vector detection and tests.
  • Documents automatic RVV optimization.
File Description
csrc/​includes/​rvv.h Implements the RVV FP32 Adam kernel.
csrc/​includes/​cpu_adam.h Integrates the RVV update path.
csrc/​adam/​cpu_adam_impl.cpp Adds RVV dispatch and capability reporting.
op_builder/​builder.py Detects RISC-V V and configures compilation.
tests/​unit/​ops/​test_op_builder.py Tests ISA-string parsing.
docs/​_tutorials/​zero-offload.md Documents RVV behavior.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread op_builder/builder.py Outdated
@zhangjian29

zhangjian29 commented Oct 14, 2026 •

Copy link
Copy Markdown
Author

Follow-up to the P1 on the bare v case: addressed in 43b1f40.

The probe now reads AT_HWCAP from /proc/self/auxv and treats the COMPAT_HWCAP_ISA_V bit (1 << ('V' - 'A'), per arch/riscv/include/uapi/asm/hwcap.h) as the decision signal. That is the interface the kernel's own vector documentation prescribes — "To get the availability of V in an ELF program, please read the COMPAT_HWCAP_ISA_V bit of ELF_HWCAP in the auxiliary vector" (Documentation/arch/riscv/vector.rst) — and it reflects the extension set the kernel's ISA parsing accepted rather than echoing the devicetree string, so an unversioned C906/D1 rv64imafdcv no longer enables the vector path by itself.

An unversioned "v" in the ISA line is not evidence of ratified V 1.0:
T-Head C906 (Allwinner D1) systems report bare rv64imafdcv while
implementing incompatible draft V 0.7.1, so the string parse alone can
still select -march=rv64gcv and emit encodings the CPU cannot execute.

Read AT_HWCAP from /proc/self/auxv (the interface the kernel's RISC-V
vector documentation defines for this question) and treat its
COMPAT_HWCAP_ISA_V bit as the decision signal; keep the explicitly
versioned ISA token as an authoritative override (v1p0 yes, v0p7
never) so pre-HWCAP kernels with precise devicetrees still work, and let
a bare v without HWCAP fall back to the scalar rv64gc build.

Signed-off-by: 张健10355098 <zhang.jian60@zte.com.cn>
@zhangjian29
zhangjian29 force-pushed the add-rvv-cpuamda-kernel branch from 43b1f40 to 976ff52 Compare October 14, 2026 01:19
@zhangjian29
zhangjian29 requested a balanced review from Copilot October 14, 2026 01:20

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@delock

delock commented Oct 18, 2026

Copy link
Copy Markdown
Collaborator

@zhangjian29 thanks for your contribution. I think the RISCV specific test should be skipped on non-riscv platform rather than mock RISCV behaviors. They could run on RISC platform either manually or on a RISCV runner if that is part of the plan. Thanks!

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants