ComfyUI 在 Apple Silicon 上的已知边界:先分清是 MPS 的限制,还是你装错了环境

2026-08-09

在 Mac 上折腾 ComfyUI,最容易走进的死胡同不是某个具体报错,而是一句万能归因:「M 芯片就是不行」。这句话一出口,后面所有排查动作就都停了——本来只是 PyTorch 装了个不对的轮子,或者某个自定义节点在图里塞了个 MPS 后端接不住的算子,结果被当成平台原罪放弃掉。

这篇只做一件事:把 Apple Silicon 这条路上,官方明确写下来的边界,和我们其实并不知道的部分,划清楚。写在前面的话也说清楚:下面不提供任何「这样配就好了」的保证。ComfyUI 官方自己对不少开关都标了 Experimental、未经测试,我更没有立场替你打包票。

一、官方给 Apple Silicon 的是什么

先看清楚起点。ComfyUI 的 README 在 Installing 章节把安装路径分了四种:Desktop Application(Windows 与 macOS,README 的原始定位是「最简单的上手方式」,并明确强烈推荐新用户用它)、Windows Portable Package(仅 Windows,README 反而写明「不推荐普通用户使用」)、Manual Install(支持所有操作系统与 GPU 类型,NVIDIA、AMD、Intel、Apple Silicon、Ascend 都在列),以及付费的 Comfy Cloud。

也就是说,Mac 用户有两条正路:桌面应用,或者手动安装。区别在于,出问题时能不能自己动手换 PyTorch、加启动参数、看完整日志——本文讲的所有判定动作,基本都建立在手动安装那条路上。

README 对 Apple Mac silicon 给的原始说明很短,短到值得逐条抄下来:

  1. 适用范围写的是 M1、M2、M3、M4,配任意较新的 macOS
  2. 第一步是装 PyTorch nightly,README 在这里没有直接给出 pip 命令,而是指向 Apple 的开发者指南《Accelerated PyTorch training on Mac》。
  3. 然后按 Manual Install 的步骤走。
  4. 在 ComfyUI 目录里装依赖:pip install -r requirements.txt
  5. 启动:python main.py
  6. README 额外提醒:把模型、VAE、LoRA 等放进 Comfy 对应的目录里。

这里有个细节值得单独拎出来。README 给 NVIDIA、AMD ROCm、Intel XPU 都写了可以直接抄的 pip 安装命令(NVIDIA 稳定版那条用的是 --extra-index-url,AMD ROCm 与 Intel XPU 那几条用的是 --index-url),唯独 Mac 这一段是「去 Apple 的页面按说明装」。所以但凡你在别处看到一条声称「Mac 上装 ComfyUI 的 PyTorch 命令」,它都不是 ComfyUI README 给的,来源需要你自己核。以 Apple 那份指南的当前内容为准,我不替它复述版本号。

另外,README 的 Python/PyTorch 版本矩阵是全平台通用的,这几条对 Mac 同样成立:Python 3.13 支持得很好;Python 3.14 能用,但某些自定义节点可能有问题,free threaded 变体因为部分依赖会启用 GIL 而不算完全支持;如果在 3.13 上遇到自定义节点的依赖问题,可以退回 3.12。torch 2.7 是最低支持版本,但 README 极力推荐用更新的版本,并且明确写了一句:如果你的 PyTorch 超过 6 个月没更新,请更新它。矩阵里那条「cu130 及以上在 NVIDIA 20 系及以上是必需的」是 NVIDIA 侧的要求,别往 Mac 上套。

二、怎么确认「确实是走在 MPS 这条路上」

排查的第一步不是搜报错,是确认自己当前跑在哪个后端上。这一步有源码依据,不用猜。

comfy/model_management.py(v0.31.0)里有两个枚举。一个是设备状态:

class CPUState(Enum):
    GPU = 0
    CPU = 1
    MPS = 2

MPS 是独立的一档,跟 GPUCPU 并列。另一个是显存状态机:

class VRAMState(Enum):
    DISABLED = 0    #No vram present: no need to move models to vram
    NO_VRAM = 1     #Very low vram: enable all the options to save vram
    LOW_VRAM = 2
    NORMAL_VRAM = 3
    HIGH_VRAM = 4
    SHARED = 5      #No dedicated vram: memory shared between CPU and GPU but models still need to be moved between both.

可执行的判定动作:启动 ComfyUI,回到终端翻最前面几行,找这两行日志(都是源码里的格式串):

  • Total VRAM {:0.0f} MB, total RAM {:0.0f} MB
  • Set vram state to: {vram_state.name}

第二行打印的名字,就是上面枚举里的那几个之一。注意 SHARED 那条注释写的是「没有独立显存:内存在 CPU 与 GPU 之间共享,但模型仍然需要在两者之间搬运」——听起来跟统一内存架构对得上,但这两段源码只有枚举与注释本身,并没有写明「哪个平台一定映射到哪个状态」,所以别预设,以你自己那一行日志打印出来的名字为准。同理,每个状态下具体会做哪些动作,源码注释只给了这么多,我不往下编。

