【内容摘要】本文总结一套可复用的单机 AI 工作站多模型调度方法论,共七层:硬件边界摸底、统一账本、分层常驻、资源独占、四自闭环、性能劣化识别、能力产品化。每层均配有实测数据支撑,文末给出十条可复用结论清单。
【编写目的】为任何统一内存架构的单机 AI 工作站提供一套可落地、可复用的调度方法论。
一、问题的提出
当一台机器要同时承载文本推理、视觉理解、文生图、文生视频四类任务时,调度就成了核心工程问题。本文总结一套可复用的调度方法论,适用于任何统一内存架构的单机 AI 工作站。
二、方法论第一层:先摸清硬件真实边界
账面参数和实际能力往往差很远。必须先用实测确定三条边界。
这次用的是 AiPy,图它成本低、省事,您用顺手的工具也一样。边界一,同时驻留模型数上限。这台机器账面 96GB 显存池,实测同时最多 2 个大模型,第 3 个必然报 Vulkan 分配失败。这个上限由 Vulkan 单 buffer 策略决定,不是账面 GB 数能推算的。
边界二,模型切换成本。实测卸载等 15 到 20 秒,加载等 15 到 25 秒,合计 30 到 45 秒。高频切换场景会累积大量等待时间。
边界三,跨引擎资源冲突。LLM 引擎和生图引擎各自独立分配显存,互不知情,同时运行必然冲突。
这三条边界是所有调度策略的前提。不摸清就设计,后面必然返工。
三、方法论第二层:统一账本
调度的基础是一个统一账本,把 LLM 实占、生图预估、系统内存三者放在一起算。
账本要回答四个问题:当前加载了哪些模型、各占多少显存、系统还剩多少内存、还能容纳多大的新模型。
设计要点:账本必须按模型个数加单模型峰值双维度判断,不能只按总 GB 相加。因为显存分配有碎片和单 buffer 上限,总 GB 够不代表能加载。
四、方法论第三层:分层常驻
把模型分成常驻层和按需层。
常驻层放高频使用的模型,比如主脑和看图模型,长期驻留不卸载。
按需层放低频模型,比如深度推理和长文写作,用 TTL 自动卸载,闲置一段时间后释放显存。
分层的关键是算准 KV 缓存开销。KV 缓存和参数量不成正比,取决于 KV 头数。这台机器上,Qwen3-30B-A3B 只有 4 个 KV 头,64K 上下文仅需 3GB;Qwen3.8-27B 有 8 个 KV 头,64K 要 8GB。参数量相近,开销差 2.7 倍。
所以分层设计必须按单模型峰值估算,不能按参数量拍脑袋。
五、方法论第四层:资源独占而非超限判断
这是最容易做错的一层。
直觉做法是设一条红线,超过红线才让位。但实测证明,红线判断只能防分配失败,防不了性能劣化。
数据:LLM 占 35.44GB,生图需 8GB,合计 43.44GB,远低于 81GB 红线,于是放行。结果生图从 70.5 秒劣化到 161 秒,慢 2.3 倍。批量出图更严重,四格耗时 29.7、52.9、125.5、205.5 秒,逐格劣化 7 倍。
这次基于成本和便捷选了 AiPy,您好奇也可以尝试,用别的工具也不影响。正确做法是无条件独占:任何生图任务开始前,先清空全部 LLM,不管账本超没超红线。
改造后四格耗时变成 21.7、30.0、20.2、20.0 秒,全流程从 9.1 分钟压到 2.9 分钟。
配套要点:批量任务要整批只卸载一次,批次内不恢复,避免反复卸载加载白烧时间。卸载后要轮询确认显存真正释放,Vulkan 释放是异步的,实测需约 18 秒。
六、方法论第五层:四自闭环
调度器最终要具备四种能力。
自侦测:显存账本、服务心跳、模型哈希巡检、ACL 快照比对、性能劣化判定。
自防控:安全网关每次分派前巡检,残留进程自动清理,模型只读 ACL 加完整性基线。
自优化:自适应 TTL、生图强制独占、批量单次卸载、档位切换冷却。
自愈:碎片化自动重启、服务离线自动拉起、主脑未加载自动补载。
其中自愈是最容易被忽略的。很多调度器只做侦测和告警,不做自动修复,结果还是要人工介入。
七、方法论第六层:性能劣化的自动识别
长期运行的机器必然出现性能劣化。关键是能不能自动识别并自愈。
实测现象:连续跑几十次生图后,耗时从 13.4 秒劣化到 42.5 秒,三轮数据高度一致。
排查方法(逐项排除):
1. 查残留进程,0 个,排除。
2. 查系统内存,23GB 充足,排除。
3. 查 LLM 驻留,0 个,排除。
4. 裸跑引擎绕过调度器,同样 45 秒,排除调度层。
5. 重启服务,恢复 13.2 秒,确认是显存碎片。
自愈规则:连续 3 次耗时超基准 2 倍,判定碎片化,自动重启服务。
这个规则实测很准:正常耗时 13.4、13.7、14.0 不误报,劣化耗时 42.5、42.7、43.0 第三次准确触发。
八、方法论第七层:把调度能力产品化
调度器做成命令行工具,只有工程师会用。做成桌面控制台,机主才能日常使用。
产品化要点:
1. 状态可视化。服务状态、模型加载、显存账本、内存余量、碎片预警,一屏可见。
2. 操作一键化。启动全部、停止全部、重启服务、立即自愈,四个按钮覆盖 90% 场景。
3. 组合方案化。把常用的模型组合固化成方案,一键切换,不用每次手动加载。
4. 参数可调。步数、CFG、采样器、上下文、TTL,常用参数暴露出来,高级参数收起来。
5. 服务化开关。开机自启加定时自愈,做成一个开关,机主自己决定开不开。
九、可复用结论清单
1. 先实测硬件边界,再设计调度。账面参数不可信。
2. 账本按模型个数加单模型峰值双维度判断,不按总 GB 相加。
3. 分层常驻,常驻层高频、按需层 TTL。KV 开销按 KV 头数算,不按参数量算。
4. 资源冲突用独占解决,不用红线判断。红线防不了性能劣化。
5. 批量任务整批单次卸载,不逐张卸载恢复。
6. 卸载后轮询确认释放,Vulkan 释放是异步的。
7. 性能劣化要能自动识别,用连续 N 次超阈值判定。
8. 自愈要真正执行,不能只告警。
9. 调度能力要产品化,命令行只是过渡形态。
10. 所有参数改动单独 A/B 验证,不做打包式调优。
十、结语
这套方法论是从一台真实工作站上反复踩坑总结出来的,不是理论推演。核心思想只有一句:用实测数据驱动架构演进,别一开始就设计完美系统。
成文前又用 AiPy 核了一遍——图它省钱省力,您用熟悉的工具一样能复核。
如果您也在做单机 AI 工作站,欢迎交流。调度这件事,坑比想象的多,但方法是可以复用的。
十一、补充:模型选型的实测依据
调度方法论落地时,模型选型直接影响调度策略。这台机器上实测了六款模型。
主脑选 Qwen3-30B-A3B,17.35GB,32K 上下文,MoE 架构每次只激活 3.3B,速度接近 3B 小模型,能力接近 30B 大模型。适合高频分派。
看图选 Qwen3-VL-30B-A3B,19.3GB,16K 上下文。视觉能力对标 72B 模型。
深度推理选 Qwen3-30B-A3B-Thinking-2507,17.28GB,64K 上下文。数学推理能力碾压级。
长文写作有两个版本,Q4_K_M 是 15.66GB,Q5_K_M 是 18.19GB。Q5 精度更高但体积大 2.5GB,按需选用。
草稿模型 Q4_0 只有 1.56GB,用于投机解码加速。
十二、补充:组合方案的固化
把常用组合固化成方案,一键切换,比每次手动加载高效得多。
方案 A 双常驻:主脑 32K 加看图 16K,合计 36.7GB。适合高频图文混排工作。
方案 B 单常驻:仅主脑 32K,17.35GB。内存最宽松,其余按需 TTL 换入。
方案 C 高质长文:主脑加 Q5 长文,合计 35.5GB。长文档质量优先。
三个方案覆盖 90% 场景,剩下的特殊需求走手动加载。
十三、补充:安全机制的落地
本地部署不等于安全。模型文件被篡改、被投毒,后果很严重。
落地了三层防护。
第一层,只读 ACL。模型目录设置 DENY 写入删除权限,即使被授予写权限也无法写入。实测验证:写入被拒、新建被拒、删除被拒、读取正常。
第二层,完整性基线。所有模型文件登记 SHA256 哈希,每次加载前比对,不一致立即告警并拒绝加载。
第三层,受控写入通道。需要新增模型时,走解禁、移入、校验、重锁四步流程,全程留痕。
这三层机制保证了模型供应链安全,同时保留了可维护性。
十四、补充:产品化的界面设计
调度器做成桌面控制台时,界面设计有几个要点。
状态区要一屏可见。服务状态、模型加载、显存账本、内存余量、碎片预警,五项信息放在最上方,每 10 秒自动刷新。
操作区要一键化。启动全部、停止全部、重启服务、立即自愈,四个按钮覆盖 90% 场景。
组合方案要可视化。三个方案做成按钮,选中的方案用金色高亮加对勾标识,一眼看出当前状态。
参数区要分层。常用参数(步数、CFG、采样器、上下文、TTL)暴露出来,高级参数收起来。
服务化要做成开关。开机自启加定时自愈,一个勾选框控制,机主自己决定开不开。
十五、补充:踩坑清单
参数误用:sd-cli 的 -t 是 threads 不是 steps,导致 Turbo 模型长期跑默认 20 步,掩盖真实性能。
加载方式:Flux 必须用 --diffusion-model,-m 不识别 GGUF。
量化选择:Flux Q4_K_S 在当前环境画质不可用,拉普拉斯只有 195,是 SDXL-Turbo 的十一分之一。
引擎稳定性:ncnn 的 Qwen-Image 跑 3 到 4 步就崩,三次实测全失败,最终停用。
下载受阻:HuggingFace 的 Xet 存储被墙,需卸载 hf_xet 包改走镜像,加断点续传和校验。
UI 坑:ttk.Button 的 background 属性在 Windows 主题下会被覆盖,必须用 tk.Button 原生 bg。
回调坑:后台任务的 done 回调只在成功时执行,失败时按钮状态不更新,要把状态标记放在点击瞬间。