平台:2× Tesla V100-SXM2-16GB(sm_70 / Volta,无 int8 tensor core)· Windows 10 企业版
模型:Qwen-Image-2.1 int8_convrot · 1024×1024 · euler + simple · CFG 1.0
口径:同 seed(20260924)、同 prompt、同画布,不换任何其它变量;时间取服务端 tqdm,或四档同口径的 wall clock
日期:2026-09-23
一、结论摘要
在已进入实测的采样加速路线里,Spectrum 是这台机器上目前第一条真正跑起来、并拿到可观加速的方案。
这个限定语不是客套。"唯一"是一个闭世界断言 —— 它同时宣称"其余全部不行",而"其余"远大于我们实际测过的范围。
逐条回查后,论域大致是这样:真跑过并否定的有九条(稀疏注意力、int8 注意力、FlashAttention / SageAttention、
DT2 分片调参、FirstBlockCache、Q4→Q3/Q2、砍步数、TE-Speed、INT8/FP8);
另有一类是硬件层面的不可达(Volta 没有 int8 tensor core,也得不到 TRT 的分块 VAE 路径);
还有一类是我们从未跑过、但这台机器今天就能跑的 —— 其中 EasyCache / LazyCache 是 ComfyUI 原生自带的节点,
零安装成本,而 QwenImage21Cache(Prefix KV Cache)本来就在编辑链的生产路径里默认开着,其贡献从未被单独测量。
所以更准确的说法是:Spectrum 是"已实测者中的第一条",而不是"已知全部方案中的唯一一条"。
这个区别在第七节的数据里不影响任何数字,但它决定了下一步该测什么。
| 配置 |
步数 |
扩散耗时 |
实际前向 / 预测 |
相对同步数基线 |
| 基线 |
25 |
69 s(2.79 s/it) |
25 / 0 |
1.00× |
| Spectrum |
25 |
33 s |
12 / 13 |
2.09× |
| 基线 |
45 |
139.9 s(wall) |
45 / 0 |
1.00× |
| Spectrum |
45 |
41 s |
15 / 30 |
3.09× |
四点需要先明确:
- 25 步档拿到 2.09×,45 步档拿到 3.09×。 加速比随总步数上升(机制见第六节)。
- 代价是细节被平滑。 高频能量下降 5% ~ 25%,同 25 步与同 45 步两组的降幅基本一致 —— 这是 Spectrum 固有的代价,与步数无关。
- 它只适用于纯文生图。 编辑 / 多图参考链在本机的显存峰值已达 94.2%,再加 Spectrum 约 800 MB 的缓存开销必然溢出。
- 推荐工作点:45 步。 用 41 s 拿到约等于「25 步基线 69 s」的细节水平。它给不了 45 步基线的细节 —— 那部分只能靠老老实实跑满步数。
下面逐项给出依据。
二、测试环境
2.1 硬件
| 项 |
配置 |
| GPU |
2× Tesla V100-SXM2-16GB,16384 MB/卡,SM 7.0(Volta),单卡 300 W |
| 卡间互联 |
NVLink,6 链路,实测 133 GB/s |
| 宿主 PCIe |
x4(主板通道受限,非 x16) |
| CPU |
AMD Ryzen 5 3400G,4 核 8 线程,最高 4.10 GHz |
| 内存 |
4× 8 GB DDR4-2866 = 32 GB(可用 30.9 GB) |
| 系统 |
Windows 10 企业版 19045 |
| 驱动 |
576.57 |
Volta 的两个硬约束贯穿全文,先摆在这里:
- 没有 int8 tensor core —— 所有依赖 int8 量化的注意力实现(SageAttention 等)在本机没有后端可用。
- 没有 bf16 张量核 —— ComfyUI 在 Volta 上只能走 FP16 路径。这也是本机为什么存在两个互斥的启动档。
内存是这台机器比显存更紧张的一环:两卡合计 32 GB 显存,而系统内存只有 30.9 GB。
2.2 软件
| 项 |
版本 |
| ComfyUI |
0.37.0 |
| PyTorch |
2.10.0+cu128(CUDA 12.8,cuDNN 9.10) |
| 启动档 |
run_comfyui_V100_lowvram_qwen.bat |
启动参数为 --cuda-device all --lowvram --disable-dynamic-vram --use-pytorch-cross-attention --disable-pinned-memory --fast-disk --disable-cuda-malloc。
两点说明:
- 该启动档不带
--fp16-unet。本机的 H3 视频档必须带这个参数,而 Qwen 与 IndexTTS 两档都不需要 —— 两个档位互斥,同一进程只能服务其中一类模型。
- 本机未安装 SageAttention,基线使用 PyTorch 原生 cross-attention。因此下文所有加速比都不含 SageAttention 的贡献,与部分公开数据不可直接对齐(见第十二节)。
2.3 模型
| 角色 |
文件 |
备注 |
| DiT |
qwen_image_2.1_int8_convrot.safetensors |
生产档,原生模块树 + int8 权重 |
| 文本编码器 |
qwen3vl_8b_w4a8.safetensors |
常驻 cuda:1 |
| VAE |
qwen_image_2.1_vae_bf16.safetensors |
— |
| 加速节点 |
Comfyui-Spectrum-Qwen2.1 |
见第三节 |
文本编码器通过 CLIPLoaderMultiGPU 显式绑定到 cuda:1。在 --lowvram 档下,ComfyUI 内置的 CLIPLoader 无法指定设备,会把文本编码器留在 CPU 上;显式绑卡是本机把整链从 536 s 压到 95 s 的那一步(与本文主题无关,但它是当前基线的组成部分)。
2.4 工作流
节点编号与 workflows/qwen_image_21_t2i_api.json 一致。整个对照实验中,唯一变化的节点是 460:
- 基线组:
451 UNETLoader → 458 KSampler
- 实验组:
451 UNETLoader → 460 SpectrumQwenImage21 → 458 KSampler
其余节点、提示词、种子、采样器设置完全相同。测试时 debug=True,用于在服务端日志里逐次打印「这一步是真实前向还是预测」。交付版本中该参数为 false。
SpectrumQwenImage21 共 13 个参数,测试使用的是节点作者默认值:
| 参数 |
值 |
参数 |
值 |
warmup_steps |
5 |
history_points |
8 |
tail_actual_steps |
2 |
chebyshev_degree |
4 |
window_size |
2.0 |
ridge_lambda |
0.1 |
flex_window |
0.75 |
blend_weight |
0.5 |
max_consecutive_forecasts |
8 |
cache_device |
main_device |
force_actual_on_control |
true |
debug |
测试 true / 交付 false |
已落地的交付工作流:workflows/ui_importable/qwen_image_21_t2i_1024_ui.json(45 步 + Spectrum 默认启用)。编辑 / 多图参考链的对应工作流中,该节点挂载但默认旁路,原因见第十一节。
三、Spectrum 是什么,以及它为什么能在 Volta 上跑起来
先澄清一个容易混淆的点:Spectrum 不属于缓存类方法。
- 缓存类(EasyCache / FirstBlockCache / TeaCache)依赖相邻去噪步的相似度复用中间特征。它需要一个相似度阈值,阈值不合适时命中率会直接掉到零。在本机 8 步蒸馏的 H3 场景下,这条路线实测命中 0/1,且额外显存必然溢出。
- Spectrum 把去噪器的中间特征视为时间的函数,用 Chebyshev 多项式 + 岭回归拟合已有步的历史,再外推预测后续步的特征。被预测的步会整体跳过 32 层 transformer,只执行代价极低的输出头(
time_text_embed → norm_out → proj_out)。
来源信息:
论文 arXiv 2603.01623 Adaptive Spectral Feature Forecasting for Diffusion Sampling Acceleration
CVPR 2026,已在 SGLang 中集成;论文在 FLUX.1 上报告 4.79×,Wan2.1-14B 上 4.67×
实现 Comfyui-Spectrum-Qwen2.1(社区实现,针对 Qwen-Image-2.1 的 32 层单流 MMDiT 编写)
它能在 Volta 上运行,有三个必要条件,缺一不可:
- 纯 PyTorch 实现,不含任何自定义 CUDA / Triton kernel。 SageAttention 那类方案在本机的死因是缺少 int8 tensor core,Spectrum 不存在这个问题 —— 没有后端可以缺失。
- 通过 ComfyUI 官方扩展点
WrappersMP.DIFFUSION_MODEL 接入,不对模型做 monkey-patch。这意味着最坏情况等价于一次空操作,而不是把图改坏。
- 校验失败时直接报错,不静默降级。 核心类名不匹配会
raise ValueError,试错成本因此接近零。
作为对照,本机此前否定掉的几条路线各有各的硬门槛:SageAttention 需要 int8 tensor core(Volta 没有)、FP8/INT8 在本机 comfy_kitchen 的 cuda 后端为 disabled: True、FirstBlockCache 在 8 步蒸馏下命中为零且额外显存必然溢出。Spectrum 是第一条在这台机器上物理可行的。
四、功能验证:预测步确实跳过了前向
在关心快多少之前,先要确认它不是空转。服务端日志在 debug=True 下会输出每次采样的调度结果:
[Spectrum-QwenImage21] run complete: branches=1 actual_calls=12 forecast_calls=13 total_calls=25
| 指标 |
25 步 |
45 步 |
| 实际前向次数 |
12 |
15 |
| 预测(跳过 32 层)次数 |
13 |
30 |
| 跳过比例 |
52.0% |
66.7% |
| 调度形态 |
warmup 5 → window 递增 → tail 2 |
同左 |
forecast_failed / 捕获失败 |
0 |
0 |
调度形态与论文的默认设置一致:前 5 步全部真实前向(用于积累拟合历史),随后预测窗口逐步增大,最后 2 步回到真实前向收尾。
一个提醒。 本机生产档是 int8_convrot 量化核心,而节点作者的 README 中有一处提示,大意是"经过量化或包装的核心不受支持"。我们据此一度判断这条路走不通,实际测试结果与这条提示并不一致 —— 量化并不改变模块树,diffusion_model 仍然是 QwenImage21Transformer2DModel,类名与结构签名校验照旧通过。
我们倾向于认为,那是一条覆盖面较宽的保守表述,针对的是用自定义实现整体替换掉原生 transformer 结构的情形;int8_convrot 只是把权重换成 int8,结构本身未被包装。这只是本机的一次单点观察,不构成对该说明的否定 —— 如果将来遇到真正被包装过的核心,仍应以节点作者的说明为准。
五、加速比
四个产物与四份图的 md5 均互不相同,可以排除执行缓存导致的"假通过":
| 配置 |
步数 |
服务端 tqdm |
wall clock |
graph md5 |
产物 md5 |
| 基线 |
25 |
69 s(2.79 s/it) |
72.39 s |
5515edeaeb8a |
a99a86656825e13c |
| Spectrum |
25 |
33 s |
36.11 s |
3a7de589769d |
7b8d0a1c6449de73 |
| 基线 |
45 |
未取到 |
139.90 s |
feb1e2206b40 |
76dbd9cd03f6a8c0 |
| Spectrum |
45 |
41 s |
45.20 s |
926416999952 |
55ac21db68151688 |
| 对比 |
口径 |
结果 |
| 同 25 步 |
tqdm 69 s → 33 s |
2.09× |
| 同 25 步 |
wall 72.39 s → 36.11 s |
2.00× |
| 同 45 步 |
wall 139.90 s → 45.20 s |
3.09× |
| 同 45 步 |
tqdm 投影 125.6 s → 41 s |
3.06× |
关于口径。 45 步基线那一次运行的服务不是由本项目的计时封装启动的,拿不到逐行 tqdm 日志,因此只能用 wall clock。wall 含模型加载与调度开销(约 3~4 s),四档在同一口径下可比。tqdm 与 wall 两条线给出的结论一致。
关于 45 步基线的 tqdm 投影。 按 25 步基线的单步成本(69 ÷ 25 = 2.76 s)外推 45 步,得到 125.6 s。这是一个投影值,不是实测值,已在表中注明。
六、加速比的结构:收益由实际前向次数决定
有一个数字值得单独解释:25 步档跳过了 52% 的步数,加速比却只有 2.09×。这其实是自洽的 —— 被跳过的步并非完全免费(仍要执行输出头与回归拟合),但代价小到在总时长里看不出来。
用「实际前向次数 × 基线单步成本」去拟合实测扩散时间:
| 档位 |
实际前向 |
拟合耗时 |
实测耗时 |
偏差 |
| Spectrum @ 25 |
12 |
12 × 2.76 = 33.1 s |
33 s |
0.1 s |
| Spectrum @ 45 |
15 |
15 × 2.76 = 41.4 s |
41 s |
0.4 s |
两档都在 0.5 s 以内对上。结论:预测步的额外开销可以忽略(远小于 0.1 s/步) —— 输出头相对 32 层 transformer 的体量几乎不占时间。
由此可以推出一个更直观的关系:
加速比 ≈ 总步数 / 实际前向次数
25 / 12 = 2.08× (实测 2.09×)
45 / 15 = 3.00× (实测约 3.06×)
这也解释了为什么加速比随总步数上升:实际前向次数几乎不随步数增长(25 步时 12 次,45 步时 15 次),而分母里的总步数在变大,比值自然被拉高。
实践含义:25 步档的加速上限就是约 2×。 论文中 4.79× 一类数字对应的是 40~50 步档,两者不属于同一前提,不应混用。
七、画质对比
7.1 方法
判画质只允许在同一像素网格上裁同一块区域,再横向拼接 —— 拼接是平移,不引入重采样。把整图缩到拼版里再看,缩略过程本身就会伪造出撕裂、梳状一类的伪影,这个坑本机已经付过一次学费。
上图标出了本文使用的五个区域:face_center(面部中央)、eyes(眼部)、mouth(嘴部)、hairline(发际/额头)、bg_corner(左上角窗光背景与发丝交界处)。bg_corner 是本次对照里最容易看出差异的区域 —— 它包含大片高频背景纹理。
两个指标:
- MAE(平均绝对误差,/255):衡量"改了多少"。同 seed 同 prompt 下,MAE 越小说明构图与主体越一致。
- 高频能量:3×3 拉普拉斯响应的方差,作为细节量的代理指标。它只说明细节被平滑了,不等于观感一定更差 —— 这是一条必须说清的边界。
先看整体观感(1:1 原尺寸,仅供把握总体印象,不用于伪影判定):
7.2 同 25 步:唯一变量是 Spectrum
| 区域 |
MAE |
高频能量比(spec25 / base25) |
| face_center |
2.505 |
0.890 |
| eyes |
2.355 |
0.877 |
| mouth |
2.306 |
0.950 |
| hairline |
3.299 |
0.874 |
| bg_corner |
1.974 |
0.751 |
7.3 同 45 步:唯一变量同样是 Spectrum
| 区域 |
MAE |
高频能量比(spec45 / base45) |
| face_center |
2.443 |
0.874 |
| eyes |
2.551 |
0.867 |
| mouth |
2.138 |
0.935 |
| hairline |
2.923 |
0.872 |
| bg_corner |
1.974 |
0.783 |
表中 bg_corner 在两处都读到 1.974,是一个真实巧合(逐像素复算为 1.973607 与 1.973750),并非复制错误。
7.4 对照:纯步数效应(25 → 45 步,都不带 Spectrum)
| 区域 |
MAE |
高频能量比(base45 / base25) |
| face_center |
5.141 |
1.158 |
| eyes |
5.464 |
1.176 |
| mouth |
5.246 |
1.080 |
| hairline |
6.274 |
1.171 |
| bg_corner |
6.112 |
1.339 |
多跑 20 步自身就能把高频能量抬升 8% ~ 34%。这一列数字是下一节的关键依据。
7.5 小结
- 软化幅度与步数无关。 同 25 步降幅 −5% ~ −25%,同 45 步降幅 −6% ~ −22%,两组基本一致。这说明它是 Spectrum 固有的代价,而不是"步数不够"。节点作者在文档中用"更柔和、更像喷绘"描述这一档的观感,我们的高频测量与该描述一致。
- MAE 只有 2.0 ~ 3.3 / 255(约 1%)。 同 seed 下构图与主体完全对齐,差异停留在细节层面,不是结构层面的改变。
- 目视结果:皮肤确实更平滑(雀斑与毛孔减弱最明显),但睫毛、虹膜、唇纹、眉毛的结构细节都在,未发现伪影或撕裂。
八、一处需要修正的归因
在初版报告中我们写道:"45 步档不软,高频能量为基线的 1.01~1.05,甚至比 25 步基线更实。"
数值本身没有错,但归因是错的,此处修正。
那个结论拿的是"45 步 + Spectrum"去比"25 步的基线" —— 变量有两个(是否启用 Spectrum、步数 25 还是 45)。把步数效应单独拆出来(见 7.4 节),可以看到多跑 20 步本身就能换到 8% ~ 34% 的高频能量。
因此,"更实"来自多跑的那 20 步,不是 Spectrum 的贡献。
修正后的准确表述:
- Spectrum 相对同步数基线,高频能量下降 6% ~ 22%(
spec45 / base45 = 0.78 ~ 0.94)。
spec45 / base25 ≈ 1.01 ~ 1.05 只说明 45 步档的 Spectrum 与 25 步基线大致持平,不能读作 Spectrum 带来了额外细节。
这也改变了对它的价值描述:Spectrum 的作用是把"25 步的质量"从 69 s 压到 41 s,而不是把"45 步的质量"变快。
九、细节能量的绝对水平与扰动幅度
各档在各区域的拉普拉斯响应方差(越大表示细节越多):
| 区域 |
base@25 |
base@45 |
spec@25 |
spec@45 |
| face_center |
264.44 |
306.26 |
235.30 |
267.58 |
| eyes |
418.96 |
492.72 |
367.54 |
427.24 |
| mouth |
177.41 |
191.65 |
168.47 |
179.19 |
| hairline |
420.02 |
491.73 |
367.14 |
428.86 |
| bg_corner |
192.23 |
257.41 |
144.27 |
201.44 |
只看两组比值:
| 比值 |
范围 |
含义 |
spec45 / base25 |
1.010 ~ 1.048 |
Spectrum@45 的细节 ≈ 25 步基线 |
spec45 / base45 |
0.783 ~ 0.935 |
达不到 45 步基线的细节 |
像素扰动幅度是另一个值得记录的对照:
| 对比 |
MAE 范围 |
变化来源 |
spec45 vs base45 |
1.974 ~ 2.923 |
仅启用 Spectrum |
spec25 vs base25 |
1.974 ~ 3.299 |
仅启用 Spectrum |
base45 vs base25 |
5.141 ~ 6.274 |
仅改变步数 |
Spectrum 引入的像素扰动,比"多跑 20 步"带来的变化还小。 也就是说,它改变的幅度落在"同一张图的不同采样轨迹"这一量级之内,而不是把图换掉。
十、显存与内存开销
| 项 |
实测值 |
| GPU0 峰值 |
11726 MB / 16384(71.6%) |
| 参考:纯 t2i 无 Spectrum(既有实测,非本轮同批) |
10922 MB |
| 差值 |
约 +800 MB |
| GPU1 |
7017 MB 恒定(文本编码器常驻) |
| 系统内存可用 |
16.8 ~ 17.5 GB(负载 43% ~ 45%) |
| ComfyUI 进程工作集 |
2123 ~ 2159 MB |
缓存开销与理论估算吻合:1024² 画布下单个 anchor 约 128 MB(bf16),最多同时保留 8 个,合计约 1 GB。
cache_device 提供三档(main_device / offload_device / cpu),显存紧张时可以往后退一档,代价是额外的传输开销。
结论:t2i 档(峰值 71.6%)完全装得下,这部分开销不构成问题。
十一、适用边界
编辑 / 多图参考链:不适用。 该链在本机的显存峰值为 15218 MB(94.2%),再叠加约 800 MB 必然溢出。此外,节点作者本人对 Qwen Image Edit 的评价也不高 —— 该链的 60 层结构全部使用 split timestep_zero modulation,主 token 的步间变化约为文生图场景的 3 倍,外推误差的累积条件更差。两条理由指向同一结论。
2K 及以上画布:不适用。 缓存开销随 token 数线性增长,2048² 画布下单个 anchor 约 512 MB,8 个合计约 4 GB,16 GB 单卡放不下。
与含 SageAttention 的数据不可直接对齐。 本机未安装 SageAttention,基线使用 PyTorch 原生 cross-attention。部分公开数据的加速比中包含 Sage 的贡献,引用时需注意。
当前不支持的条件已经较多,因此建议把它视为实验档位而非生产默认。 目前的交付工作流中,t2i 链路默认启用(45 步),编辑链路挂载但旁路;两条路径都可以通过一步操作切换回纯基线。
关于"还没测过的同类方案":本文不能替它们下结论。 前面给出的否定结论,其论域只覆盖真正跑过的那几条。缓存复用这一族里,EasyCache 与 LazyCache 是 ComfyUI 原生自带的节点(comfy_extras/nodes_easycache.py,分类在 advanced/debug,标注为实验性),零安装成本,走的是与 Spectrum 相同的官方扩展点;我们此前在 H3 上否定的是 FirstBlockCache,而它"命中率为零"的成因与该模型只有 8 步蒸馏有关,这个成因无法直接搬到 25 / 45 步的文生图场景。同样,QwenImage21Cache(Prefix KV Cache)本就在编辑链里默认开启(device=auto),它的实际贡献也从未被单独测量过——该节点自带 device=off 开关,做一次对照的成本接近零。
这三条都还没测。它们未必更好,但在测过之前,"没有更快的方案"这个判断是欠账的。
十二、数字的解读口径
- 本文与节点作者公布的数据均为单 seed、单 prompt(样本量 1)。 应当作量级使用,而不是精确常数。节点作者在 RTX 3060(928×1664,25 步,euler+simple)上实测 25 步 49 s → 22 s(约 2.2×)、45 步档约 3.1×;与本机的结果处于同一量级,说明这不是 V100 特有的现象。
- 高频能量低不等于观感一定更差。 它只说明细节被平滑了;是否可接受取决于用途。人像、插画这类对皮肤质感敏感的场景会更明显,而此类差异在缩略图上基本不可见。
- 论文的 4.79× 与本机的 2.09× 并不矛盾。 前者对应 40~50 步档,本机测的是 25 步档。引用加速比时应连同步数一起引用。
- 45 步基线的扩散时间来自 wall clock(该运行时未接入本项目的计时封装),而其它三档有服务端 tqdm。四档在同一 wall 口径下可比,结论与 tqdm 口径一致。
十三、复现
python tools/run_server_timed.py --log logs/xxx_svc.log --bat run_comfyui_V100_lowvram_qwen.bat
python tools/tmp/spectrum_ab_test.py --run all --seed 20260924
python tools/tmp/spectrum_ab_test.py --run spec_base45 --seed 20260924
python tools/tmp/spectrum_crop_cmp.py --base ComfyUI/output/spec_base45_00001_.png \
--spec45 ComfyUI/output/spec_spec45_00001_.png \
--outdir logs/spectrum_crops_b45
python tools/tmp/spectrum_blog_figs.py
接线:UNETLoader → SpectrumQwenImage21 → KSampler.model。参数使用节点作者默认值即可。
两个容易踩的操作细节:
- 服务必须通过
tools/run_server_timed.py 启动。在 Git Bash 中直接用 cmd //c <bat> 会被参数解析吃掉,只输出一行横幅就退出。
- 若机器上已有服务占用 8188 端口,重复启动不会报"端口占用",而是以
OSError [WinError 1114] c10.dll 初始化失败 结束,且启动器会静默返回 0。看到这个错误先查端口,很可能已有可用服务,直接复用即可。
十四、结论
- 可用,且仅限纯文生图。
- 推荐工作点:45 步。 扩散 41 s(tqdm)/ 45.2 s(wall),细节约等于 25 步基线,比 25 步基线快约 1.7×。
- 相对同 45 步基线,加速 3.09×,代价是细节降到基线的 78% ~ 94%。
- 25 步档约为 2.09×,这是该档位的实际上限,不宜按论文数字预期。
- 编辑 / 多图参考链与 2K 画布不适用,显存会溢出。
一句话概括:它把"25 步的质量"从 69 s 压到 41 s,而不是把"45 步的质量"变快。
真人
以上为AI 均为总结的内容,以下是人:
- “bg_corner 是本次对照里最容易看出差异的区域” 这点我不同意,AI 应该用数据得出的结论,我觉得还是脸部细节的差距比较大,雀斑,眉毛,嘴唇,基线细节更多,观感就是更显老。
- 多少少少糅合了其他信息,所以除了速度的变化和结果对比。其他信息只在本台电脑有效。