MiniCPM-V 4.7 35B-A3B 本地部署实录:RTX 3070 8GB 显存跑多模态,36 token/s

摘要:19.7GiB 的模型文件跑在 8GB 显存的 RTX 3070 上,本文给出完整启动参数、三组性能实测(纯文字 / 看图 / 1B 对照)、显卡负载对比,以及 llama.cpp 版本、mlock 加载、视频输入三个坑。核心结论:35B 能跑,但瓶颈不在显卡在内存带宽。
关键词:MiniCPM-V 4.7、OpenBMB、llama.cpp、n-cpu-moe、MoE 推理、显存优化、RTX 3070、端侧大模型、GGUF、mtmd

写在前面

MiniCPM-V 4.7 发布时,官方通稿的重点是移动端:3GB 内存、iPad Pro 15+ token/s。我关心的是另一个问题:桌面端,一张 8GB 显存的入门卡,能不能跑?

本文所有数据来自我自己的机器实测,命令、参数、日志原样贴出,可复现。

环境

|------|---------------------------------------------------------------------------------|
| 项目 | 配置 |
| CPU | AMD R9 7900,12 线程 |
| 内存 | 64GB DDR5 5200 |
| 显卡 | RTX 3070 8GB(驱动 581.15,CUDA 13.0) |
| 推理框架 | llama.cpp llama-server(build 11617) |
| 系统 | Windows 10 26100 |
| 模型 | MiniCPM-V-4_7-35B-A3B-Q4_K_M.gguf(19.7GiB)、MiniCPM-V-4_7-1B-Q4_K_M.gguf(641MiB) |

一句话结论

能跑,而且挂上视觉投影器也没吃满 8GB。

|-------------|---------------------------------|--------------------|
| 项目 | 35B-A3B(Q4_K_M) | 1B(Q4_K_M) |
| 能否在 8G 显存上跑 | 能,含视觉 | 能 |
| 生成速度 | 35.5 ~ 42 token/s(长任务稳定 36 上下) | 270 ~ 288 token/s |
| 显存占用 | 3897 MiB(纯文字)/ 6065 MiB(含视觉) | 1021 MiB |
| 加载耗时 | 33 秒(未锁内存) | 7.7 秒 |

核心参数:--n-cpu-moe 41

完整启动命令:

复制代码
llama-server.exe -m MiniCPM-V-4_7-35B-A3B-Q4_K_M.gguf \
  --mmproj mmproj-model-f16-4x.gguf \
  --host 0.0.0.0 --port 8080 \
  -ngl 99 --n-cpu-moe 41 --parallel 3 \
  -ctk q4_0 -ctv q4_0 --flash-attn on \
  --temp 0.85 --top-k 50 --top-p 0.95 \
  --repeat-penalty 1.1 --min-p 0.01

--n-cpu-moe 41 的意思是:前 41 层的 MoE 专家权重留在 CPU 内存,不加载到显卡。 模型共 40 层,所以 41 覆盖全部层,256 个专家一个都不上 GPU。

于是模型被劈成两半:

  • 留在内存:256 个专家权重,模型体积的大头
  • 放进显存:注意力层、词表、embedding 等非专家部分,加当前这一步要用的 8 个专家

MoE 每个 token 只激活 8 个专家,所以显存只需常驻"非专家部分 + 当前 8 个专家"。

代价:瓶颈转移到内存带宽

这是本文最该说清楚的一点。两组 nvidia-smi 采样对比:

|---------|-----------|--------------|
| 项目 | 纯文字模式 | 处理图片时 |
| 显存占用 | 3897 MiB | 6065 MiB |
| GPU 利用率 | 36% | 46% ~ 49% |
| 功耗 | 46W | 158W ~ 168W |
| 温度 / 风扇 | 48°C / 0% | 76°C / 82% |

纯文字模式下显卡功耗只有 46W(上限 220W),大部分时间在等内存送专家权重过来。此时换更强的显卡没有意义,瓶颈在内存带宽。 而一旦挂上视觉投影器,功耗跳到 168W、风扇 82%,显卡才真正开始干活。

显存差值 2168MiB,投影器文件本身 910MB。多出的部分推测为视觉塔中间结果 + 图片 token 的 KV cache(推断,未拆分验证)。

另外,服务开着不释放显存:空闲时利用率 0%、功耗 13W,显存仍是 6065MiB。

图片的 token 代价

实测日志:

复制代码
task 0  :prompt eval time = 8899.90 ms / 1091 tokens(122.59 tokens per second)
task 424:prompt eval time = 6931.62 ms / 2348 tokens(338.74 tokens per second)

同一台机器,纯文字提问的 prompt 只有 34 ~ 333 个 token,一张图就是 1091 ~ 2348 个 token。

这解释了官方为什么在投影器里做视觉 token 压缩。我手上两个投影器的元数据对比:

|--------------------------|---------|-----|--------------|
| 文件 | 体积 | 张量数 | scale_factor |
| mmproj-model-f16.gguf | 1.12 GB | 460 | 4 |
| mmproj-model-f16-4x.gguf | 910 MB | 444 | 2 |

