[WS1][Ascend] [Qwen3-8b] Fused logp ops - #370
Open
zhangj1an wants to merge 1 commit into
Open
Conversation
zhangj1an
requested review from
EthanZero2Hero,
Flink-ddd,
KJLdefeated,
bitborne and
inaniloquentee
as code owners
September 1, 2026 05:10
|
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 |
Mirror the CUDA deterministic logp kernel (csrc/deterministic_logp_kernel.cu)
with an Ascend C forward in csrc/ascend/fused_logp_ascend.asc: the same
two-pass fixed-order reduction (row max, then sum-exp) in fp32, fp32 output
matching DeterministicLogpCUDAOp's contract, out-of-range targets -> 0.0.
Every row is reduced end-to-end by one AI-core block with a fixed tile
order, so 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 and transcendental implementations are
platform-specific).
Wrapper mirrors the CUDA _FusedLogpAutograd bridge (lead-shape support,
row-local fp32 VJP backward, native fallback). Registered as the ascend
candidate in the logp gtest spec and in the registry's NPU priority map.
Ports the shared-module Ascend build (npu_module.cpp + setup.py bisheng)
and the check_operator --device npu support.
Verified on Ascend 910 / CANN 8.5.1:
- gtest logp ascend candidate fp32/bf16/fp16, output + gradient: all pass
(fp32 output max_abs 9.5e-7 vs atol 1e-5; grads <= 7.6e-6).
- Batch invariance bitwise: batch 1 vs {2,4,16,300}, positions 1..7,
multi-tile V=10000, repeated runs.
- pytest tests/test_logp_ascend.py: 22 passed.
- Regression: test_batch_invariant_logp.py 44 passed, test_dispatch.py
13 passed.
style: apply black formatting to files carried unformatted on main
(vllm_runtime.py, flash_attn.py, _C_npu.pyi) so the PR head passes
pre-commit CI.
zhangj1an
force-pushed
the
feat/ascend-deterministic-logp
branch
from
September 1, 2026 05:41
57d74aa to
d18e7b8
Compare
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 deterministic fused logp (
csrc/deterministic_logp_kernel.cu+DeterministicLogpCUDAOp) to Ascend NPU:_C_npu.fused_logp_ascend): mirrors the CUDA deterministic kernel's math —logp[n] = logits[n, target[n]] - logsumexp(logits[n, :])— with the same two-pass fixed-order reduction: row max over a fixed tile order, thensum(exp(x - max))over the same fixed tile order,lse = max + log(sum),logp = selected - lse, all in fp32. Out-of-range targets produce0.0, matching the CUDA kernel. Output is fp32, matchingDeterministicLogpCUDAOp's contract.MAX_BLOCKS=128). The instruction sequence for a row depends only onV, never onNor block assignment, so a row's logp is bitwise identical across batch sizes, row positions, and block assignments on the NPU (verified).expfis a software polynomial; the AscendExpis a hardware instruction). The guarantee is the same one the CUDA kernel provides on its platform: batch-invariant determinism. Measured drift vs the fp32 gold reference is ~1e-7.FusedLogpAscendOpmirrors the CUDA_FusedLogpAutogradbridge — lead-shape support ([..., V] -> [...]), row-local fp32 VJP backward (dlogits = grad * (one_hot(target) - softmax)), native fallback for non-NPU/non-contiguous inputs. Registered as the"ascend"candidate in thelogpgtest spec and asASCEND_FUSED_LOGPin the registry's NPU priority map ([ASCEND_FUSED_LOGP, PYTORCH_NATIVE]).csrc/ascend/npu_module.cppconsolidates the singlePYBIND11_MODULE(logp + fused logp);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(durable fresh-shell fix).scripts/check_operator.pygains--device npusupport.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_logp_ascend.asccsrc/ascend/npu_module.cpp_C_npupybind registration (batch_invariant_logp + fused logp). New.csrc/ascend/batch_invariant_logp_ascend.ascPYBIND11_MODULE(moved to the aggregated file). Kernel logic unchanged.rl_engine/kernels/ops/ascend/loss/logp.pyFusedLogpAscendOp(Ascend C forward + row-local fp32 VJP backward). New.rl_engine/kernels/ops/ascend/loss/__init__.pyrl_engine/_C_npu.pyifused_logp_ascendtype stub.rl_engine/kernels/gtest/operator_specs.py"ascend"candidate for thelogpop.rl_engine/kernels/registry.pyASCEND_FUSED_LOGPbackend + NPU priority map entry.rl_engine/tests/test_dispatch.pyscripts/check_operator.py--device npu/ auto-detect support.tests/test_logp_ascend.pydocs/operators/fused-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.
logpascend candidate, fp32 × 2x16x257, output + gradientlogpascend candidate, bf16 × 2x16x257, output + gradientlogpascend candidate, fp16 × 2x16x257, output + gradienttorch.equal)tests/test_logp_ascend.pytests/test_batch_invariant_logp.pyrl_engine/tests/test_dispatch.pygtest raw output (fp32, representative)
pytest: tests/test_logp_ascend.py (summary)
Notes
expfpolynomial vs the Ascend vectorExpinstruction). The Ascend kernel mirrors the formula and the two-pass fixed-order structure; on the NPU its own fixed tree makes the op batch-invariant bitwise, which is the property the WS1 contract'sforward_invariancerow requires (bitwise) — theforward_accuracyrow is tolerance-based (fp32 drift ~1e-7, well inside atol=1e-5)._FusedLogpAutograd, computed in fp32 and cast back to the input dtype; no cross-token reduction, so gradients are batch-layout independent.black/isort/flake8(line-length 100) pass for all modified Python files.