资讯详情

96GB显存,FLUX.2-dev一张图还要3分钟?我们把它跑到了35秒:一次完整的FP8优化实战

📅 2026/10/11 4:44:48 | 华诺云谱 👁 阅读
96GB显存,FLUX.2-dev一张图还要3分钟?我们把它跑到了35秒:一次完整的FP8优化实战
一、先讲一个很反直觉的场景卡很贵GPU却经常不干活我们在服务器上做的是4000张遥感风格合成图像2000张RGB可见光2000张合成LWIR红外对应2000个场景。每张1024×1024、FLUX.2-dev、32步扩散、batch size1。刚开始速度很“稳定”每张150180秒。这不是完全不能接受但几千张算下来太漫长了。更糟的是GPU似乎老在“摸鱼”。我们专门监控了约360秒、172个采样点监控项CPU Offload原方案GPU平均利用率25.7%GPU利用率≤20%的采样点79.1%GPU利用率≥80%的采样点20.3%显存占用变化2.862.1GiB当时Python进程CPU使用约99.5%约一个逻辑核心完整单张出图约150180秒注意GPU利用率25.7%不是“显卡性能只发挥了25.7%”的严谨换算它是驱动统计的忙碌情况。但一张图要三分钟、GPU多数时间很空闲、显存不断上上下下三个现象放一起显然值得查。第一条经验不要一看到大模型跑得慢就默认是显卡算不动。二、真相藏在模型大小里96GB竟然也装不下我们把本地FLUX.2-dev权重文件实际扫了一遍模块文件数量BF16权重文件大小Mistral文本编码器1044.72GiBTransformer扩散主干760.02GiBVAE10.31GiB总计18约105.05GiB我们的RTX PRO 6000通过nvidia-smi报告显存97887 MiB换算约95.6GiB。仅BF16权重文件体积就比它大激活、CUDA工作区、缓存还没算呢。于是旧版用了一套很合理的方案CPU Offload。vram_config { offload_dtype: torch.bfloat16, offload_device: cpu, onload_dtype: torch.bfloat16, onload_device: cuda, preparing_dtype: torch.bfloat16, preparing_device: cuda, computation_dtype: torch.bfloat16, computation_device: cuda, }你可以把它想成桌上放不下全部资料就先把暂时用不着的一摞放回柜子要用再抱回来。这样能干活但要是每生成一张图都得来回搬柜子就会明显拖慢连续生产。有一个很容易误会的地方“模型只初始化了一次”不等于“模型组件在每张图的各个阶段不再CPU↔GPU切换”。我们的Flux2ImagePipeline.from_pretrained()确实只执行一次但在DiffSynth的模型设备管理里文本编码、Transformer去噪、VAE解码之间仍可能按需onload()和offload()。后来用nvidia-smi dmon观察到的现象特别有说服力GPU计算SM低的时候PCIe传输却很显眼显存还在慢慢上涨GPU计算跑到高负载时PCIe流量反而少了显存又往下走时反向传输也出现了。这些现象与CPU↔GPU反复搬模型高度吻合。这里还不能给出“每张图150秒里面有多少秒花在搬运”的精确数字因为没做逐算子Profiler但优化方向已经很清楚。三、为什么我们连“GPU显存大幅波动”都觉得焦虑这还不只是速度问题。我们的机器是多人使用的计算服务器。CPU Offload时显存有时掉到几GiBGPU利用率也低旁观者很容易觉得“这卡还很空”。最担心的是另一份任务进来后续双方争显存一不小心OOM长批次生产就停了。这种担忧很现实现有日志能证明真的曾有其他任务跑到GPU而造成OOM。而且Exclusive_Process模式限制的是正常情况下的并发CUDA计算上下文它不是绑定某个用户名的永久GPU租约。你把GPU跑到100%也不是安全隔离真正的资源预约要靠Slurm等调度器、设备权限和服务器管理员的规则。所以我们的优化目标其实有三个出图快、任务稳定、资源状态更容易管理。最后这个目标仍需要正式资源调度配合不能只靠调模型参数。四、最关键的转折老师一句话换了一个思路感谢DiffSynth项目开发老师的指导阿里巴巴魔塔社区DiffSynsth团队我们开始尝试权重用FP8 E4M3FN存设备尽量都选CUDA真正计算依然使用BF16。fp8_cuda { offload_dtype: torch.float8_e4m3fn, offload_device: cuda, onload_dtype: torch.float8_e4m3fn, onload_device: cuda, preparing_dtype: torch.float8_e4m3fn, preparing_device: cuda, computation_dtype: torch.bfloat16, computation_device: cuda, }别把它读成“模型都用FP8直接算所以快了”。我们得到加速的合理解释是FP8减少大模型权重驻留体积让模型有机会长期留在显存从而少做很多CPU↔GPU搬运。它不等于所有计算都走了FP8 Tensor Core也不保证其他DiffSynth版本或GPU会有相同结果。我们先没有碰正在生成红外的GPU3而是选了空闲的GPU1物理第2张卡独立建项目、独立输出、独立SQLite直接做RGB的2000张批量生产。没想到第一次并没有成功。五、最扎心的坑32步只跑33秒结果每张图都失败启动后前半段简直让人惊喜100%|██████████| 32/32 [00:33, 1.05s/it]以前三分钟一张现在扩散阶段只用了33秒。可是紧接着每张任务都报File diffsynth/models/flux2_vae.py, line 2106, in decode latents_bn_std torch.sqrt(self.bn.running_var.view(...) 0.0001) RuntimeError: ufunc_add_CUDA not implemented for Float8_e4m3fn为什么因为我们一开始把Mistral、Transformer、VAE全套用了FP8。VAE内部有BatchNorm相关统计量加法当前PyTorch CUDA路径不支持这种FP8加法。重点不是OOM不是显卡不支持整套模型不是提示词错了。错误发生在VAE解码阶段。扩散进度条达到100%也没有任何用PNG根本没保存。后来统计发现旧错误影响了27条失败记录的重试计数。我们停掉GPU1服务、备份原文件和SQLite再做了一个非常小的修改。六、真正跑通大模型FP8小VAE留BF16修复其实只要抓住一个原则谁必须FP8就给谁别把小模块也一股脑量化。我们的最终加载配置核心是from diffsynth.pipelines.flux2_image import Flux2ImagePipeline, ModelConfig MODEL_ID black-forest-labs/FLUX.2-dev model_configs [ # 大模块1Mistral文本编码器 ModelConfig( model_idMODEL_ID, origin_file_patterntext_encoder/*.safetensors, **fp8_cuda, ), # 大模块2FLUX.2 Transformer ModelConfig( model_idMODEL_ID, origin_file_patterntransformer/*.safetensors, **fp8_cuda, ), # 小模块VAE保留默认BF16不传入FP8配置 ModelConfig( model_idMODEL_ID, origin_file_patternvae/diffusion_pytorch_model.safetensors, ), ]以上仅是ModelConfig核心片段完整运行还需要本地模型、tokenizer_config、pipeline初始化及任务循环。我们在当前DiffSynth提交版本上验证了它而不是说所有版本都能复制即跑。VAE只有约0.31GiB保持BF16占用的空间并不大却避开了FP8不兼容的运算。这一次终于看到了真正想要的日志17:58:00 MODEL LOADED ONCE 17:58:35 SUCCESS 0001 (35.8s) ...visible.png 17:59:10 SUCCESS 0003 (34.9s) ...visible.png去噪完 → VAE解码完 → PNG写盘 → 任务标记SUCCESS → 继续下一张。这才是完整的成功。我们也记住一个新规矩永远用可读取的最终图片和结果状态作为生成成功的证据不用进度条替代。七、稳了之后才轮到另一张显卡GPU3原进度不能丢GPU1开始高速出RGB后GPU3还在用原BF16 CPU Offload跑LWIR。于是我们把修复后的FP8方案迁移到GPU3做成v6.5。但原则是绝对不为提速重刷已经生成的红外图。v6.5上线流程是先做只读校验4000条提示词SHA256、红外优先任务顺序、GPU的PCI/UUID、现有SQLite。优雅停止GPU3旧v6.3服务对SQLite做一致性备份。启动v6.5保留相同的图片输出目录和断点状态Mistral/Transformer用FP8 CUDA、VAE用BF16。最多等待480秒必须确认至少一张新增的真实1024×1024 PNG成功保存才启用新版本为正式服务否则尝试回退。最终日志是最好的回答MODEL LOADED ONCE (FP8 TEDiT CUDA, BF16 VAE) infrared complete98 missing1902 SUCCESS 0198 (35.4s) ...infrared.png SUCCESS 0200 (34.2s) ...infrared.png SUCCESS 0202 (34.4s) ...infrared.png SUCCESS 0204 (34.8s) ...infrared.png也就是说以前的98张红外图保住了新的红外图也连续成功生成。旧v6.3服务文件保留以便手动回退当前新旧配置输出的图片会在同一数据集中共存后期研究必须记录它们的生成精度版本。八、最振奋的一幕两张卡一起满负荷工作2026-10-1018:16:59我们同时查询GPU1和GPU3得到了下面这张现场“成绩单”关键指标GPU1 · 可见光GPU3 · 红外版本v6.4修复版v6.5迁移版systemd服务activeactiveGPU利用率该时刻99%100%显存占用56,520MiB56,520MiB温度78°C79°C功率显示601W602W最近成功出图约34–35秒34.2–35.4秒和旧方案比最直观的差异对比项优化前优化后已观测32步、1024×1024完整成功出图150180秒/张约3436秒/张权重驻留BF16 CPU Offload两个大组件FP8 CUDAVAE BF16GPU状态360秒均值25.7%双卡单次快照99%/100%任务连续性v6.2曾遇到图像拒收反复重启两张卡均连续出现SUCCESS以GPU3的4张样本为例平均是34.70秒。如果只用150180秒对比34.70秒差不多是4.35.2倍的单张耗时量级差异若按这个速度简单换算大约104张/小时/卡。但我们不会把这个预测写成已经测到的长期吞吐这里不包括初次加载、失败重试、I/O波动、服务维护时间旧版本的统计窗口、图片模态和样本分布也不完全相同。真要形成结论还得固定任务集合跑更长的A/B测试。九、今天之前版本已经迭代过很多次如果只看35秒容易忘记前面那些绕不过的坎版本解决的主要问题v4纠正视角把文本统一为严格约束v5 / v5.1根据实际出图发现的透视问题重写尺度/模态描述v6 / v6.1形成4000条、2000对稳定任务集与seed/配对编号v6.2红外优先然而在线颜色拒收让任务卡住重复重启v6.3去掉生产阶段的外观拒收先存图、后做图像质检32步稳定流水线v6.4在独立GPU1引入FP8发现VAE解码兼容性问题并修复v6.5原进度保留地迁移GPU3实现FP8高吞吐红外续跑个人实战工程经验陆续更新用于复盘严禁未注明出处的转载。个人实战工程经验陆续更新用于复盘严禁未注明出处的转载。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