执行摘要
- 一句话:为扩散模型 benchmark 工具添加混合分辨率请求支持,提升测试真实性。
- 推荐动作:该 PR 值得精读,特别是
RandomDataset 中的权重采样实现和 per-request 参数传递的设计,展示了如何扩展 benchmark 工具以支持多样化负载。关注点包括:权重采样算法(random.choices 的使用)、接口变更(generate_batch 从字典到列表)的处理、以及混合分辨率下像素吞吐量的正确计算方式。
功能与动机
根据 PR body,动机是 'To test server with different prompts sizes',即测试服务器在不同提示大小(如图像分辨率)下的表现,以更真实地模拟实际使用场景。
实现拆解
- 添加 CLI 参数:在
bench_offline_throughput.py 和 bench_serving.py 中新增 --random-request-config(JSON 字符串定义请求配置文件,包含 width、height、num_inference_steps 和 weight 字段)和 --random-request-seed(随机种子)参数,用于接收混合分辨率配置。
- 核心逻辑实现:在
datasets.py 的 RandomDataset 类中,解析 JSON 配置,使用 random.choices 基于权重采样请求配置文件,并新增 get_sampling_params 方法提供 per-request 参数;同时修改 __getitem__ 以根据采样配置覆盖默认参数。
- benchmark 逻辑调整:修改
bench_offline_throughput.py 的 generate_batch 函数,使其接受 per-request 采样参数列表(原为单个字典),并调整 calculate_metrics 以正确计算混合分辨率下的像素吞吐量(累加每个请求的实际像素)。
- HTTP 请求更新:在
bench_serving.py 中,确保 num_inference_steps 等参数被包含在图像和视频生成的 JSON payload 中,以传递给服务器。
- 验证与错误处理:添加验证逻辑,确保
--random-request-config 仅与 --dataset random 一起使用,避免与其他数据集(如 VBenchDataset)冲突,并处理 JSON 解析异常。
关键文件:
python/sglang/multimodal_gen/benchmarks/datasets.py(模块 数据集模块;类别 source;类型 core-logic;符号 get_sampling_params): 核心逻辑变更,实现了混合分辨率请求的权重采样和 per-request 参数管理,新增 get_sampling_params 方法,是功能实现的关键。
python/sglang/multimodal_gen/benchmarks/bench_offline_throughput.py(模块 离线吞吐量;类别 source;类型 core-logic;符号 generate_batch, calculate_metrics): 关键入口文件,添加了混合分辨率支持的 CLI 参数,并修改了 generate_batch 和 calculate_metrics 函数以处理 per-request 参数和正确计算像素吞吐量。
python/sglang/multimodal_gen/benchmarks/bench_serving.py(模块 服务端测试;类别 source;类型 core-logic): 服务端 benchmark 脚本,添加了相同的 CLI 参数并确保 num_inference_steps 等参数被包含在 HTTP 请求中,以支持混合分辨率负载测试。
关键符号:get_sampling_params, generate_batch, calculate_metrics
关键源码片段
python/sglang/multimodal_gen/benchmarks/datasets.py
核心逻辑变更,实现了混合分辨率请求的权重采样和 per-request 参数管理,新增 get_sampling_params 方法,是功能实现的关键。
import random
import json
class RandomDataset(BaseDataset):
def __init__(self, args, api_url: str = "", model: str = ""):
super().__init__(args, api_url, model)
self.num_prompts = args.num_prompts or 100
self.random_request_config = args.random_request_config # 直接访问属性,避免 getattr
if self.random_request_config:
# 解析 JSON 配置字符串
self.random_request_config = json.loads(self.random_request_config)
# 使用 pop 提取权重并同时从配置中移除 weight 键,提高效率
weights = [p.pop("weight") for p in self.random_request_config]
seed = args.random_request_seed
rng = random.Random(seed) # 使用指定种子确保可重现性
# 基于权重采样请求配置文件,采样数量等于请求数
self._sampled_requests = rng.choices(
self.random_request_config, weights=weights, k=self.num_prompts
)
else:
self._sampled_requests = None # 未配置时保持原行为
def get_sampling_params(self, idx: int) -> dict:
"""返回每个请求的采样配置字典,若无混合配置则返回空字典。"""
if self._sampled_requests:
return self._sampled_requests[idx]
return {}
def __getitem__(self, idx: int) -> RequestFuncInput:
profile = self._sampled_requests[idx] if self._sampled_requests else {}
# 根据采样配置覆盖默认参数,支持 width、height、num_inference_steps 等字段
return RequestFuncInput(
prompt=f"Random prompt {idx} for benchmarking diffusion models",
api_url=self.api_url,
model=self.model,
width=profile.get("width", self.args.width),
height=profile.get("height", self.args.height),
num_frames=profile.get("num_frames", self.args.num_frames),
num_inference_steps=profile.get(
"num_inference_steps", self.args.num_inference_steps
),
fps=profile.get("fps", self.args.fps),
)
python/sglang/multimodal_gen/benchmarks/bench_offline_throughput.py
关键入口文件,添加了混合分辨率支持的 CLI 参数,并修改了 generate_batch 和 calculate_metrics 函数以处理 per-request 参数和正确计算像素吞吐量。
def generate_batch(
engine: DiffGenerator,
bench_args: BenchArgs,
prompts: List[str],
user_sampling_params: List[Dict[str, Any]], # 改为 per-request 参数列表
) -> BatchOutput:
"""同步生成一批图像/视频,支持混合分辨率请求。"""
assert len(user_sampling_params) == len(prompts), (
f"user_sampling_params length ({len(user_sampling_params)}) must match "
f"prompts length ({len(prompts)})"
) # 添加断言确保参数长度匹配,防止错误
output = BatchOutput()
start_time = time.perf_counter()
torch.cuda.reset_peak_memory_stats()
for prompt, params in zip(prompts, user_sampling_params): # 遍历每个请求及其参数
try:
sampling_params_kwargs = dict(params) # 复制 per-request 参数
sampling_params_kwargs["prompt"] = prompt
result = engine.generate(sampling_params_kwargs=sampling_params_kwargs)
# ... 处理结果
except Exception as e:
# ... 错误处理
output.latency = time.perf_counter() - start_time
return output
def calculate_metrics(
outputs: List[BatchOutput],
total_duration: float,
resolution: Tuple[int, int, int],
num_requests: int,
all_sampling_params: Optional[List[Dict[str, Any]]] = None, # 新增参数用于混合分辨率
) -> Dict[str, Any]:
"""计算生成指标,支持混合分辨率下的像素吞吐量。"""
successful = [o for o in outputs if o.success]
num_success = len(successful)
width, height, frames = resolution
if all_sampling_params: # 如果提供了 per-request 参数,则累加每个请求的实际像素
total_pixels = sum(
p.get("width", width)
* p.get("height", height)
* p.get("num_frames", frames)
for p in all_sampling_params[:num_success]
)
else: # 否则使用全局分辨率计算
total_pixels = num_success * width * height * frames
metrics = {
"num_requests": num_requests,
"successful_requests": num_success,
"request_throughput": num_success / total_duration,
"pixel_throughput": total_pixels / total_duration, # 正确计算混合分辨率下的像素吞吐量
}
return metrics
评论区精华
风险与影响
- 风险:
- 回归风险:
bench_offline_throughput.py 中 generate_batch 的接口从接受单个 user_sampling_params 字典改为列表,可能影响现有调用,但该函数仅在模块内部使用,且添加了断言确保参数长度匹配。
- 性能风险:
RandomDataset 初始化时使用 random.choices 进行权重采样,复杂度 O(n),对于大量请求(如数万)可能轻微影响初始化时间,但 benchmark 中请求数通常有限(默认 100)。
- 安全风险:解析用户提供的 JSON 字符串(
--random-request-config),若输入恶意或畸形 JSON 可能导致解析异常,现有代码使用 json.loads 但未显式捕获异常,依赖上层错误处理。
- 兼容性风险:新增参数为可选,默认行为不变,向后兼容;但若用户错误地将
--random-request-config 与非 random 数据集结合使用,会触发验证错误。
- 影响:
- 对用户:benchmark 用户现在可以定义混合分辨率请求配置文件,模拟真实世界中的多样化负载,获得更准确的性能数据(如吞吐量、延迟),有助于评估服务器在不同工作负载下的表现。
- 对系统:仅影响扩散模型 benchmark 工具(
sglang/multimodal_gen/benchmarks/ 模块),不改变核心扩散模型推理逻辑或服务器运行时,对生产系统无直接影响。
- 对团队:提升了测试工具的灵活性和真实性,支持更复杂的性能测试场景,有助于开发团队进行负载测试和性能调优;代码变更集中在 benchmark 模块,易于维护。
- 风险标记:接口变更, JSON 解析风险, 缺少单元测试
关联脉络
- PR #23443 [diffusion] ci: allow using prebuilt sgl-kernel wheel for GT regeneration: 同属 diffusion 模块的 CI 相关 PR,涉及扩散模型测试工具链的优化,与本 PR 的 benchmark 功能互补。
- PR #23422 [diffusion] support custom output folder name in GT generation workflow: 同属 diffusion 模块的 CI 工作流改进,展示了扩散模型测试工具的持续演进,与本 PR 的 benchmark 扩展相关。
参与讨论