执行摘要
- 一句话:默认种子改为42,重构partitioning与disagg种子传递
- 推荐动作:建议关注 partitioning 模块提取的设计(单一职责、可复用)、DenoisingContext 数据类与字典返回的权衡、disagg 种子传递的演进。该 PR 展示了增量重构与特性增强的合并模式,适合用于学习渐进式重构。
功能与动机
来自PR body:'to align with diffusers default: generator = torch.Generator().manual_seed(42)'。使默认种子与diffusers库一致,保证复现性。
实现拆解
-
修改默认种子值:在 http_server.py 中将 DEFAULT_SEED 常量从 1024 改为 42;在 image_api.py、video_api.py 中调整 Form(...) 默认参数;在 protocol.py 中更新 ImageGenerationsRequest 和 VideoGenerationsRequest 的 seed 字段默认值;在 io_struct.py 中更新 RolloutRequest 的 seed 默认值。
-
抽取通用 Partitioning 模块:创建 python/sglang/multimodal_gen/test/partitioning.py,定义 PartitionItem 数据类和 partition_items_by_lpt 函数实现 LPT(最长处理时间)分区算法。随后在 run_suite.py 中导入该模块重写 auto_partition 函数,并新增 get_suite_files_rel 和 partition_items_by_index;在 CI 脚本 compute_diffusion_partitions.py 中通过 _load_partitioning_helpers 动态加载该模块,移除本地重复实现,增加对 b200 suite 的支持和 include_standalone 选项。
-
引入 DenoisingContext 数据类:在 denoising.py 中新增 DenoisingContext dataclass,替代先前 _prepare_denoising_loop 返回的字典。在 hunyuan3d_shape.py 中改为返回 DenoisingContext 实例,并新增 is_warmup 字段。
-
增强 Disagg 种子传递:在 scheduler_mixin.py 的 extract_transfer_fields 中添加 seed 序列化逻辑,将 req.seed 写入 scalar_fields;在 _build_disagg_req 中根据 seed 字段重建 torch.Generator,并支持 seed 为列表的多输出场景。
-
补充测试覆盖:在 test_disagg_trace.py 中新增两个测试用例验证单种子和列表种子在 disagg 中的正确传递与重建。
-
更新 CI 配置:修改 diffusion-ci-gt-gen.yml 以支持 b200 suite 和新 partitioner,同步更新 gen_diffusion_ci_outputs.py。
关键文件:
python/sglang/multimodal_gen/test/partitioning.py(模块 测试分组;类别 test;类型 test-coverage;符号 PartitionItem, partition_items_by_lpt): 新增文件,提取了LPT分区算法的核心实现(PartitionItem数据类和partition_items_by_lpt函数),被测试运行器和CI脚本共同引用,是本次重构的关键产出。
python/sglang/multimodal_gen/runtime/disaggregation/scheduler_mixin.py(模块 反聚合调度;类别 source;类型 core-logic;符号 extract_transfer_fields, _build_disagg_req): 核心逻辑变更:在提取传输字段时序列化seed,在反序列化时支持种子列表重建多个generator,使disagg正确传递种子信息,支撑多输出场景。
scripts/ci/utils/diffusion/compute_diffusion_partitions.py(模块 CI脚本;类别 infra;类型 infrastructure;符号 _load_partitioning_helpers, build_partition_items): CI分区脚本重构:改为从partitioning.py导入PartitionItem和lpt_partition,移除重复实现;增加对b200 suite的支持和standalone可选项。
python/sglang/multimodal_gen/test/run_suite.py(模块 测试运行器;类别 test;类型 test-coverage;符号 get_suite_files_rel, partition_items_by_index, partition_test_files): 测试运行器重构:导入partitioning模块替代本地auto_partition逻辑,新增get_suite_files_rel和partition_items_by_index函数。
python/sglang/multimodal_gen/runtime/pipelines_core/stages/hunyuan3d_shape.py(模块 3D形状管道;类别 source;类型 dependency-wiring;符号 DenoisingContext): 引入DenoisingContext数据类,替换_prepare_denoising_loop返回字典,新增is_warmup字段。
python/sglang/multimodal_gen/test/unit/test_disagg_trace.py(模块 测试单元;类别 test;类型 test-coverage;符号 test_transfer_keeps_seed_needed_to_rebuild_generator, test_build_disagg_req_rebuilds_generator_list): 新增两个测试用例,覆盖种子在disagg中的正确传递和列表重建。
关键符号:PartitionItem, partition_items_by_lpt, _load_partitioning_helpers, build_partition_items, get_suite_files_rel, partition_items_by_index, extract_transfer_fields, _build_disagg_req, test_transfer_keeps_seed_needed_to_rebuild_generator, test_build_disagg_req_rebuilds_generator_list
关键源码片段
python/sglang/multimodal_gen/test/partitioning.py
新增文件,提取了LPT分区算法的核心实现(PartitionItem数据类和partition_items_by_lpt函数),被测试运行器和CI脚本共同引用,是本次重构的关键产出。
from __future__ import annotations
from dataclasses import dataclass
@dataclass(frozen=True)
class PartitionItem:
"""单个可分区项,包含种类、唯一标识和预估耗时。"""
kind: str # 'case' 或 'standalone'
item_id: str
est_time: float
used_fallback_estimate: bool = False
def partition_items_by_lpt(
items: list[PartitionItem], num_partitions: int
) -> list[list[PartitionItem]]:
"""
LPT(最长处理时间)分区算法。
将 items 按预估耗时降序排列,然后依次分配给当前总耗时最小的分区,
使得各分区总耗时尽可能均衡。
返回包含 num_partitions 个分区的二维列表。
"""
if not items or num_partitions <= 0:
return []
# 按预估耗时降序排列;耗时相同则按 kind 和 item_id 排序保证确定性
sorted_items = sorted(
items,
key=lambda item: (-item.est_time, item.kind, item.item_id),
)
partitions: list[list[PartitionItem]] = [[] for _ in range(num_partitions)]
partition_sums = [0.0] * num_partitions
for item in sorted_items:
# 找到当前总耗时最小的分区
min_idx = partition_sums.index(min(partition_sums))
partitions[min_idx].append(item)
partition_sums[min_idx] += item.est_time
return partitions
评论区精华
Review 中 gemini-code-assist[bot] 建议将各入口的默认种子改为 None 而非 42,理由是避免与 SamplingParams 默认值重复,降低维护成本。但作者未采纳,保留了显式 42,可能认为显式默认更清晰。该建议在 http_server.py、image_api.py、video_api.py、protocol.py、io_struct.py 等多处提出,均未被采纳。
- 默认种子应改为None还是硬编码42 (design): 作者未采纳,保留了显式42。可能认为显式默认更清晰或希望立即对齐 diffusers。
风险与影响
- 风险:默认种子从1024改为42会使原有依赖特定种子的生成结果变化,用户需适配;硬编码 seed 在各入口可能随 SamplingParams 默认值变化而不一致;partitioning 重构可能影响 CI 分片均衡,需关注后续执行情况;disagg 种子列表支持是新增路径,在极端边 case 下可能存在未覆盖的时序问题。
- 影响:用户:API 默认种子变化,生成结果与之前不同,需关注复现性。系统:disagg 服务现在支持多输出种子列表,提高功能完整性,但新增逻辑需要监控。团队:partitioning 模块化降低了后续维护成本,DenoisingContext 统一了参数传递模式。影响范围限于 multimodal_gen 子系统。
- 风险标记:默认种子变更, 硬编码seed冗余, CI分区重构, disagg种子列表支持
关联脉络
参与讨论