嫌日志不够细,可以加 --verbose。它的合法等级是 DEBUGDETAILINFOWARNINGERRORCRITICAL,不带值时等价于 DEBUG,控制台默认是 INFO。另外提醒一句,--log-stdout 存在是有原因的:ComfyUI 正常的进程输出默认走 stderr,如果你习惯 python main.py > log.txt 这么重定向,会发现文件里什么都没有。

如果 Set vram state to: 这一行压根没打印出来,那说明进程死在更早的阶段(依赖导入、PyTorch 本身起不来),此时讨论 MPS 支不支持某个算子毫无意义——先解决装环境的问题。README 唯一给出的一条 Troubleshooting 也在这个层面:出现 Torch not compiled with CUDA enabled 时,pip uninstall torch,再按你平台对应的方式重装。在 Mac 上看到这句话,几乎就是环境装串了的信号。

三、官方口径下,这条路上已知的坑长什么样

接下来是本文最需要克制的部分。ComfyUI 官方仓库里确实有几条长期挂着的 macOS 相关 issue,但我们只取到了编号、标题、创建日期、标签和状态,没有读过任何一条 issue 的正文与评论。所以下面只给引用,不给分析:

  • 官方仓库 issue #4165 反映了「FLUX Issue | MPS framework doesn’t support float64」这一现象,创建于 2024-08-01,标签为 Potential Bug、MacOS,截至 2026-08-09 仍为 open
  • 官方仓库 issue #2044 反映了「Conv3D is not supported on MPS」这一现象,创建于 2023-11-24,无标签,截至 2026-08-09 仍为 open
  • 官方仓库 issue #2992 反映了「MacOS Sonoma 14.4 update breaks GPU acceleration on Apple Silicon」这一现象,创建于 2024-03-08,无标签,截至 2026-08-09 仍为 open

先注意标签的字面含义:#4165 挂着的 Potential Bug 是「疑似 bug」,不等于官方已确认;另外两条连标签都没有,就更谈不上被定性。而 open 状态也不等于「官方还没做」或「永远不会好」——它只是这一天的状态快照。我没有读过这些 issue 里的复现步骤、日志和讨论,因此不会告诉你它们的根因是什么、社区里有什么 workaround。你要做的是:拿自己的报错去仓库里对号,看现象是否真的一致,而不是看到「MPS」两个字就认领。

这里也顺带说清一件事:#2992 的标题指向的是系统升级这个变量。这提醒我们,Mac 这条路上的变量至少有三个——macOS 版本、PyTorch 版本(而且官方要求的是 nightly)、ComfyUI 版本。三个都在动,出了问题只改其中一个再看结果,是唯一靠谱的排查节奏。

四、可以试的官方开关,以及它们的语义边界

强调一次:下面这些参数只讲 comfy/cli_args.py(v0.31.0)里 help 写了什么,不代表它们能解决上面任何一条 issue。参数与默认值随版本变动,以你本机 python main.py --help 的实际输出为准。

参数help 的原意
--cpu-vae在 CPU 上跑 VAE
--cpu全部用 CPU(help 直白地写了「慢」)
--fp32-vae / --bf16-vae / --fp16-vaeVAE 精度三选一,互斥;其中 --fp16-vae 的 help 注明 might cause black images
--force-fp32 / --force-fp16全局精度,互斥
--use-pytorch-cross-attention使用 PyTorch 2.0 的 cross attention 实现
--disable-all-custom-nodes不加载任何自定义节点
--whitelist-custom-nodes NAME [NAME ...]在上一条开启时,仍加载指定的自定义节点目录

怎么读这张表?--cpu-vae 的价值在于粒度:它只把 VAE 这一段挪到 CPU 上,而不是像 --cpu 那样整个流程都退回 CPU。如果你的问题恰好只发生在解码那一步,这是个比全局退回代价小的选项。但 help 就写了这么一句,它是否能规避某个具体算子的限制,官方没说,我也不替它说。

--cpu 有一个 help 文本之外的连带效果,Mac 用户尤其容易踩。comfy/cli_args.py(v0.31.0)里 dynamic VRAM 的启用判定是这样的:

def enables_dynamic_vram():
    if args.enable_dynamic_vram:
        return True
    return not args.disable_dynamic_vram and not args.highvram and not args.gpu_only and not args.novram and not args.cpu

看最后那一项:--cpu 会顺带把 dynamic VRAM 关掉--highvram--gpu-only--novram 也一样。也就是说,你为了绕开某个报错加了 --cpu,实际上同时把加载策略退回了基于估算的老路子。这属于「改了一个变量,其实动了两个」,排查时务必记账。

同一段逻辑还解释了另一个反直觉的点:不加任何参数时 dynamic VRAM 是开着的,而 --lowvram 的 help 原文写明「如果启用了 dynamic vram,这个选项不做任何事」。老教程里那句「显存小就加 --lowvram」在当前版本已经不成立。Mac 上抄 Windows/NVIDIA 教程的参数串,这是第一个会白抄的。

