[WS1][kernels] Deterministic attention Ascend C kernel - #320
Conversation
Signed-off-by: chenyang <2082464740@qq.com> (cherry picked from commit 093339d)
Signed-off-by: Zhang Jian <jianmusings@gmail.com> (cherry picked from commit 7a763dd295ce0541f15c4ef717d3137a48a33319)
- csrc/ascend/attention/deterministic_attention_ascend.asc: Ascend C batch-invariant standard-softmax attention forward (one AI-core block per (b, q_head, row), fixed 64-key tile order, two-pass streaming reduction, no split-K); bf16/fp16, D=128, GQA, causal + key_padding_mask - rl_engine/kernels/ops/ascend/attention/deterministic_attn.py: autograd wrapper (Ascend C forward + reference backward via NativeAttentionOp) - registry: ASCEND_DETERMINISTIC_ATTENTION op backend; npu priority map gains attention/attn/kv_cache_attention entries - gtest spec: attention gains an ascend candidate - tests/test_attention_ascend.py, benchmarks/benchmark_attention.py, docs/operators/attention.md, _C_npu.pyi stub - setup.py: recursive .asc glob so kernels may live in subdirectories (cherry picked from commit 7970761c947bbd30d647d55356701faff6c2d04e)
- fully-masked rows: track anyValid in pass 1 and short-circuit to out = 0 / lse = -inf instead of letting exp(NEG_INF - NEG_INF) = exp(0) leak weight into P.V (mirrors the Triton reference guards) - lse of invalid rows is true -inf (matches the reference max_score/log(0) path), not -FLT_MAX - ComputeScores: ReduceSum lands directly in the score lanes and the whole tile syncs once (S_V before, V_S after) instead of per-key WaitVector round trips - tests: independent generators per q/k/v (batch size must not shift the k/v stream), non-causal same-content position sweep, dispatch test now accepts the Ascend deterministic op
|
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: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…rministic-attention-test Resolve conflicts with the merged PR RL-Align#297 (batch-invariant logp Ascend): - logp kernel/op/tests/docs/benchmark take the upstream reviewed versions; the kernel's PYBIND11_MODULE stays in the ops_npu.asc aggregator - registry keeps the upstream cpu-inheritance for the npu platform and adds the attention override on top - setup.py keeps the recursive .asc glob; device.py keeps the upstream broader exception probe - _C_npu.pyi exposes both operator stubs
|
I tested this PR on Ascend A3. Correctness looks good, but I observed a significant performance issue with the current Ascend attention kernel. CorrectnessBoth BF16 and FP16 forward checks passed:
Forward + gradient checks also passed for both BF16 and FP16, with zero error for q/k/v gradients. The full Ascend attention test suite also passed: So I did not find a correctness issue in my environment. PerformanceEnvironment: I ran: BF16 results:
The Ascend kernel is around 200–260× slower than the native path in these test cases. There is also a clear scaling pattern: The measured latency is approximately proportional to |
Latest Status [19 Aug 2026]
Ready for review.
Summary
Following the previous deterministic attention implementation (CUDA issue #147
DeterministicAttentionOp+ Triton referenceTritonBatchInvariantAttentionOp, i.e.rlkernel.attention.deterministic_core.v1), this PR implements an Ascend NPU version:Forward is implemented as an Ascend C (CANN) kernel,
_C_npu.deterministic_attention_ascend:(b, q_head, row)is processed end-to-end by a single AI Core block, using two streaming reduction passes in a fixed 64-key tile order:(m, l, u)summary merge. Therefore, the reduction tree for each row depends only onSkv / D / mask, and is independent of batch size or block scheduling/allocation. This makes it batch-invariant, corresponding to thenum_splits=1approach described in the blog.key_padding_mask. The output dtype matches the input dtype and an FP32 LSE is returned. Fully masked rows produce output 0 andlse = -inf, consistent with the guard in the Triton reference.Backward uses the VJP of
NativeAttentionOp.forward_fp32(structurally identical to the gtest gold implementation, with zero gradient error), reusing q/k/v/mask saved during forward. Triton is unavailable on NPU, so this follows the same portable-backward idea as the Triton op.Integrated using the
.ascextension pattern from PR [draft][WS1][kernels] Batch-invariant logprob Ascend C Kernel #297:ASCEND_DETERMINISTIC_ATTENTIONto the registry."npu"dispatch forattention/attn/kv_cache_attention.ascendcandidate to the gtest spec._C_npu.pyistub.Build notes (same pattern as PR #297)
Each
.ascsource file can define only onePYBIND11_MODULE, because linking multiple sources with Bisheng causes a duplicatePyInit__C_npuerror.Therefore, pybind registrations for all operators are consolidated in
csrc/ascend/ops_npu.asc, while individual kernel files contain only the kernel and host forward functions.The
.ascglob insetup.pywas also changed to recursive (**/*.asc), allowing kernels to follow the CUDA-style directory structure undercsrc/ascend/attention/.Files
csrc/ascend/attention/deterministic_attention_ascend.asccsrc/ascend/ops_npu.asc_C_npupybind registration file (logp + attention). New.csrc/ascend/batch_invariant_logp_ascend.ascPYBIND11_MODULE, which is moved to the aggregated registration file. Kernel logic is unchanged.rl_engine/kernels/ops/ascend/attention/deterministic_attn.pyrl_engine/kernels/registry.pyASCEND_DETERMINISTIC_ATTENTION; addsattention/attn/kv_cache_attentiondispatch for the"npu"platform.rl_engine/kernels/gtest/operator_specs.pyascendcandidate for attention.tests/test_attention_ascend.pytests/test_attention.pybenchmarks/benchmark_attention.pydocs/operators/attention.mdrl_engine/_C_npu.pyideterministic_attention_ascendstub.setup.py.ascglob to**/*.asc.Test
gtest
pytest
Test results
Environment: 8× Ascend 910, CANN 8.5.1 (Bisheng), torch 2.10.0 + torch_npu 2.10.0.
suite=attention passed=True pass_rate=1.0000suite=attention passed=True pass_rate=1.0000suite=attention passed=True pass_rate=1.0000(q/k/v gradient errors are all 0)suite=attention passed=True pass_rate=1.0000(q/k/v gradient errors are all 0)suite=batch_invariant_logp passed=True pass_rate=1.0000tests/test_attention_ascend.pygtest: attention ascend bf16 (raw)
gtest: attention ascend fp16 (raw)
gtest: attention ascend fp16 --check-grad (raw)
gtest: attention ascend bf16 --check-grad (raw)
gtest: batch_invariant_logp ascend bf16 regression (raw)
pytest: tests/test_attention_ascend.py (raw)
benchmark: benchmarks/benchmark_attention.py (raw)
Notes
ruff checkpasses for all modified files.