视觉编码器骨架一致(448 分辨率 / 14 patch / 1152 维 / 4304 FFN / 27 层 / 16 头 / projector_type minicpmv4_7),差别只在 clip.vision.projector.scale_factor。

⚠️ 注意:文件名和数值是反的。 叫 -4x 的文件 scale_factor 是 2,不带后缀的才是 4。别按字面推断。

本文用的是 -4x 那个(scale_factor 2,压缩更轻、保留细节更多)。

三个坑

坑一:llama.cpp 版本要够新

旧 build 加载视觉投影器直接失败:

复制代码
E mtmd_get_memory_usage: error: Failed to load CLIP model from ...\mmproj-model-f16-4x.gguf
E srv load_model: [mtmd] failed to get memory usage of mmproj

路径和文件都是好的。升级到 build 11617 后同一条命令一次通过。 llama.cpp 的 mtmd 模块改动很勤,旧 build 认不了新投影器格式是常态。版本号可以从进程路径直接看:D:\llamab11617\llama-server.exe。

坑二:别用 --load-mode mlock

第一次纯文字跑,命令带 --load-mode mlock,加载耗时 3 分 7 秒 。第二次多模态没带这条,33 秒。

需要说明:两次间隔一天,系统文件缓存状态不同,不能把六倍差距全算在 mlock 头上。但方向明确:mlock 要把 19.7GiB 全锁进物理内存,动作本身很慢。日志里框架自己也在提示:

复制代码
W llama_model_loader: tensor overrides to CPU are used with mmap enabled - consider using --load-mode none for better performance

日常折腾建议不加 mlock。

坑三:视频输入 llama.cpp 走不通

跑视频时报:

复制代码
Server Error
Unable to connect to server - please check if the server is running

看着像服务挂了,其实服务是活的,文本请求正常。这是 llama.cpp 的多模态接口只支持静态图片,不支持视频帧序列。 是框架限制,不是模型缺陷。想跑视频得换框架或走 Python 侧实现。

另有一个现象记录在案:日志反复出现 W find_slot: non-consecutive token position ... 警告,不影响结果,未查到权威解释,不做解读。

能力对照

跑了一套题(Python 逻辑 / 多步计算 / 化学 pH / 数学证明 / 自我介绍),由另一个模型按 10 分制逐题打分,口径为 AI 评分,仅作参考,非权威跑分:

|------------|-------------|-------------|
| 题 | 35B-A3B | 1B |
| 自我介绍 | 10 | 10 |
| Python 逻辑题 | 8 | 0 |
| 多步计算 | 10 | 2 |
| 化学 pH 计算 | 10 | 0 |
| 数学证明 | 7 | 2 |
| 合计 | 46 / 60 | 24 / 60 |

值得记的两笔:35B 的五步递推计算一步没错(终值 1296),草酸 pH 题给出正确值 2.7;1B 在 pH 题上错答 1.52,Python 题完全跑偏。

选型建议

选 35B-A3B :显存只有 8G 但内存有 32G 以上;要处理文档图表;能接受 36 token/s。 选 1B :要速度和并发;任务边界清晰(抽取、分类、格式化);显存紧张。 都不建议:指望它们做复杂数学推导或高质量工程代码。

小结

35B 多模态模型,19.7GiB 文件,8GB 显存老卡 + 64GB 内存能跑,35 token/s 上下,OCR 和结构识别可用。门槛确实塌了。

而它和在手机上跑用的是同一套思路:不需要把所有东西同时装进口袋,只要做到要用的时候能拿到。

更多信息可以关注同名GZH获取。

相关推荐
dyxal5 小时前
FireRedVAD 深度解析:小红书开源的工业级语音活动检测“小钢炮”
人工智能·开源·语音识别
加宝的起点雷达6 小时前
40 条候选里 38 条来自同一个源,主卡整屏重样
人工智能·算法·创业
紧跟先前的步伐6 小时前
Go AI Agent 实战 28|Agent 的预算、超时与停止条件
开发语言·人工智能·后端·ai·golang
蓝星科学6 小时前
AI Agent 说「已完成」,凭什么信——ChipCode 的证据链与产物门禁设计
人工智能
田里的水稻6 小时前
FA_CNN卷积神经网络二十六---从全连接到卷积PyTorch
人工智能·pytorch·cnn
艺杯羹6 小时前
MCP本地服务集成避坑:从Stdio管道僵死到双向JSON-RPC稳健通信
人工智能·python·ai·系统架构·大语言模型·ai编程·mcp
武子康6 小时前
h3.c 的两个权重槽,怎样把内存压力换成 SSD 等待
c语言·人工智能·agent
大模型真好玩6 小时前
豆包真人分身操作技巧:这次让我来做主演
人工智能·agent·deepseek
xyzzklk6 小时前
在Open-WebUI中提升向量化速度
网络·人工智能·爬虫·ai·语言模型·自然语言处理·安卓
QXWZ_IA6 小时前
矿山安全监测从感知到预警的全链路算法
人工智能·安全