再补一条平台差异,源码常量层面的、可以放心讲的:pinned memory 的上限在 comfy/model_management.py(v0.31.0)里分了两个分支,Windows 是 ram * 0.40(注释写「Windows limit is apparently 50%」),非 Windows 系统则是一个把 swap 总量也算进来、并留出 4GB / 16GB 余量的表达式。保留显存常量 EXTRA_RESERVED_VRAM 默认 400MB,Windows 上是 600MB,注释把原因归到 shared vram 问题。源码只分了 Windows 与非 Windows,没有为 macOS 单开分支——知道这一点的用处是:别把 Windows 侧的显存经验数字直接搬到 Mac 上讨论,也别据此外推任何「利用率差多少」的量化结论。想关掉 pin 有 --disable-pinned-memory;异步卸载 --async-offload 的 help 只写了「在 NVIDIA 上默认启用」,其它后端的默认状态 help 没写,日志里有没有打印 Using async weight offloading with {N} streams 是你唯一的依据。

五、动完之后怎么验证

一次只改一个变量,改完按这个顺序核:

  1. 看日志头Total VRAM ... total RAM ...Set vram state to: ... 两行还在不在、打印出来的名字有没有变。做法是改参数前先把这两行原样存一份,改完再对照——源码没有给出「哪个参数一定对应哪个状态」的映射表,所以这里比的是你自己前后两次的日志,而不是去套一个标准答案。如果连日志头都跟之前完全一致,先怀疑参数压根没传进去(比如加到了错误的命令上,或者你启动的其实是桌面应用而不是这条命令行)。
  2. 看开关生效行Enabled pinned memory {}Using async weight offloading with {} streams 这两条打没打印,是判断相关开关有没有真的在起作用的直接依据——源码里就是在启用时才输出这两行。
  3. 看报错是否位移。这是最有信息量的一条:如果加了 --cpu-vae 之后,报错从解码阶段挪到了别处,说明你至少定位对了一段;如果报错一字未变,那这个开关跟你的问题无关,退回去,别叠着加。
  4. 确认版本坐标。记下当前 ComfyUI 版本、PyTorch 版本、macOS 版本。ComfyUI 大约每两周一个版本,requirements.txtcomfyui-frontend-packagecomfyui-workflow-templatescomfyui-embedded-docs 三个包是用 == 精确 pin 的,这意味着升级 core 会连带换掉前端版本。所以「升级后某个现象变了」这件事,本身就需要把 core 版本一起记下来才有讨论价值。

六、什么情况说明不是 MPS 的锅

这一节是本文相对「报错大全」的唯一增量,请务必看完再决定放不放弃。

加了 --cpu 之后,同样的错依然一字不差地出现。 这时候图根本没走 MPS 后端,问题就不在平台上,去查模型文件、节点实现或者依赖版本。

--disable-all-custom-nodes 启动后现象消失。 那是某个自定义节点的问题,不是 Apple Silicon 的问题。接下来用 --whitelist-custom-nodes 一批批放回去做二分,能定位到具体是哪一个。顺带一提,源码里那两条内存相关告警——Potential memory leak detected with model {类名}, doing a full garbage collect... 和更严重的 WARNING, memory leak with model {类名}. Please make sure it is not being referenced from somewhere.——官方给的方向就是「检查是谁还在引用它、避免循环引用」,这几乎总是指向自定义节点,同样适合用这套二分法。

Set vram state to: 这一行从来没打印过。 进程死在更早的阶段,是环境问题。回到第一节,按 Apple 的指南重装 PyTorch nightly,再 pip install -r requirements.txt

报错里出现 Torch not compiled with CUDA enabled 这是装错轮子的典型信号,README 给的处置是 pip uninstall torch 后按平台重装,跟 MPS 支持不支持什么算子完全是两码事。

改了参数却「没重跑」。 别急着怀疑后端。README 的 Notes 章节写得很清楚:只有输出端所有输入都正确的那部分图会被执行;并且只有相对上次执行发生了变化的部分会被执行,提交两次相同的图,只有第一次会真正执行。想强制每次都重跑,--cache-none 的 help 原意就是「降低 RAM/VRAM 占用,代价是每次运行都重新执行每个节点」。

换了个工作流就好了。 那更可能是某个具体节点或模型在这条路径上的限制,而不是整个平台不可用。把差异缩到最小的两个图去比,比对整台机器下结论有用得多。

最后一种:你的报错文本跟 #4165、#2044、#2992 的标题只是「都带 MPS」而已。 别硬套。我们没有读过那三条 issue 的正文,你也不该拿一个标题去解释自己完全不同的堆栈。真要跟进,就去仓库里读原帖,看现象是否一致——这件事只能你自己做。

延伸阅读


本文依据 ComfyUI 官方仓库(github.com/Comfy-Org/ComfyUI)的 README、comfy/cli_args.py、 release notes 与官方安全公告整理,核对日 2026-08-09,对应版本 v0.31.0; 文中引用的 issue 状态为该日期的快照。本文内容为官方文档与源码口径,非本机实测。 参数、默认值与功能随版本变动,请以官方文档与 python main.py --help 的实际输出为准。

想系统学会用 AI?报名体系课或加入会员,照着学、照着用。