返回首页

FLUX.2-dev GGUF Q4_K_M:在 Apple Silicon 上占用 29 GB VRAM

Apple M3 Pro 上 FLUX.2-dev GGUF Q4_K_M 模型内存消耗分析显示峰值达 28.92 GB,而非预期的 19 GB。主要消耗项——MPS-overhead 和权重去量化。提出增量传输和 empty_cache 的优化,将峰值降低 1.5 GB。

FLUX.2-dev GGUF 中的 29 GB VRAM:M3 Pro 上的分解与优化
Advertisement 728x90

FLUX.2-dev GGUF Q4_K_M 在 Apple Silicon 上为何占用 29GB 显存

理论上,量化后的 FLUX.2-dev 模型(GGUF Q4_K_M 格式)应仅需约 19GB 内存,但在搭载 M3 Pro 芯片的 Apple Silicon 设备上,其显存峰值高达 28.92GB。深入分析发现,额外消耗的内存主要来自 MPS 开销、权重反量化过程,以及统一内存中 CPU 与 GPU 之间的数据传输。

加载架构与逐级卸载机制

FLUX.2-dev 使用 Mistral-Small-3.2-24B 文本编码器,全精度下需 45GB 显存。针对 Apple Silicon,采用 MLX 提供的 4 位版本,占用 16GB。整个流程遵循逐级卸载模式:

  • 加载 MLX 编码器(约 13GB)。
  • 在 CPU 上将提示词编码为嵌入向量。
  • 卸载编码器并清空缓存。
  • 从磁盘加载 DiT 模型(GGUF Q4_K_M,约 19GB)。
  • 在 CPU 上初始化 VAE 和调度器。
  • 将完整推理管线迁移至 MPS。

理论峰值是各组件最大值的总和,但实际表现受统一内存机制影响而不同。

Google AdInline article slot

测试环境

  • macOS: 26.3.1 (Tahoe)
  • 芯片: Apple M3 Pro,36GB 统一内存
  • Python: 3.14.3
  • PyTorch: 2.11.0
  • diffusers: 0.38.0.dev
  • mlx-lm: 0.31.1

使用 phys_footprint(类似活动监视器)和 PyTorch 的 MPS 指标进行性能分析。psutil.rss 不计入 MPS 分配的内存。

详细内存使用拆解

分阶段测量结果

| 阶段 | phys_footprint | MPS 驱动 | MPS 当前 |

|-------|----------------|------------|-------------|

Google AdInline article slot

| 基线 | 0.27 GB | 0 | 0 |

| MLX 编码器加载后 | 13.22 GB | 0 | 0 |

| GGUF 在 CPU 上 | 19.23 GB | 0 | 0 |

Google AdInline article slot

| pipe.to(mps) | 23.79 GB | 20.06 GB | 18.75 GB |

| 推理中段 | 26.50 GB | 25.62 GB | 18.78 GB |

峰值 28.92GB 出现在 pipe.to("mps") 阶段,原因是 CPU 和 MPS 同时存在数据副本。

28GB 峰值构成解析

  • DiT Q4_K_M(uint8):18.59 GB
  • VAE(bf16):0.16 GB
  • MPS 池开销:+1.31 GB
  • IOKit/Metal graphCache:~3.73 GB(着色器、页表、待处理缓冲区)

GGUF 权重在 MPS 上保持 uint8 格式;反量化为 bf16 在前向传播过程中逐层完成。临时 bf16 张量(最高达 6.92GB)在缓存中累积。

降低峰值内存的优化策略

  • 增量式 MPS 迁移:逐个参数迁移,并每 30 个参数执行一次 gc.collect()
def _move_to_device_incremental(pipe, device):
    n = 0
    for attr in list(vars(pipe)):
        comp = getattr(pipe, attr, None)
        if not isinstance(comp, torch.nn.Module):
            continue
        for param in comp.parameters():
            param.data = param.data.to(device)
            n += 1
            if n % 30 == 0:
                gc.collect()
        for buf in comp.buffers():
            buf.data = buf.data.to(device)
        gc.collect()
    torch.mps.synchronize()
    torch.mps.empty_cache()
  • 步骤间清空缓存:在推理步骤中加入回调,使用 torch.mps.empty_cache() 清除反量化缓存。
  • 生成后清理:推理完成后,执行 gc.collect() 再调用 torch.mps.empty_cache()

优化效果对比

| 指标 | 优化前 | 优化后 | 变化 |

|--------|--------|-------|-------|

| 峰值 phys_footprint | 28.92 GB | 27.36 GB | -1.56 GB |

| 推理后稳定状态 | 26.25 GB | 21.76 GB | -4.49 GB |

| 生成耗时(1 步) | 2:04 | 2:11 | +7秒 |

峰值下降源于加载阶段的增量垃圾回收;稳定状态改善来自缓存清理。无法优化的 MPS/IOKit 开销仍维持在约 3.5GB。

核心结论:

  • 稳定状态最低约 24GB,推理峰值约 27GB。
  • 主要成本:18.59GB 的 uint8 DiT 权重 + 3.5GB MPS 开销。
  • 反量化至 bf16 增加 3–5GB 临时缓冲区。
  • CPU→MPS 传输因统一内存机制使峰值翻倍。
  • 优化后峰值减少 1.5GB,稳定状态减少 4.5GB,且无质量损失。

FLUX.2-dev GGUF 在 M3 Pro 上的实际最小需求为 24GB 以上统一内存。对于更小配置,需采用更激进的量化或 CPU 卸载方案。

— Editorial Team

Advertisement 728x90

继续阅读