Repository navigation
Conversation
Gate on the create_graph() capability instead of device names, route is_current_stream_capturing through the accelerator API, and rename validate_cuda_graph_support to validate_graph_capture_support with matching cleanup of CUDA-only wording in internal names, docstrings, and error messages. The user-facing hybrid_engine.enable_cuda_graph config key is unchanged. Update the unit tests to capability-gated skips and rename the test module accordingly. Signed-off-by: Zizhao Tang <1601677496@qq.com>
Switch the attention call to npu_fusion_attention_v3: the v1/v2 variants launch on an internal secondary stream that CANN capture rejects (107025), and the eager fallback then hits a lagging-mask failure (561103). Grow the KV-cache table on demand because layer_id is derived from DeepSpeedSelfAttention.num_layers, a process-wide counter that only grows, so a second engine built in one process indexes out of bounds. Signed-off-by: Zizhao Tang <1601677496@qq.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
The flag now reads as a backend capability instead of a CUDA-specific feature. The old key remains as a deprecated alias whose value migrates to the new field with a warning, so existing configs keep working. Signed-off-by: Zizhao Tang <1601677496@qq.com>
|
Codex Review: Something went wrong. Try again later by commenting “@codex review”. ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
1 similar comment
|
Codex Review: Something went wrong. Try again later by commenting “@codex review”. ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
The config-json page still documented the pre-rename key; point it at enable_graph_capture and note the deprecated enable_cuda_graph alias, and drop the CUDA-specific wording in the graph description. Signed-off-by: Zizhao Tang <1601677496@qq.com>
cf342ec to
9a4cce3
Compare
Summary
The HybridEngine graph-capture paths (per-position decode graphs from #8271 and the continuous-rollout graphs from #8732) were gated on CUDA in several places: a device-name check, an input device-type check, and hard-coded "CUDA graph" naming. This PR replaces them with accelerator capability hooks so any backend that implements graph capture (
create_graph()returning a graph,capture_to_graph,replay_graph, andis_current_stream_capturing) takes the same code path as CUDA.Two accelerator-specific fixes ride along to make the NPU path actually work:
npu_fusion_attention_v3): the v1/v2 variants launch work on an internal secondary stream that CANN capture rejects atcapture_end(error 107025).layer_idis derived fromDeepSpeedSelfAttention.num_layers, a process-wide counter that only ever grows, so any process that builds a second engine would otherwise index out of bounds.Design
Capability gates instead of name gates.
validate_cuda_graph_supportbecomesvalidate_graph_capture_supportand rejects backends withget_accelerator().create_graph() is Noneinstead of comparingdevice_name()with"cuda". The continuous-rollout path uses the same capability check. Its capture guard (is_current_stream_capturing, used byDeepSpeedStaticCacheto skip host-side bounds checks while recording) already routes through the accelerator abstraction since #8732 (CUDA implementation, safeFalsedefault); this PR adds the NPU implementation.Naming. Internal names, docstrings, and error messages drop the "CUDA" prefix (
validate_graph_capture_support, "continuous graph capture", "per-position graph"). The config key is renamed tohybrid_engine.enable_graph_captureso the flag reads as a backend capability rather than a CUDA-specific feature, following the rename request in #8271's thread. The oldhybrid_engine.enable_cuda_graphkey still works as a deprecated alias: its value migrates to the new field with a warning (the existing DeepSpeed deprecated-field machinery), so existing config files keep working.NPU flash attention.
NPUInference._softmax_contextcallstorch_npu.npu_fusion_attention_v3, the graph-mode variant. The v1/v2 variants rejected capture with "capture model contains a stream that was not joined to the original stream" (107025); after the failed capture the fallback eager path then hit a secondary failure (561103) because host-side counters had already advanced. v3 captures cleanly in the BSH layout (the docs only promise BNSD), and both failure modes disappear together.Safety
The existing refusals are preserved and remain device-agnostic: ZeRO stage 3,
release_inference_cache,inference_tp_size > 1, and unpinned generation lengths all refuse graphs with a warning and fall back to eager, as do capture failures at runtime. The continuous-rollout path keeps its explicit rejections of aligned decode fronts, cache trimming, andflash_attention_2implementations.Results
Old container path (
#8271methodology)facebook/opt-1.3blocal weights, ZeRO-2, FP16, single Ascend NPU, 256-token prompt, 128 new tokens:Throughput scales 10.2× over a 32× batch increase. Batch 8, averaged over 4 measured iterations of an RLHF-style loop (eval → generate → train → forward/backward/step):
Continuous rollouts (
#8732methodology)gpt2local weights, FP16, batch 1, 32-token prompt, 32 new tokens, greedy, continuous batching on a single Ascend NPU, two warmup calls and five steady-state measurements:That is a 5.97× steady-state speedup, with the first call (including capture) at 395.5 ms reported separately. Two different prompts (seeds 1234/1235) produced token-identical eager and graph outputs (32/32 tokens each) while reusing one capture.
Tests
tests/unit/hybrid_engine/test_he_graph.py(renamed fromtest_he_cuda_graph.py):release_inference_cache/inference_tp_sizerejections, the dispatch state machine, capture-failure fallback, and invalidation on length change.seq_inferencemarker) asserting a graphed generation is token-identical to the same generation run eagerly.Continuous-rollout suite, run on NPU with Transformers 4.57.6:
NPU end-to-end validation ran locally on a single Ascend NPU (PyTorch 2.10 + torch_npu 2.10.0.post7; Transformers 4.57.6): both paths capture and replay correctly with token-identical outputs, and the eager path is unchanged. The three HybridEngine scripts in DeepSpeedExamples (TODO: fill in the script names) were also run end-to-end on NPU with graph capture enabled.
Scope
The graph flag remains opt-in and off by default; nothing changes for CUDA, whose eager path measured identically before and after. Only ZeRO-2 with
inference_tp_size=1was benchmarked on the container path, matching the upstream guards. Known limitations carried over or found while measuring:del/GC), so a 4-step loop exhausts the 32 GB card. This is unrelated to graph capture and tracked separately.get_query_offsetCache-API compatibility work, tracked in Support Transformers 5.20 cache query offsets in DeepSpeedStaticCache #8852; this PR does not include it.Related work
enable_graph_capturerename request.get_query_offsetsupport this PR depends on for newer Transformers versions.