Repository navigation
[v5] 修复 Qwen3.5 显存估算、自适应采样准入和扩容负载计数 - #363
Open
qychen2001 wants to merge 3 commits into
Open
qychen2001 wants to merge 3 commits into
qychen2001 wants to merge 3 commits into
Conversation
…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>
1 of 4 tasks
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.
PR 类型
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()对齐;生成先于训练结束时,同步点上的快照仍然是空的。