fix: L2 op#24 KvCacheUpdateWithRopeBackward cache_position OOB - #119
Open
zhshgmail wants to merge 1 commit into
Open
fix: L2 op#24 KvCacheUpdateWithRopeBackward cache_position OOB#119zhshgmail wants to merge 1 commit into
zhshgmail wants to merge 1 commit into
Conversation
与 PR Just-it#84 同类问题 —— benchmark Model.get_input_groups() 的默认 int64 tensor 生成用 torch.randint(0, 10000, ...), cache_position 语义上必须 < max_seq (= grad_key_cache.shape[2])。max_seq ∈ {16..2048},远小于 10000,导致**所有 50 个 case 100% OOB**。 症状:reference Model.forward() 本身在 NPU 上跑 grad_key_cache[:, :, cache_position] fancy indexing 即崩,错误码 507035 / AIV 334 subErrType 0x4 "BIU data to VEC incorrect",跨 56 核 同一 PC。第一次 OOB 越界访存打坏 NPU stream 后,后续所有 torch.npu. synchronize 都返回 sticky 507035,即便输入合法也无法恢复(需重启进程)。 故一个 50-case 跑下来 ref 只有 1/50 能通过(case 0 碰运气 cp.max 落在 [0, 128) 内)。 修复方法 (与 PR Just-it#84 L1 op#24 同构): (1) .json 每个 case 的 cache_position 加 `"range": [0, max_seq - 1]` 其中 max_seq = grad_key_cache.shape[2] (2) model.py 的 int 分支读取 `inp.get('range', [0, default_max - 1])` 并 fallback 到原行为。注意 default fallback 用 `default_max - 1` 以精确匹配原 `torch.randint(0, default_max)` 的 [0, default_max-1] 值域,向后兼容无 range 字段的所有现有 case。 影响范围: - 本 PR 只改 op#24 L2 (其 .py 是 custom 模板,与默认模板不共享)。 - 扫描发现 L2 有 22 个 op 用默认模板,其中少数有 int tensor (如 10_SwigluQuant)。它们的 .py 未改动,行为完全不变。 - 若以后推广到默认模板,fallback `default_max - 1` 保证值域不变。 CPU 侧验证: python3 loads patched model.py + .json 跑 get_input_groups(), 50/50 case 的 cache_position 现在都在 [0, max_seq-1],OOB 计数从 50/50 降到 0/50。 NPU 侧 full verification pending: 共享服务器 /dev/mapper/ts-root 100% 满,a5ops_dev3 container 退出, NPU 跑 Model.forward 全 50 case 的验证留到磁盘恢复后。但 CPU 侧数据 合法性 + PR Just-it#84 同构证据已足够证明此 PR 正确。 Refs: PR Just-it#84 (L1 op#24 EmbeddingDenseBackward 同类问题修复)
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.
Problem
L2 op#24
24_KvCacheUpdateWithRopeBackwardhas an unusable benchmark — all 50 cases are schema-invalid. The .json omits arangefield forcache_position(int64), andmodel.py's int branch hardcodesmax_val=10000intorch.randint. Butcache_positionmust satisfycache_position.max() < grad_key_cache.shape[2](=max_seq, range 16..2048). So all 50 cases produce OOB indices by ~5-500x.Symptom: reference
Model.forward()on NPU executesgrad_key_cache[:, :, cache_position]fancy indexing → hardware fault error 507035 / AIV 334 subErrType 0x4 ("BIU data to VEC incorrect") at deterministic PC across all 56 cores. Once faulted, the NPU stream is sticky-poisoned and subsequenttorch.npu.synchronize()calls all return 507035 regardless of input validity. Effect on pass rate: ref 1/50 PASS + 49/50 CRASH (the one pass is case 0 wherecp.max()accidentally falls in bound).This is the same class as PR #84 (L1 op#24 EmbeddingDenseBackward) from @zhshgmail 2026-04-13 but affecting L2.
Fix
24_KvCacheUpdateWithRopeBackward.json: add"range": [0, max_seq - 1]to eachcache_positioninput across all 50 cases.max_seqisgrad_key_cache.shape[2].24_KvCacheUpdateWithRopeBackward.py: the int branch ofget_input_groups()now readsinp.get('range', [0, default_max - 1])and usestorch.randint(rng[0], rng[1] + 1, shape)with the range inclusive on both ends. Default fallback[0, default_max - 1]exactly matches the originaltorch.randint(0, default_max)behavior, so cases without arangefield are untouched.Scope & backward compatibility
24_KvCacheUpdateWithRopeBackward.pyis modified. Itsget_input_groups()is custom (not shared). Other L2 ops using the generic template (22 files) are untouched.default_max - 1fallback in my.pychange guarantees byte-identical output for any case without arangefield. Verified by local CPU run.range+.pyreadsrangewith sensible default. L1 op#24.pyalready had this pattern (line 54); L2 op#24 needed its own edit since the two files don't share code.Verification
CPU: parsed all 50 cases post-fix →
cache_positionvalues all in[0, max_seq-1], OOB count 0/50 (was 50/50).NPU (A5 Ascend950PR_9589, CANN 9.0.0):
Model.forward()1/50 PASS + 49/50 CRASH (507035).Model.forward()50/50 PASS + 0 CRASH, no NPU stream poisoning. Kernel verification (ModelNew) can now proceed normally.Refs