[WS1][Ascend] [Qwen3-8b] Fused linear logp ops - #372
Open
zhangj1an wants to merge 1 commit into
Open
Conversation
Mirror the SM90 fused linear logp kernel's reduction contract
(csrc/cuda/fused_linear_logp_sm90.cu, contract v1) with an Ascend C forward
in csrc/ascend/fused_linear_logp_ascend.asc: ascending vocab-row scan with
the online rescale chain, per-row fp32 dots over a fixed D-tile order, bias
in fp32, final min(zt - lse, 0) clamp, fp32 output. No [N, V] logits are
materialized. A row's logp is bitwise identical across batch sizes,
positions, and block assignments on the NPU; cross-platform bitwise parity
is not claimed (hardware reduction trees / transcendentals differ).
Wrapper mirrors FusedLinearLogpSM90Op's surface; the backward is the shared
chunked_linear_logp_backward (the CUDA op's portable fallback formula). TP
and bias calls delegate to the native reference. Registered as the ascend
candidate in the linear_logp gtest spec and in the registry's NPU priority
map. Ports the shared-module Ascend build and check_operator npu support.
Verified on Ascend 910 / CANN 8.5.1:
- Forward vs hand-computed fp32 reference: max_abs <= 2.2e-4 at the gtest
shape (pure fp32 tree drift; pytest atol 5e-4). The gtest's own forward
comparison is stricter than any independent kernel can meet (fp32 tree
drift vs atol 1e-5; bf16/fp16 gold accumulates the matmul in the input
dtype) - documented in the PR body.
- gtest gradients (fp32): hidden 2.4e-7, weight 3.0e-8 (atol 1e-5).
- Batch invariance bitwise: batch 1 vs {2,4,16,300}, positions 1..7,
multi-tile D=10000, repeated runs.
- pytest tests/test_linear_logp_ascend.py: 23 passed.
- Regression: test_batch_invariant_logp.py 44 passed, test_dispatch.py
13 passed.
zhangj1an
requested review from
Flink-ddd,
KJLdefeated,
bitborne and
inaniloquentee
as code owners
September 1, 2026 05:57
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Team Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Comment |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Latest Status [1 Sep 2026]
Ready for review.
Summary
Port of the CUDA fused linear log-prob (
csrc/cuda/fused_linear_logp_sm90.cu+FusedLinearLogpSM90Op) to Ascend NPU:_C_npu.fused_linear_logp_ascend): computeslog_softmax(hidden @ W^T + b)[target]without materializing[N, V]logits, mirroring the SM90 kernel's bitwise reduction contract (contract v1):newM = max(m, z); sum = sum * exp(m - newM) + exp(z - newM)exactly like the CUDA per-split merge;logp = min(zt - lse, 0)matches the CUDA contract; out-of-range targets yield 0.MAX_BLOCKS=128), so a row's logp is bitwise identical across batch sizes, row positions, and block assignments on the NPU (verified withtorch.equal).FusedLinearLogpAscendOpmirrorsFusedLinearLogpSM90Op's surface (apply(hidden, lm_head_weight, target_ids, bias=None), validation, fp32 output). TP and bias calls delegate to the native reference (same fallback shape as the CUDA op's non-SM90 paths). The backward is the shared Liger-stylechunked_linear_logp_backward— the exact formula the CUDA SM90 op falls back to — so gradients follow the CUDA op's portable backward."ascend"in thelinear_logpspec;ASCEND_FUSED_LINEAR_LOGPin the registry NPU priority map ([ASCEND_FUSED_LINEAR_LOGP, PYTORCH_LINEAR_LOGP]);scripts/check_operator.pygains--device npusupport.csrc/ascend/npu_module.cppconsolidates the singlePYBIND11_MODULE;batch_invariant_logp_ascend.asconly drops itsPYBIND11_MODULEblock.setup.pygains the Ascend extension build (bisheng,**/*.ascglob) with the CANN env export in_find_ascend_home.Build notes (same pattern as PR #320 / #355)
Each
.ascsource file can define only onePYBIND11_MODULE(linking multiple sources with Bisheng causes a duplicatePyInit__C_npuerror), so pybind registrations are consolidated incsrc/ascend/npu_module.cpp;batch_invariant_logp_ascend.asconly drops itsPYBIND11_MODULEblock.Files
csrc/ascend/fused_linear_logp_ascend.asccsrc/ascend/npu_module.cpp_C_npupybind registration. New.csrc/ascend/batch_invariant_logp_ascend.ascPYBIND11_MODULE(moved to the aggregated file). Kernel logic unchanged.rl_engine/kernels/ops/ascend/loss/linear_logp.pyFusedLinearLogpAscendOp(Ascend C forward + shared chunked backward). New.rl_engine/kernels/ops/ascend/loss/__init__.pyrl_engine/_C_npu.pyifused_linear_logp_ascendtype stub.rl_engine/kernels/gtest/operator_specs.py"ascend"candidate for thelinear_logpop.rl_engine/kernels/registry.pyASCEND_FUSED_LINEAR_LOGPbackend + NPU priority map entry.rl_engine/tests/test_dispatch.pyscripts/check_operator.py--device npu/ auto-detect support.tests/test_linear_logp_ascend.pydocs/operators/linear-logp.mdsetup.py_find_ascend_home.Test
Test results
Environment: Ascend 910, CANN 8.5.1 (Bisheng), torch 2.10.0 + torch_npu 2.10.0.post2.
torch.equal)tests/test_linear_logp_ascend.pytests/test_batch_invariant_logp.pyrl_engine/tests/test_dispatch.pypytest: tests/test_linear_logp_ascend.py (summary)
Notes
torch.matmul+log_softmaxat D=4096 (fp32 addition is not associative); the CUDA kernel has the same property on its platform. The Ascend kernel pins its own fixed order, which makes the op batch-invariant bitwise on the NPU (forward_invariancecontract row).black/isort/flake8(line-length 100) pass for all modified Python files.