Skip to content

[v5] 修复 Qwen3.5 显存估算、自适应采样准入和扩容负载计数 - #363

Open
qychen2001 wants to merge 3 commits into
dev-swift-v5from
fix/v5-bug-1102
Open

qychen2001 wants to merge 3 commits into
dev-swift-v5from
fix/v5-bug-1102

Conversation

@qychen2001

@qychen2001 qychen2001 commented Nov 2, 2026 •

Copy link
Copy Markdown
Collaborator

PR 类型

  • Bug Fix
  • New Feature
  • Document Updates
  • More Models or Datasets Support

PR 信息

实验是 8 张 GPU 上的 Qwen3.5-4B GRPO:数学数据,开启 thinking,accuracy 奖励,FSDP2,vLLM,in-place 同步权重。资源模式有两种:

  • estimate:训练开始前一次性算出训练卡、采样卡,以及 vLLM 的 max_num_seqs 和 max_num_batched_tokens。
  • adaptive:在这份计划之上,每次同步权重时再决定要不要叫醒睡在训练卡上的采样引擎,以及要不要往空着的卡上新加一个采样引擎。

下面三处都会让这条路径在启动或扩容时走错。ms-swift 侧配套改动(规则奖励被当成奖励模型)在 modelscope/ms-swift#10495 。

1. Qwen3.5 估不准显存,prefill 长度被写成整份 KV

场景。 resource_mode 为 estimate 或 adaptive 时,RLResourceEstimator 在拉起 Ray 之前读 Hugging Face 配置,用来算每张采样卡能放多少 KV,以及一次调度最多塞多少 token。

现象。 Qwen3.5 是多模态组合模型。顶层 config 的 hidden_size、层数、词表都是 0,文本形状在 text_config 上。估算器只读顶层,会拒绝这个模型,或者按 0 来算。

KV 的头大小原来用 hidden_size // num_attention_heads。Qwen3.5 这是 2560 / 16 = 160,配置里的 head_dim 是 256。按 160 算,同样的显存会多放出并发。这次 4B、每张 96GiB 的卡上,max_num_seqs 会从 68 变成 109。

max_num_batched_tokens 原来直接写成 KV 能装下的 token 数,这次大约 57 万。vLLM 把它同时当作一次 prefill 的上限,以及视觉编码器 profile 的预算,于是会去 profile 几十张最大尺寸的图。在 PPU 上这会在 rotary_kernel 里报非法地址,引擎起不来。

修复。 存在 text_config.hidden_size 时改读 text_config,并补上父配置的 torch_dtype。KV 字节数优先用配置里的 head_dim;没有或不是正数时,才退回 hidden_size // num_attention_heads。max_num_batched_tokens 改为一次 prefill 的长度:不超过 KV 容量,也不超过 max_model_len(没有引擎上下文时用 max_position_embeddings),并且至少能放下每条正在解码的序列的一个 token。这次上下文是 12288,所以这个值是 12288,不再是整份 cache。

2. 自适应采样被搬到另一个进程,准入表丢了

场景。 resource_mode=adaptive。configure_workers 先在驱动进程的采样器上记下哪些副本是 ACTIVE,然后才构造 MultiTurnRollout。不是和训练卡 colocate 时,rollout 默认要放到远端 actor 上。

现象。 远端 actor 拿到的是被 pickle 过的采样器。序列化会丢掉准入表,并标记“准入归原来的驱动进程”。远端的 sample() 仍走驱动进程那条路径,于是报错:Adaptive sampling must be admitted by its original driver, not a serialized handler。prompt 进不了采样器,训练一步都没有。estimate 不会调用 configure_workers,所以同一套 GRPO 在 estimate 下可以跑完。

修复。 remote_class 在决定要不要把实例放到远端之前,如果类提供了 _coerce_remote_group,就用它的返回值作为 remote_group。MultiTurnRollout 在采样器已经有 _sampler_workers 时返回 None,rollout 留在持有准入表的这个进程。采样器还没配置过 worker 时,仍按原来的 remote_group 放置。

3. 扩容读的是一条已经没人写的负载计数

场景。 resource_mode=adaptive。每次同步权重前,decide() 用 sampler.inflight_count > 0 判断采样是不是还在忙。连续两个同步点都忙,并且训练侧在空等数据,才会先叫醒训练卡上睡着的采样引擎;再隔若干步,才往空闲卡加引擎。

现象。 现行的 sample() 在整个调用期间占着 WorkerEntry.dispatching。WorkerEntry.inflight 只在已经不用的提交/收集账本里累加,这条路径上一直是 0。inflight_count 原来只加 inflight,所以每次判定都认为采样是空的,压力计数被清零。表现是:权重同步组一直只有 1 个发送端加上专用采样卡;训练卡上的共享引擎一直睡着,只剩大约 1GiB;空闲卡上没有新引擎。

修复。 inflight_count 改为在 worker 锁里把每个采样 worker 的 inflight 和 dispatching 加在一起。正在执行的 sample() 会被算进负载。

实验结果

8 张 PPU-ZW810(每张 96GiB),Qwen3.5-4B,5 个 optimizer step。prompt 上限 1024,completion 上限 8192,max_model_len=12288。

  • estimate,4 张训练卡加 4 张采样卡:5 步完成。计划读到了 text_config 和 head_dim=256,max_num_seqs=68,max_num_batched_tokens=12288。profile 没有非法地址。4 次 in-place 同步,每次 723 个张量,写出了 checkpoint-final。
  • adaptive,4 张训练卡、2 张专用采样卡、2 张空闲卡,共享引擎睡在训练卡上:修复 2 之后,日志是本地初始化 MultiTurnRollout,prompt 进入驱动进程上的采样器,不再出现上面的准入报错。专用采样卡每次同步都收到 723 个张量。这 5 步里没有叫醒共享引擎:每次同步时,和训练重叠的那批生成已经返回,dispatching 在判定那一刻也是 0。这个修复让计数和现行 sample() 对齐;生成先于训练结束时,同步点上的快照仍然是空的。

qychen2001 and others added 3 commits November 2, 2026 15:56
…er chunk

Qwen3.5 keeps its shape on text_config, and its Q/K/V size is head_dim rather than hidden_size over the head count. max_num_batched_tokens is the prefill chunk, capped by max_model_len, so a profile run does not treat the whole KV cache as a vision batch.

Co-authored-by: Cursor <cursoragent@cursor.com>
configure_workers records live replicas on the driver handler. Pickling that handler drops the table and then refuses sample(), so MultiTurnRollout stays in this process once the pool is configured.

Co-authored-by: Cursor <cursoragent@cursor.com>
The current sample path holds dispatching for the whole call. The retired inflight ledger stays at zero, so the scaler never sees a busy sampler.

Co-authored-by: Cursor <cursoragent@cursor.com>
@qychen2001 qychen2001 changed the title [v5] Fix adaptive resource estimates, rollout admission, and scaler load [v5] 修复自适应资源估算、rollout 准入和扩容负载计数 Nov 2, 2026
@qychen2001 qychen2001 changed the title [v5] 修复自适应资源估算、rollout 准入和扩容负载计数 [v5] 修复 Qwen3.5 显存估算、自适应采样准入和扩容负载计数 Nov 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant