Repository navigation
Conversation
自动审查进度
更新时间:2026-10-22 11:54 北京时间。运行期间约每 5 分钟更新;阶段任务数会随核验展开,不能当作整轮完成百分比。 |
| # Producer only: QA completion still orders this kernel. The following | ||
| # QB may initialize early but must GDC-wait before reading Q/scales. | ||
| tl.inline_asm_elementwise( | ||
| "griddepcontrol.launch_dependents; // $0", |
There was a problem hiding this comment.
[P2] QB 入口级 PDL 触发先于全部 Q/SF 写入,读序安全单点依赖快照外 DeepGEMM 消费端读前 gdc.wait,门控仅检查 get_pdl() 且无构建绑定
部署方已使进程内 deep_gemm.get_pdl() 为真(生产代码从不调用 set_pdl,需运维预置),再开 DSV41_FULL_DECODE_MULTISTREAM=1 与 DSV41_FULL_DECODE_QB_PDL=1,且满足 FULL 门控(TP1、SM10x、H32/D128/TopK512、merged_qb 存在、eager 预热后,attention_v41.py:3170 进入 try_full_decode)时,FULL 源层每步解码与每次图重放都经过该 programmatic 边;若所装 DeepGEMM 构建的 PSS 消费内核在 gdc.wait 之前读取 A/scales,即持续读到未写入数据。fallback 路径(attention_v41.py:3186)不传 qb_pdl,默认两开关均 "0" 时行为与 base 一致。
base 无触发指令、无 full_overlap.py、compute_qkv 不传 pdl(base:98)、try_project_quantized_qkv 无 pdl 参数(base:85);head 新增入口级触发(:29-39)并经 full_overlap.py:172 → compute_qkv.py:99 → query_norm_quant(pdl) → PDL=pdl(:93)接线至 merged.forward_quantized(compute_qkv.py:113)的 deep_gemm 调用,首次把消费端可执行窗口从『生产者完成/数据已写出』提前到『生产者入口、Q/SF 完全未写入』。
PDL=True 时 _query_norm_quant_kernel 在入口、任何 Y/Q/SF store(:47/:57/:65)之前发射 griddepcontrol.launch_dependents(:33),允许同流以 PSS 属性启动的 merged QB deep_gemm.fp8_fp4_gemm_nt 提前执行其 wait 之前的代码;触发与 QB GEMM 之间(compute_qkv.py:100-112)仅主机端切片/getattr/profiler 上下文与 torch.empty,无其他设备内核发射。消费端调用(_v41_merged_qb.py:65-70)不传任何同步参数,是否读前等待完全由外部库内核决定。_qb_pdl_enabled 只检查两个环境变量、merged_qb 存在与 hasattr(get_pdl) 且为真(full_overlap.py:23-33),不校验消费内核 wait 位置、版本或构建。
若决定性未知被否定(消费端读前不 wait):QB 读到未写出的 Q/SF,q/index_q 及其后全部 attention/解码输出静默数值错误,随捕获的 CUDA Graph 持续重放,生产路径无运行时校验可拦截;若消费端如文档声称在读前 wait,则仅重叠初始化,无正确性影响。严重度按未知成立时的后果评估。
rtp_llm/models_py/modules/dsv41/_v41_query_quant.py:33:"griddepcontrol.launch_dependents; // $0",
rtp_llm/models_py/modules/dsv41/_v41_query_quant.py:47:tl.store(Y + row * D + cols, y, cols < D)
rtp_llm/models_py/modules/dsv41/_v41_query_quant.py:57:tl.store(Q + row * D + cols, tl.reshape(quant, (BLOCK,)), cols < D)
rtp_llm/models_py/modules/dsv41/_v41_query_quant.py:27:PDL: tl.constexpr = False,
rtp_llm/models_py/modules/dsv41/_v41_query_quant.py:93:PDL=pdl,
rtp_llm/models_py/modules/dsv41/_v41_query_quant.py:31:# QB may initialize early but must GDC-wait before reading Q/scales.
rtp_llm/models_py/modules/dsv41/_v41_query_quant.py:26:BLOCK: tl.constexpr,
rtp_llm/models_py/modules/dsv41/_v41_query_quant.py:85:def try_project_quantized_qkv(attn, x):
rtp_llm/models_py/modules/dsv41/fp8/decode/full_overlap.py:25:os.environ.get("DSV41_FULL_DECODE_QB_PDL", "0") != "1"
rtp_llm/models_py/modules/dsv41/fp8/decode/full_overlap.py:33:return hasattr(deep_gemm, "get_pdl") and deep_gemm.get_pdl()
rtp_llm/models_py/modules/dsv41/fp8/decode/full_overlap.py:172:qb_pdl=_qb_pdl_enabled(mega),
rtp_llm/models_py/modules/dsv41/fp8/decode/compute_qkv.py:99:quantized_qkv = try_project_quantized_qkv(attn, x, pdl=qb_pdl)
rtp_llm/models_py/modules/dsv41/fp8/decode/compute_qkv.py:113:q, index_q = merged.forward_quantized(*qr_quantized)
rtp_llm/models_py/modules/dsv41/fp8/decode/compute_qkv.py:98:quantized_qkv = try_project_quantized_qkv(attn, x)
rtp_llm/models_py/modules/dsv41/fp8/_v41_merged_qb.py:65:deep_gemm.fp8_fp4_gemm_nt(
rtp_llm/models_py/modules/dsv41/fp8/attention_v41.py:3170:output = try_full_decode(
docs/benchmark/dsv41_full_layer_optimize.md:111:DeepGEMM QB consumer must launch with programmatic serialization and wait before
docs/benchmark/dsv41_full_layer_optimize.md:371:cudaGridDependencySynchronize(), while actual A/B TMA loading follows it.
docs/benchmark/dsv41_full_layer_optimize.md:129:2.8.2+30e85d9.cu132, and a FlashMLA wheel exposing Mega Attention.
deps/requirements_torch_gpu_cuda13.txt:40:http://artlab.alibaba-inc.com/1/pypi/rtp_llm/deep_gemm/deep_gemm-2.8.2%2Bad62a90.cu132-cp310-cp310-linux_x86_64.whl
rtp_llm/test/perf_test/dsv41_full_decode_pdl.py:191:raise RuntimeError(f"Expected one Q norm -> QB edge, got {qb_edges}")
rtp_llm/test/perf_test/dsv41_full_decode_pdl.py:268:torch.testing.assert_close(value, ref, rtol=0, atol=0, msg=key)
rtp_llm/test/perf_test/dsv41_full_decode_pdl.py:105:deep_gemm.set_pdl(library_pdl)
rtp_llm/models_py/modules/dsv41/fp8/test/test_v41_global_overlap.py:572:if not hasattr(deep_gemm, "get_pdl") or not deep_gemm.get_pdl():
rtp_llm/models_py/modules/dsv41/fp8/test/test_v41_global_overlap.py:192:dg.set_pdl.assert_not_called()
rtp_llm/models_py/bindings/cuda/kernels/scaled_fp8_quant.cu:106:asm volatile("griddepcontrol.launch_dependents;");
rtp_llm/models_py/bindings/cuda/kernels/scaled_fp8_quant.cu:83:asm volatile("griddepcontrol.wait;");
rtp_llm/models_py/bindings/cuda/launch_utils.cc:14:enablePDL = !StaticConfig::user_disable_pdl;
rtp_llm/models_py/modules/factory/fused_moe/impl/cuda/executors/deepgemm_hybrid_executor.py:853:down_input_fp8, down_input_scale = trt_fp8_quantize_128(down_input, False)
rtp_llm/models_py/modules/factory/fused_moe/impl/cuda/executors/deepgemm_hybrid_executor.py:864:m_grouped_fp8_gemm_nt_contiguous(
rtp_llm/models_py/modules/dsv41/utils.py:84:deep_gemm.fp8_fp4_gemm_nt(
rtp_llm/models_py/modules/dsv41/_v41_query_quant.py:105:projected = linear(x)
docs/benchmark/dsv41_full_layer_optimize.md:44:| deep_gemm.get_pdl() | Must already be true for that producer trigger to be enabled |
待确认:部署所用 DeepGEMM 构建的 fp8_fp4_gemm_nt 在 get_pdl()=true 时是否以 programmatic 序列化属性启动、及其 gdc.wait 相对首次 A/scales 读取的位置——库源/二进制不在快照(3rdparty/deep_gemm 仅两个无关补丁),仓钉 wheel ad62a90(deps:40)与文档验证构建 30e85d9(docs:129)哈希不同,门控(full_overlap.py:33)无任何版本绑定;这是唯一能坐实或推翻本失败的事实
建议:在 _qb_pdl_enabled 中把门控从 hasattr+get_pdl() 收紧为绑定经核验的 DeepGEMM 版本/构建白名单(与 runner 验证产物一致),或启用前要求复现 runner 式图边+PTX 审计与逐位探针通过;或将触发点后移至 Q/SF store 之后(对齐 scaled_fp8_quant.cu:106 的仓内 post-store 纪律),使消费端即使缺读前 wait 也退化为可见性竞态而非读取未写入数据;维持双开关默认关闭。
评审版本:597c930afcb4
| with torch.cuda.device(x.device): | ||
| capturing = torch.cuda.is_current_stream_capturing() | ||
| streams = (_GLOBAL_COMPUTE_STREAMS, _INDEXER_STREAMS) | ||
| if capturing and any(device not in cache for cache in streams): |
There was a problem hiding this comment.
[P2] 新增 FullOverlapCPUTest.test_cold_capture_and_failed_producer 在无可见 GPU 环境因 try_full_decode 对 Mock 缓存流重建真实 CUDA 流而确定性 ERROR
在无可见 GPU 的机器(纯 CPU 节点或隐藏 CUDA 设备、torch 可导入)以 pytest/unittest 直接运行 head 的 test_v41_global_overlap.py(支持 main 直接执行,640 行);即作者文档 268-275 行自述采用的 GPUs hidden 验证实践。bazel 目标因 exec_properties 绑定 GPU 节点(BUILD:97-100)且 pytest_main 要求足量 CUDA 设备(pytest_main.py:45-57),默认 bazel 路径不进入 CPU-only 场景。
base 的 decode/ 目录无 full_overlap.py,base 测试文件仅含 GlobalOverlapCPUTest(31 行)与 GlobalOverlapCudaTest(177 行)两类;head 新增该模块、FullOverlapCPUTest 与该用例,并把侧流获取从姊妹函数 start_global_decode 的『缓存命中即直取』(head global_overlap.py:87 保持不变)改为『无条件经 _get_process_cuda_stream 复核并可重建真实流』。attention.py 的 _get_process_cuda_stream 本身 base→head 未变(两侧 165-175 行逐行一致),变化在于新调用方使其对 Mock 缓存命中也生效。
head 新增 try_full_decode 的冷捕获检查(full_overlap.py:117)仅在 device 缺失于任一流缓存时早退;测试向两个缓存注入 {0: Mock}(test:271/273)均命中,故不早退,119-121 行随即对 _GLOBAL_COMPUTE_STREAMS 与 _INDEXER_STREAMS 无条件调用 _get_process_cuda_stream。该函数在缓存命中时仍复核 stream.device.index != device_index(attention.py:172);Mock 的 device.index 为自动生成属性、与整数 0 比较恒不等,于是执行真实 torch.cuda.Stream(device=cuda:0) 构造(attention.py:173)。测试已 patch _cuda_device_index、torch.cuda.current_stream/device/stream/is_current_stream_capturing 等全部入口(test:274-284),但未 patch torch.cuda.Stream 或 _get_process_cuda_stream(该构造在测试文件中仅出现于带 skipUnless 守护的 CUDA 类 364/591 行),所在类 FullOverlapCPUTest(177 行)无任何跳过装饰;无可见 GPU 时第一阶段(capturing=True)即在流规范化处抛异常,用例以 ERROR 结束。
该新增用例在 GPU 隐藏环境确定性 ERROR(测试层面失败,非生产运行时缺陷),污染 CPU-only 套件结果、阻断文档自述的离线验证流程全绿(12 项选定 gate/lifetime 测试中 11 项通过、此项报错)。文档 270-274 行将其表述为 existing/predates the PDL patch,相对本 PR base→head 不成立(测试类与模块均为新增),可能误导维护者按基线遗留问题搁置。生产路径不受影响:真实流对象的 device.index 与缓存键一致,attention.py:172 复核通过即复用缓存,无重建或流churn。
rtp_llm/models_py/modules/dsv41/fp8/decode/full_overlap.py:117: if capturing and any(device not in cache for cache in streams):
rtp_llm/models_py/modules/dsv41/fp8/decode/full_overlap.py:120: _get_process_cuda_stream(cache, x.device) for cache in streams
rtp_llm/models_py/modules/dsv41/fp8/attention.py:172: if stream is None or stream.device.index != device_index:
rtp_llm/models_py/modules/dsv41/fp8/attention.py:173: stream = torch.cuda.Stream(device=torch.device("cuda", device_index))
rtp_llm/models_py/modules/dsv41/fp8/test/test_v41_global_overlap.py:253: def test_cold_capture_and_failed_producer(self):
rtp_llm/models_py/modules/dsv41/fp8/test/test_v41_global_overlap.py:266: main, glob, aux = Mock(), Mock(), Mock()
rtp_llm/models_py/modules/dsv41/fp8/test/test_v41_global_overlap.py:267: glob.cuda_stream, aux.cuda_stream = 123, 456
rtp_llm/models_py/modules/dsv41/fp8/test/test_v41_global_overlap.py:271: full_overlap, "_GLOBAL_COMPUTE_STREAMS", {0: glob}
rtp_llm/models_py/modules/dsv41/fp8/test/test_v41_global_overlap.py:273: full_overlap, "_INDEXER_STREAMS", {0: aux}
rtp_llm/models_py/modules/dsv41/fp8/test/test_v41_global_overlap.py:177:class FullOverlapCPUTest(unittest.TestCase):
rtp_llm/models_py/modules/dsv41/fp8/test/test_v41_global_overlap.py:300:@unittest.skipUnless(torch.cuda.is_available(), "CUDA required")
rtp_llm/models_py/modules/dsv41/fp8/test/test_v41_global_overlap.py:31:class GlobalOverlapCPUTest(unittest.TestCase):
rtp_llm/models_py/modules/dsv41/fp8/decode/global_overlap.py:78: stream = _GLOBAL_COMPUTE_STREAMS.get(device_index)
rtp_llm/models_py/modules/dsv41/fp8/decode/global_overlap.py:87: stream = _GLOBAL_COMPUTE_STREAMS.get(device_index)
docs/benchmark/dsv41_full_layer_optimize.md:270:gate/lifetime tests, 11 passed with GPUs hidden. The existing
docs/benchmark/dsv41_full_layer_optimize.md:273:_get_process_cuda_stream replaces it. It errors without a visible GPU. This
docs/benchmark/dsv41_full_layer_optimize.md:271:FullOverlapCPUTest.test_cold_capture_and_failed_producer still attempts to
rtp_llm/models_py/modules/dsv41/fp8/decode/full_overlap.py:134: global_stream.wait_stream(current)
建议:首选测试侧最小修复:为 glob/aux 设置 device.index=0(Mock 支持链式属性赋值)或 device=torch.device('cuda', 0),使 attention.py:172 复核命中、Mock 被直接复用,两阶段断言原样保留且全流程 CPU 安全;或在测试中 patch attention._get_process_cuda_stream/torch.cuda.Stream;或将该用例移入带 skipUnless(torch.cuda.is_available()) 的类。生产侧可令 try_full_decode 与 start_global_decode 一致:缓存命中先 .get() 直取、未命中再走 _get_process_cuda_stream,消除姊妹函数分歧。同时把文档 270-274 行 existing/predates the PDL patch 的表述更正为相对上游 base 由本分支引入,并补记 GPU 可见环境下该用例的实测结果。
评审版本:597c930afcb4
| # Producer only: QA completion still orders this kernel. The following | ||
| # QB may initialize early but must GDC-wait before reading Q/scales. | ||
| tl.inline_asm_elementwise( | ||
| "griddepcontrol.launch_dependents; // $0", |
There was a problem hiding this comment.
[P2] FULL decode Q-norm 入口 PDL 触发把 QB 提前启动的读取安全委托给快照外 DeepGEMM 消费端 wait 契约;门仅校验策略位,且构建钉扎 wheel 与文档验证版本不一致
SM10x(capability==10,_v41_decode_global.py:299)、TP1、Index 32×128/TopK512、存在 merged_qb 的 DSv4.1 FULL1/FULL2 解码;部署设置 DSV41_FULL_DECODE_MULTISTREAM=1 与 DSV41_FULL_DECODE_QB_PDL=1,且 DG 全局策略已由部署侧置真(docs:44 列为启用条件,生产代码只读不改,测试断言 set_pdl 未被调用)。eager 预热与 CUDA Graph 捕获/回放均可达(仅冷捕获整体回退,full_overlap.py:117-130)。
base 的该内核无 PDL 分支、query_norm_quant 签名无 pdl 参数(base :56)、compute_qkv.py:98 调用不传 pdl,且 base 全仓 dsv41 无任何 launch_dependents——该边只能等生产者完整完成后隐式释放,文档实测 PDL off 时 norm/QB 零重叠(docs:364),消费端 wait 位置对本边正确性无关。head 新增入口触发并经 full_overlap.py:172→compute_qkv.py:99 传入,首次打开实测 1.27-4.13us 的提前启动窗口(docs:365),使外部消费端 wait 成为本边正确性的必要条件。
head 在 _query_norm_quant_kernel 入口、首个 tl.load(:42) 与全部 store(Y:47/Q:57/SF:65) 之前,按 PDL constexpr 发射 griddepcontrol.launch_dependents(:29-39)。当 deep_gemm.get_pdl() 策略为真时,同流紧随的 merged QB(_v41_merged_qb.py:65 直调 deep_gemm.fp8_fp4_gemm_nt,调用处不传任何 pdl 参数,启动属性完全由外部库决定)可以程序化串行属性在 Q-norm 尚未写出 Q/SF 时提前启动;正确性取决于该外部内核(及其 wait 前先启动的辅助内核)在读取 A(量化 Q)/SF(尺度)之前执行 griddepcontrol.wait。生产门 _qb_pdl_enabled(full_overlap.py:23-33) 只读 env 开关与策略位,不校验所装内核的 wait 位置;DeepGEMM 源码不在快照内,仓内无法核实。
若部署 DeepGEMM 在策略为真时确以程序化串行启动 QB,且该内核(或其 wait 前的辅助内核)在读取 A/SF 之前无 griddepcontrol.wait,则 QB 读到未完成的量化 Q 与尺度,Q/index 投影静默数值错误(无异常、无日志),污染该配置下全部 FULL 解码输出;若库遵守自身契约或对该形状未采用程序化启动,则触发仅提前启动时机或为无害空操作。
rtp_llm/models_py/modules/dsv41/_v41_query_quant.py:33:"griddepcontrol.launch_dependents; // $0",
rtp_llm/models_py/modules/dsv41/_v41_query_quant.py:42:x = tl.load(X + row * stride_x + cols, cols < D, 0).to(tl.float32)
rtp_llm/models_py/modules/dsv41/_v41_query_quant.py:31:# QB may initialize early but must GDC-wait before reading Q/scales.
rtp_llm/models_py/modules/dsv41/fp8/decode/full_overlap.py:25:os.environ.get("DSV41_FULL_DECODE_QB_PDL", "0") != "1"
rtp_llm/models_py/modules/dsv41/fp8/decode/full_overlap.py:33:return hasattr(deep_gemm, "get_pdl") and deep_gemm.get_pdl()
rtp_llm/models_py/modules/dsv41/fp8/decode/full_overlap.py:172:qb_pdl=_qb_pdl_enabled(mega),
rtp_llm/models_py/modules/dsv41/fp8/decode/compute_qkv.py:99:quantized_qkv = try_project_quantized_qkv(attn, x, pdl=qb_pdl)
rtp_llm/models_py/modules/dsv41/fp8/decode/compute_qkv.py:113:q, index_q = merged.forward_quantized(qr_quantized)
rtp_llm/models_py/modules/dsv41/fp8/_v41_merged_qb.py:65:deep_gemm.fp8_fp4_gemm_nt(
rtp_llm/models_py/modules/dsv41/_v41_query_quant.py:56:def query_norm_quant(x: torch.Tensor, weight: torch.Tensor, eps: float):
rtp_llm/models_py/modules/dsv41/fp8/decode/compute_qkv.py:98:quantized_qkv = try_project_quantized_qkv(attn, x)
docs/benchmark/dsv41_full_layer_optimize.md:364:The norm/QB pair had zero overlap with PDL off and
docs/benchmark/dsv41_full_layer_optimize.md:365:approximately 1.27-4.13 us overlap with the entry trigger, depending on the case.
arch_config/arch_select.bzl:99:"deep_gemm@http://artlab.alibaba-inc.com/1/pypi/rtp_llm/deep_gemm/deep_gemm-2.8.2%2Bad62a90.cu132-cp310-cp310-linux_x86_64.whl",
docs/benchmark/dsv41_full_layer_optimize.md:129:2.8.2+30e85d9.cu132, and a FlashMLA wheel exposing Mega Attention.
docs/benchmark/dsv41_full_layer_optimize.md:130:This is an observed environment, not proof that arbitrary mixed wheels work.
3rdparty/deep_gemm/BUILD:17:"deep_gemm/include/**/.h",
rtp_llm/test/perf_test/dsv41_full_decode_pdl.py:193:expected = int(cuda.CUgraphDependencyType.CU_GRAPH_DEPENDENCY_TYPE_PROGRAMMATIC)
rtp_llm/models_py/modules/dsv41/fp8/test/test_v41_global_overlap.py:192:dg.set_pdl.assert_not_called()
rtp_llm/models_py/modules/dsv41/fp8/_v41_decode_global.py:299:if torch.cuda.get_device_capability(x.device)[0] != 10:
docs/benchmark/dsv41_full_layer_optimize.md:44:| deep_gemm.get_pdl() | Must already be true for that producer trigger to be enabled |
待确认:部署所用 DeepGEMM wheel(含构建钉扎 2.8.2+ad62a90.cu132)在 get_pdl() 为真时 fp8_fp4_gemm_nt 的启动属性,及其主内核与 wait 前先启动的辅助内核中 griddepcontrol.wait 相对 A/SF 读取的位置——源码不在快照内,该两项前提直接决定所述静默数值错误是否存在
建议:在 _qb_pdl_enabled 或 FULL 预热/首次捕获阶段对所装 DeepGEMM 做完整性审计:仿照仓内 _v41_wo_a_quant.py 的 _VENDOR_HASHES sha256 校验惯例钉扎已验证版本/哈希白名单,或校验 QB 内核 PTX/SASS 中 griddepcontrol.wait 先于 A/SF 装载,不满足则回退为无触发;或首次启用时对 QB 输出与关断 PDL 的参考做逐位自校验(复用 runner compare 逻辑);同时将构建钉扎 wheel 与文档验证版本对齐并在验证记录中钉扎。
评审版本:597c930afcb4
| triton.next_power_of_2(table.shape[1]), | ||
| num_warps=4, | ||
| ) | ||
| schedule = _deep_gemm.get_paged_mqa_logits_metadata( |
There was a problem hiding this comment.
[P2] 一份 DG dense schedule 在一次前向内被多个自源层重复传入 fp8_fp4_paged_mqa_logits,只读契约在快照内无法核实
SM100+DeepGEMM FP4 paged 可用的 DSv4.1 FULL decode:各层 positions 为 decode_rope_metadata 每前向缓存的同一 converted 张量(默认 DSV41_REUSE_DECODE_ROPE=1),block table 为每步经 bind_attn_cache 绑定给所有层的同一 INDEXER_KV 张量的 [:B] 视图(data_ptr 不变),缓存键命中;默认串行路径每个自源层一次 DG dense 调用,同一 schedule 被逐层多次消费;非默认 DSV41_FULL_DECODE_MULTISTREAM=1 路径同样共享。head 测试明确验证不同 pool 的 owner 共享同一份 metadata。
base 每次 fp8_fp4_paged_indexer_score 内新建 request_ids/lengths/tables/schedule 并在同一调用内单次消费(base _indexer_score.py:212-238),score_decode_indexer 无 metadata 参数且调用点不传(base attention_v41.py:2905-2918);head 新增 get_decode_metadata 缓存与 metadata 旁路,一份 schedule 被一次前向内所有兼容自源层复用,DSV41_FUSE_INDEXER_METADATA 默认开。
get_decode_metadata 仅由一次前向内首个自源层调用 _deep_gemm.get_paged_mqa_logits_metadata 构建 schedule,并与 lengths/safe_table/expanded_table/request_ids 一起按 positions/table 的 data_ptr/shape/stride/dtype 与几何参数缓存(pool 刻意不入键);FULL 拓扑下其余自源层(layer_id==kv_source_layer_id 且 H32/D128)命中同键,把同一组张量传入各自层的 fp8_fp4_paged_indexer_score→fp8_fp4_paged_mqa_logits。若该 DG 调用改写任一入参,第二个自源层起将消费被改动的调度数据。
若 DG 在该调用中改写 schedule/lengths/tables/indices 任一入参:自第二个自源层起调度错乱,logits 行缺失或错位,token 选择静默错误,解码输出质量损坏且无崩溃信号;位于默认开启路径。
rtp_llm/models_py/modules/dsv41/fp8/_v41_decode_indexer.py:172: schedule = _deep_gemm.get_paged_mqa_logits_metadata(
rtp_llm/models_py/modules/dsv41/fp8/_v41_decode_indexer.py:180: cache[key] = (positions, table, result)
rtp_llm/models_py/modules/dsv41/fp8/_v41_decode_indexer.py:100: os.environ.get("DSV41_FUSE_INDEXER_METADATA", "1") != "1"
rtp_llm/models_py/modules/dsv41/fp8/_v41_decode_indexer.py:121: or not is_supported(positions.device, pool.shape[1])
rtp_llm/models_py/modules/dsv41/fp8/_indexer_score.py:240: schedule = metadata.schedule
rtp_llm/models_py/modules/dsv41/fp8/_indexer_score.py:247: scores = operation(
rtp_llm/models_py/modules/dsv41/fp8/attention_v41.py:2871: indexer_metadata = decode_indexer.get_decode_metadata(
rtp_llm/models_py/modules/dsv41/fp8/attention_v41.py:2868: and self.layer_id == self.kv_source_layer_id
rtp_llm/models_py/modules/dsv41/fp8/decode/rope_metadata.py:27: cache[position_key] = (positions, converted)
rtp_llm/models_py/modules/dsv41/fp8/attention_v41.py:2796: table = self._block_tables_by_type[INDEXER_KV][:B]
rtp_llm/models_py/modules/dsv41/block.py:602: with bind_attn_cache(self.attn, kv_cache, block_tables_by_type):
rtp_llm/models_py/modules/dsv41/fp8/test/test_v41_decode_indexer.py:468: # Owners with identical table views share metadata, never KV pools.
rtp_llm/models_py/modules/dsv41/fp8/test/test_v41_decode_indexer.py:570: self.assertIs(reused, plan)
rtp_llm/models_py/modules/dsv41/fp8/_indexer_score.py:219: schedule = _deep_gemm.get_paged_mqa_logits_metadata(
rtp_llm/models_py/modules/dsv41/fp8/attention_v41.py:2905: all_logits = decode_indexer.score_decode_indexer(
待确认:deep_gemm 包源码不在快照内(deepgemm_wrapper.py 仅从外部包解析符号,仓库内无其实现文件),无法核实 fp8_fp4_paged_mqa_logits 对 schedule_meta/lengths/tables/indices 是否只读
建议:每层打分前单独重建 schedule(其余融合字段仍可共享),或在仓库内补一个多层共享同一 metadata、连续多次真实 DG 消费的严格等值测试(对照 base 稀疏 plan 共享测试的 assertIs+等值模式),以钉住 dense API 只读语义。
评审版本:597c930afcb4
597c930 to
e78fc94
Compare
e78fc94 to
47b858e
Compare
8263c6a to
b74e9aa
Compare
Original-commits: 8e0b3f1
Original-commits: b57181a
Original-commits: 468b13b
Original-commits: 1c9d6d0
Original-commits: 58071aa
Original-commits: f743725
Original-commits: e13bc06
Original-commits: 4981fe6
Original-commits: d95fb9c
Original-commits: 8263c6a
Original-commits: d23fb76c
Remove the source-pinned FlashMLA consumer, patch, bindings and outgoing REUSE ready-QKV PDL handshake. Route attention through the existing FlashMLA wheel again. Keep REUSE QKV/index fusion, FULL multistream, metadata fusion and incoming QB PDL intact. Add CPU contracts for the retained producer plan and binding signature.
344d648 to
9b18300
Compare
dbfae22
into
alibaba:feature/dsv41-dev-main-202161013

Summary
Reduce DSv4.1 Flash decode overhead through FULL attention overlap, Reindex projection and sparse-selection fusion, and batched MTP/DSpARK preparation. Target branch:
feature/dsv41-dev-main-202161013.In the B64/rank, ctx32K, 4DP4EP workload below, the latest measured revision
667f2a13dimproves full-model fixed-batch decode TPS by 5.37% and reduces MTP step time by 5.09% against the retained same-day target baselinedd6dd239a. The baseline was not rerun in this attempt. A separate, earlier timeline analysis at438fbb2a0shows a 10.54% reduction in the layer-count-weighted Attention interval. Accuracy results are reported separately with their own reference revision.Attention Optimizations
9b183007adds compatibility with the locked device-header layout.2d454c4f; the incoming QB PDL path is retained.Other Decode Optimizations
bdb284c7and replayed as6df05f77f, this is included in the latest end-to-end measurement at667f2a13d; the earlier Attention and accuracy measurements do not include it.Configuration
DSV41_FULL_DECODE_MULTISTREAM1DSV41_FULL_DECODE_QB_PDL1DSV41_FUSE_INDEXER_METADATA1DSV41_FUSED_FRONT_PROJECTION,DSV41_FUSED_QB_POSTPROCESS10restores the corresponding separate operationsDSV41_OVERLAP_SPARSE_PLAN10uses serial preparationDSV41_CUSTOM_QB,DSV41_FUSED_QB_KV,DSV41_FUSED_TOPK_SLOTS,DSV41_FUSED_READY_QKV0DSV4_FUSED_DSPARK_QUERY_INPUTS,DSV4_FUSED_DSPARK_COMMIT_ROWS1Shape/device eligibility checks remain in place. Unsupported inputs and cold captures retain the corresponding fallback paths. The FULL model path does not enable DeepGEMM's process-global PDL policy itself.
End-to-End Decode Performance
Four B300/SM103 GPUs, TP1/DP4/EP4, B64 per rank (256 concurrent requests), ctx32768, DSpARK gamma=5, Sparse MQA and CUDA Graph enabled. Each request produces 192 tokens in 32 MTP rounds, with six output tokens per round. Target verification processes 384 tokens/rank and draft proposal processes 320 tokens/rank. Both arms use asynchronous engine execution and
FAKE_BALANCE_EXPERT=0.This measures the complete model's decode execution through the RTP engine, including draft proposal, target verification, draft commit, sampling and engine overhead. The fixed-batch workload uses synthetic KV, skips real prefill and forces full draft acceptance. It is not an online-serving throughput measurement including prefill, queueing or network latency, and does not measure a real draft acceptance rate.
The latest run on 2026-10-21 measures PR
667f2a13dusing FULL multistream + PDL. Targetdd6dd239aand previous PR438fbb2a0below are retained same-day measurements, not reruns in this attempt. All three use internal revisiondabfb8112, the same physical GPUs, workload and DeepGEMM runtime. The PR builds include the locally approved BUILD-only repair for nestedselect(); inference logic is unchanged by that repair. The three native library hashes match between the two PR runs. These results cover the listed revisions, not subsequent PR or target-branch changes.dd6dd239a, earlier same day438fbb2a0+ BUILD repair, earlier same day667f2a13d+ BUILD repair, multistream + PDLAt
667f2a13d, MTP step time decreases by 1.154 ms (5.09%) versus the retained baseline. Compared with the previous PR run, TPS increases 1.01% and step time decreases 0.217 ms. The latest three unprofiled rounds measure 279.0010, 278.9747 and 279.0483 per-request TPS (range 278.97-279.05). The runs occurred at different times, so the incremental gain is not an isolated on/off measurement of the DSpARK fusion.Each run uses two warmup rounds, three unprofiled measurement rounds and one separate profiling round. Exclude the first six-token round from each request's engine timing:
token_ms = (cost_time_us - first_token_cost_time_us) / 1000 / 186. Take each rank's request mean, then the slowest rank, then the median across the three measurement rounds. Per-request TPS is1000 / token_ms, aggregate TPS is256 * per-request TPS, and MTP step time is6 * token_ms. Profiler timings do not enter these results.The PR run enables FULL multistream, its Q-norm-to-QB PDL trigger and the DeepGEMM PDL policy; baseline has these disabled. Other features retain their branch defaults, including disabled custom QB/KV/slots/ready-QKV paths. The measured gain is the combined result of the active changes and PDL policy, not an isolated attribution to one operator.
Attention Performance
The following historical timeline compares target
dd6dd239awith PR438fbb2a0, using the same model and workload as the end-to-end comparison but a separate profiling round. It is not a measurement of the later667f2a13drevision.The table is rank 0's mean per-layer GPU Attention interval over the first three captured target-verify iterations, grouped by Attention type. The interval starts after input HC/norm and ends at Attention output projection completion, before the FFN mHC transition. It excludes MoE and is not an end-to-end MTP step measurement.
Positive reduction means faster. The improvements are concentrated in FULL and Reindex; SWA and Reuse show small slowdowns in this capture. The optional custom QB/KV/slots/ready-QKV paths were disabled, so these measurements do not establish their benefit.
Recorded Operator Measurements
Historical B300 microbenchmarks from the Reindex/Plan changes, recorded in the integration comment at
801eb19c. These are separate from the layer timeline above and are not a fresh full-PR end-to-end measurement.select_tokensselect_tokensThe selection benchmark alternates CUDA Graph variants with eight rotating inputs. Operator timings and overlap savings are not added together or treated as request-throughput gains.
Accuracy Evaluation
The completed evaluation covers 262/262 requests, with exit code 0, no failed requests and no surviving test processes. It compares the source branch's default path at
801eb19c->438fbb2aunder the same evaluation setup. This reference differs from the target-branch performance baseline above.801eb19c438fbb2aAll 64 MRCR raw outputs are identical between revisions. GPQA has a net decrease of two correct answers: five changed from correct to incorrect and three from incorrect to correct; truncated responses increased from four to five. These results establish unchanged MRCR outputs and a small GPQA score difference on this sample, not a blanket guarantee of zero regression.
The evaluation covers the default source-branch path; default-off kernels are not counted as validated. The accuracy table and historical Attention table do not include the later DSpARK preparation change
bdb284c7. The latest end-to-end row at667f2a13ddoes include that change; no new accuracy evaluation is claimed for this revision or subsequent heads.Reproduction and Validation
The PR includes regression coverage for cache slots and metadata, fallback dispatch, projection reload, changed-input CUDA Graph replay, cross-stream dependencies, compact candidate prefixes, replay-updated request validity, and MTP masks/page tables.
The Reindex/Plan integration record reports the following validation runs through
801eb19c:These are historical, overlapping runs, not an additive test count. The attention-end launch mode covered in those runs has since been removed. They used source-verified existing native operator artifacts and do not establish a fresh complete native build, full checkpoint/service reload acceptance, or coverage of the later C++ MTP gatherer changes. The later model accuracy evaluation is reported separately above.
667f2a13dabove; accuracy coverage remains at438fbb2a0.