在本地跑大模型时,很多人会先看算力:CPU是几核,GPU有多少 TOPS。结果真正跑起来却发现,设备明明算力不差,生成速度却始终提不上去。这个现象背后的关键瓶颈,往往不是计算单元,而是内存带宽。最近讨论度很高的 Xiaomi AI Cube 就是一款把“近内存带宽”做到 1.22 TB/s 的本地 LLM 硬件方案。本文不打算只堆参数,而是从内存带宽与 LLM 推理的关系出发,拆解这个指标意味着什么,并给出在高带宽设备上部署、测试本地大模型的一套可复用思路。
1. 背景与核心概念
1.1 LLM 推理的访存瓶颈
大语言模型(Large Language Model,LLM)的推理过程本质上由两大部分组成:Prefill 和 Decode。Prefill 阶段负责处理用户输入的 Prompt,一次性生成第一轮计算的 KV Cache;Decode 阶段则逐个生成 Token,是用户在对话界面中等待得最久的部分。
很多开发者在刚接触 LLM 推理优化时,会把注意力放在“每秒多少 FLOPs”上。但在实际部署中,LLM 推理尤其是单用户交互场景里的 Decode 过程,往往是一个访存密集型任务。每一次生成一个新的 Token,都需要把模型权重从头到尾读一遍。也就是说,模型越大,生成单个 Token 需要搬移的数据量就越大。
这里可以用一个简单的估算来帮助理解:
- 一个 7B 参数的模型,以 FP16 精度存储,权重大小约为 14GB。
- 每生成 1 个 Token,理想情况下至少需要从内存中读取全部权重。
- 如果内存带宽只有 100GB/s,那么生成 1 个 Token 的最短耗时也在 140ms 左右,换算下来只有 7 tokens/s。
- 如果把内存带宽提升到 1TB/s 级别,生成 1 个 Token 的访存耗时可以降到 14ms 左右,对应约 70 tokens/s。
这个对比清楚说明了一个结论:在本地 LLM 场景中,带宽往往比纯算力更早成为天花板。很多 CPU 平台的算力并非不够,而是权重数据“喂”不过去,导致计算单元一直在等待。
1.2 什么是近内存带宽
近内存带宽(Near-Memory Bandwidth)并不是一个全新的概念,它脱胎于近内存计算(Near-Memory Computing)思想。传统计算机的内存带宽,指的是内存控制器与内存颗粒之间、或者内存条与 CPU/GPU 之间的数据传输速率。数据需要在 DRAM、缓存、计算单元之间来回搬运,物理链路越长,延迟越高,带宽越容易受限。
近内存计算把计算单元物理上做得更靠近内存,甚至把部分计算逻辑放进存储控制器的附近,从而大幅缩短数据搬运路径。这样做的好处有三个:
- 降低访存延迟。
- 提升单位功耗下的数据吞吐能力。
- 避免传统外部总线接口成为性能瓶颈。
Xiaomi AI Cube 提到的 1.22 TB/s 近内存带宽,翻译成更直观的说法就是:计算单元和存储之间最核心的数据通道,峰值可以达到每秒 1.22 太字节级别。这个量级通常已经远超普通 PC 的 DDR4/DDR5 内存带宽,也比很多入门级独立显卡的显存带宽更高。
需要注意的是,近内存带宽与常见的“显存带宽”“系统内存带宽”并不完全等同。它们之间的区别可以简单理解成不同位置的数据通路:
| 带宽类型 | 常见位置 | 典型量级 | 主要用途 |
|---|---|---|---|
| 系统内存带宽 | CPU 与 DDR 内存之间 | 几十 GB/s 到上百 GB/s | 常规程序运行、文件缓存 |
| 显存带宽 | GPU 与显存之间 | 数百 GB/s 到 TB/s 级别 | 图形渲染、AI 训练、模型推理 |
| 近内存带宽 | 计算单元与近邻存储之间 | 数百 GB/s 到 TB/s 级别 | 边缘 AI 推理、端侧 LLM、存算优化 |
从这张表可以看到,1.22 TB/s 本身是很有竞争力的数字,但它是不是能在真实业务中完全发挥出来,还要看软件栈、访存模式和数据容量是否匹配。
1.3 Xiaomi AI Cube 是什么
根据现有公开信息,Xiaomi AI Cube 是一款面向本地 LLM 推理场景的 AI 计算设备。它的核心定位不是“跑分最高”,而是把大模型部署到普通用户可以接触到的本地环境中,让数据不必上传到云端也能完成高质量对话、代码生成和知识问答。
从产品命名和宣传点来看,AI Cube 强调“Local LLMs”和“Near-Memory Bandwidth”,说明它重点解决的是端侧部署大模型时的两个现实问题:
- 内存容量能不能把模型放进去。
- 内存带宽能不能把模型权重及时“喂”给计算单元。
目前官方并没有把完整的芯片架构、内存颗粒型号和软件 SDK 全部公开,因此本文不会去猜测具体的硬件设计。但我们可以把 1.22 TB/s 当成一个近期值得关注的硬件指标,围绕它展开原理分析和部署实践。
2. 硬件指标解读:1.22 TB/s 意味着什么
2.1 数字换算与实际体验
先来做单位换算。计算机行业经常出现 TB 和 TiB 混用的问题:
- 1 TB/s = 1000 GB/s,这是十进制换算。
- 1 TiB/s = 1024 GiB/s,这是二进制换算。
如果厂商按十进制标注,1.22 TB/s 等于 1220 GB/s;如果是二进制标准,则约等于 1249 GB/s。大多数消费级产品的标称带宽习惯使用十进制,所以我们在估算时可以按 1220GB/s 处理。
把这个带宽代入前面的 7B FP16 模型例子中:
- 权重 14GB。
- 读取耗时理想值:14GB ÷ 1220GB/s ≈ 11.5ms。
- 每秒最多可以完成约 87 次全量权重读取,也就是理论极限约 87 tokens/s。
在实际运行中,Decode 阶段还需要读取 KV Cache,同时计算单元也不可能把全部时间都花在内存读取上,所以实际流畅速度通常要打折扣。但即便只有理论值的 60% 到 70%,也能做到每秒 50 到 60 个 Token。对于本地对话、文档摘要、代码补全这类场景,这个速度已经足够日常使用。
下面这个 Python 脚本可以帮你快速做带宽到 token 速度的换算:
# 文件路径:scripts/estimate_bandwidth.py def estimate_tokens_per_second( model_size_b: float, bits_per_weight: int = 16, bandwidth_gbps: float = 1220.0, ): """ 根据模型大小、量化精度和带宽估算理论解码速度。 参数说明: model_size_b : 模型参数数量,单位是 B(10 亿)。 bits_per_weight : 每个权重占用的 bit 数。FP16 为 16,INT8 为 8,INT4 为 4。 bandwidth_gbps : 内存带宽,单位是 GB/s。 """ weight_bytes = model_size_b * 1e9 * (bits_per_weight / 8) time_per_token_ms = weight_bytes / bandwidth_gbps * 1000 tokens_per_second = 1000 / time_per_token_ms return weight_bytes, time_per_token_ms, tokens_per_second if __name__ == "__main__": for bits in (16, 8, 4): total_bytes, time_ms, tps = estimate_tokens_per_second(7, bits, 1220) print(f"bits={bits:>2} 权重={total_bytes / 1e9:.2f}GB 理论耗时={time_ms:.2f}ms token/s={tps:.1f}")运行结果会显示,量化确实能把权重体积和访存时间压到很低的水平。这也是为什么本地 LLM 方案普遍推荐使用 4bit 量化模型。
2.2 与常见平台的带宽对比
为了更直观地感受 1.22 TB/s 的定位,可以把它和开发者在 PC 上经常使用的平台做对比:
| 平台类型 | 典型内存带宽 | 对 7B FP16 模型的单 Token 理论读取耗时 |
|---|---|---|
| 普通 DDR4 PC | 约 30-50GB/s | 280-470ms |
| DDR5 PC | 约 60-80GB/s | 175-233ms |
| 高端游戏显卡 | 约 600-1000GB/s | 14-23ms |
| AI Cube 近内存带宽 | 约 1220GB/s | 约 11.5ms |
需要说明的是,上面的游戏显卡数据是显存带宽,不是 CPU 内存带宽。如果你的模型权重保存在系统内存中,那么即使显卡本身带宽很高,也会受到 PCIe 或统一内存接口的限制。
小米 AI Cube 的 1.22 TB/s 如果能在实际软件栈中稳定发挥,它的单 Token 权重读取速度会非常接近中高端独立显卡的显存读取速度。对于不能使用显卡、或者希望控制功耗和体积的边缘设备来说,这是一个很有参考意义的路线。
2.3 带宽与可运行模型规模的关系
带宽决定的是模型运行速度,容量决定的是能不能运行模型。因此带宽再高,也需要匹配足够的内存空间。
以常见量化精度为参考,不同参数规模的模型体积大致如下:
| 模型规模 | FP16 | INT8 | INT4 |
|---|---|---|---|
| 7B | 约 14GB | 约 7GB | 约 4GB |
| 13B | 约 26GB | 约 13GB | 约 7GB |
| 33B | 约 66GB | 约 33GB | 约 18GB |
| 70B | 约 140GB | 约 70GB | 约 40GB |
如果一台设备只有 16GB 可用内存,那么跑 FP16 的 7B 模型已经比较吃力,跑 INT4 的 13B 模型则相对合适。若设备内存能够达到 32GB 以上,INT4 的 33B 模型也可以放到本地推理。
这里还要提醒一点:模型权重之外,上下文窗口和 KV Cache 也会占用额外内存。上下文越长,KV Cache 占用越大。所以“内存容量刚好能装下权重”并不等于能正常跑长文本。
3. 本地 LLM 部署的核心原理
3.1 Prefill 与 Decode 的差异
部署过模型的人都知道,第一次提问时等待时间往往很长,但后续回复却是逐字出现。这个现象背后的原因就是 Prefill 和 Decode 的计算特征不同。
Prefill 阶段要处理整个 Prompt,属于计算密集任务。它需要把输入文本的所有 Token 并行带入模型计算,因此算力越强,首 Token 延迟越低。
Decode 阶段是逐 Token 生成,每一步只能计算一个 Token,这个过程很难完全并行化,而且每一步都要重新读取全量权重。即使算力再强,如果内存带宽不够,每一步都会被卡在访存上。
在交互式对话场景中,用户对首 Token 延迟和后续 Token 速度都很敏感。一个典型的本地 LLM 硬件方案如果想要体验流畅,至少要在 Decode 阶段提供足够的带宽。这也是为什么 1.22 TB/s 近内存带宽会比单纯宣传 TOPS 更有说服力。
3.2 量化如何影响带宽需求
权重精度越低,单个权重占用的字节数越少,读取同样参数所需的总数据量就越小。假设一个 7B 模型:
- FP16:每个权重 2 字节,总权重约 14GB。
- INT8:每个权重 1 字节,总权重约 7GB。
- INT4:每个权重 0.5 字节,总权重约 3.5GB 到 4GB。
这意味着在相同带宽下,使用 INT4 模型可以把读取权重的时间缩短到 FP16 的四分之一。用 1220GB/s 带宽计算,FP16 7B 模型理论约为 87 tokens/s,INT4 7B 模型理论上可以冲到 300 tokens/s 以上,虽然实际还会受其他因素限制,但量化带来的收益非常明显。
不过量化也不是越低越好。INT4 可能导致模型精度下降,在复杂推理、数学计算、非中文场景下更容易出现错误。工程上需要根据业务场景在速度和效果之间取平衡。通常在通用对话场景中,Q4_K_M、Q5_K_M 这类量化格式是比较稳妥的选择。
3.3 KV Cache 的隐藏成本
KV Cache 是 LLM 推理中另一个容易被忽视的访存项。它用来保存已处理 Token 的 Key 和 Value 向量,避免每一步重新计算历史信息。
KV Cache 的大小取决于模型层数、注意力头数、隐藏层维度和上下文长度。以 7B 级别模型为例,在 4096 上下文长度下,KV Cache 可能占用几百 MB 到 1GB 以上。如果上下文长度扩展到 32K 甚至 128K,KV Cache 会成倍增长。
KV Cache 对带宽的影响是:Token 生成越多,历史信息越长,每一步需要读取和写入的 KV Cache 就越大。再加上全量模型权重复读取,高带宽设备的优势会被长期对话场景进一步放大。反过来,如果内存带宽不足,长上下文对话的生成速度会随着对话变长而明显下降。
4. 实战:面向高带宽设备的本地 LLM 部署思路
4.1 创建项目结构
虽然 Xiaomi AI Cube 的完整 SDK 还没有大规模开放,但高带宽本地推理设备在软件层面通常可以沿用当前主流的大模型推理栈。下面我们使用 llama.cpp 生态作为示例,演示一套通用的部署和基准测试流程。
先创建一个干净的项目目录:
mkdir -p local-llm/models mkdir -p local-llm/scripts cd local-llm项目结构建议如下:
local-llm/ ├── models/ │ └── qwen2-7b-instruct-q4_k_m.gguf ├── scripts/ │ ├── estimate_bandwidth.py │ ├── run_llama_cpp.py │ └── benchmark_decode.py └── README.mdmodels目录存放 GGUF 格式的量化模型文件,scripts目录存放加载和测试脚本。这里的模型示例选用常见的 Qwen2 7B Instruct,实际部署时可以根据设备内存容量换成其他模型。
4.2 安装依赖与编译推理引擎
llama.cpp 是一个支持 GGUF 模型格式的轻量推理项目,也是本地 LLM 部署中非常常见的方案。它既可以用官方预编译二进制,也可以从源码编译。
最简单的安装方式是通过 Python 的llama-cpp-python包:
pip install llama-cpp-python如果设备是 ARM 架构或需要针对特定指令集优化,推荐先从源码编译:
git clone https://github.com/ggerganov/llama.cpp.git cd llama.cpp make -j4编译完成后,可以先用内置的帮助命令确认版本:
./llama-cli --help | head -n 20在这类设备上运行时,需要关注编译参数是否启用了当前平台支持的向量扩展。如果软件栈还未适配某款新芯片,可以先关闭硬件加速运行,让推理引擎以内存带宽友好的方式执行,再逐步开启优化开关。
4.3 加载模型并预热
使用llama-cpp-python加载模型时,最关键的两个参数是model_path和n_gpu_layers。在普通 CPU 设备上,n_gpu_layers可以设置为 0;如果设备提供 GPU 或 NPU 后端,则可以根据支持情况传入-1表示尽量将层加载到加速器。
下面是一段加载模型并进行简单对话的代码:
# 文件路径:scripts/run_llama_cpp.py from llama_cpp import Llama llm = Llama( model_path="models/qwen2-7b-instruct-q4_k_m.gguf", n_ctx=2048, n_gpu_layers=-1, ) output = llm( "请用一句话介绍内存带宽对自然语言处理的影响。", max_tokens=128, temperature=0.7, echo=False, ) print(output["choices"][0]["text"])这段代码的作用是把模型权重载入内存,并在推理时生成一段简短回复。n_ctx=2048表示上下文窗口为 2048 Token,如果你需要使用长文档摘要,可以适当调大,但要留意 KV Cache 对内存容量的占用。
模型加载完成后,第一次推理通常会有预热成本,比如 KV Cache 初始化、内存页分配、线程池启动等。所以正式跑性能测试之前,最好先执行一次短输出,排除初始化阶段的影响。
4.4 编写解码性能测试脚本
性能测试的重点放在 Decode 阶段。最简单的方式是固定输入 Prompt,让模型连续生成 256 个 Token,然后统计总耗时。
# 文件路径:scripts/benchmark_decode.py import time from llama_cpp import Llama llm = Llama( model_path="models/qwen2-7b-instruct-q4_k_m.gguf", n_ctx=2048, n_gpu_layers=-1, ) prompt = "请列举内存带宽在大模型推理中的重要性:" # 预热 llm(prompt, max_tokens=16) start = time.perf_counter() output = llm(prompt, max_tokens=256) elapsed = time.perf_counter() - start generated_text = output["choices"][0]["text"] token_count = len(output["choices"][0]["text"]) print(f"生成耗时: {elapsed:.2f} 秒") print(f"输出文本长度: {token_count} 字符") print(f"平均速度(字符/秒): {token_count / elapsed:.2f}")这里的“字符数/秒”并不是严格意义上的 tokens/s,因为中文字符和 Token 并不完全等同。更精确的测试可以直接读取 llama.cpp 返回的 usage 字段,其中会包含completion_tokens和total_tokens。
如果需要命令行级别的权威测试,可以运行 llama.cpp 自带的 benchmark。在源码目录下执行:
./llama-bench -m ../local-llm/models/qwen2-7b-instruct-q4_k_m.gguf -p 64 -n 256其中-p 64表示使用 64 Token 的输入,-n 256表示生成 256 Token。llama-bench 会分别输出 Prompt 处理和生成阶段的数据,是排查性能瓶颈的实用工具。
4.5 结果解读与瓶颈定位
拿到测试结果后,不要只看一个综合速度,要分别看:
- Prefill 阶段 Token/s:反映算力上限。
- Decode 阶段 Token/s:反映内存带宽和访存优化水平。
- 平均内存占用:判断是否接近容量上限。
如果在高带宽设备上 Decode 速度依然很低,优先检查是否启用了正确的加速后端,以及模型是否存放在高带宽内存区域。很多设备会同时存在普通内存和近内存,如果模型被加载到慢速内存,即使硬件标称带宽再高也无法体现。
还可以用perf或/proc/meminfo观察内存带宽压力:
perf stat -e cache-misses,instructions ./llama-cli -m models/qwen2-7b-instruct-q4_k_m.gguf -p "测试" -n 64需要注意的是,perf在不同平台上支持的事件名可能不同,嵌入式设备上可能需要换成 vendor 私有的 profiling 工具。性能测试最重要的原则是:先确认数据确实在目标存储区域,再讨论带宽利用率。
5. 常见误区与排查思路
5.1 常见误区
| 误区 | 实际情况 |
|---|---|
| 1.22 TB/s 等于外接接口带宽 | 这是近内存带宽,不一定是 PCIe/USB 等外部接口带宽 |
| 内存带宽高就能运行任意大模型 | 还要看内存容量、量化格式、上下文长度 |
| 带宽越高,Prefill 一定越快 | Prefill 更依赖算力,带宽主要影响 Decode |
| 量化会让模型完全不能商用 | 4bit 量化在多数通用任务中效果好,但需要针对场景验证 |
| 峰值带宽等于实际带宽 | 实际访存可能无法打满峰值,特别是小模型逐 Token 推理时 |
5.2 带宽够高但生成慢的排查清单
如果遇到“设备带宽很高,但跑模型速度不理想”的情况,可以按下面顺序排查:
第一步,检查模型是否真的被加载到高带宽内存区域。对于近内存计算设备来说,数据摆放位置可能决定了性能数量级。
第二步,检查是否开启了硬件加速。部分推理框架默认只使用 CPU,或者没有识别到新增的 AI 算子。
第三步,检查上下文长度。如果n_ctx设置得非常大,KV Cache 可能占用了大量带宽和内存,导致有效带宽下降。
第四步,检查推理框架版本。新芯片通常需要配合新版本的编译器和内核模块,旧版本可能无法利用指令集或内存控制器特性。
第五步,检查是否统计了完整的端到端耗时。用户点击按钮到看到第一个字的时间,包含模型加载、Prompt 处理、网络传输等多个环节,不能全部归罪于 Decode 速度。
5.3 实际部署中的常见问题
| 问题现象 | 常见原因 | 解决思路 |
|---|---|---|
| 设备内存足够但 OOM | 上下文过长导致 KV Cache 膨胀 | 调低 n_ctx,或使用更强量化 |
| 模型总是输出乱码 | 量化格式不兼容或采样参数异常 | 检查 GGUF 元数据,重置 sampler 参数 |
| 生成速度越来越慢 | 对话历史太长,KV Cache 持续增长 | 使用摘要裁剪历史,或限制最大长对话轮数 |
| 设备发热严重 | 未做频率控制,持续满载推理 | 开启功耗限制,选择更小模型 |
| 多个用户同时访问卡顿 | 推理进程串行排队 | 引入动态批处理或服务化框架 |
6. 最佳实践与工程建议
6.1 模型大小和量化格式的选择
在高带宽但容量有限的设备上,最优策略是“用 4bit 量化保持模型规模,用上下文管理控制 KV Cache”。日常对话场景中,7B 到 14B 级别的量化模型是性价比最高的区间。需要处理复杂代码或者更强数学能力时,可以直接测试 32B 以上模型,但要为内存容量留出余量。
量化格式的选择可以参考一个简单原则:先跑通 Q4_K_M,再根据效果逐步升级到 Q5_K_M 或 Q8_0。不要在刚开始部署时追求极端低比特,因为这会给后续排错增加复杂度。
6.2 日志和可观测性
生产环境使用本地 LLM 时,一定要记录模型版本、推理框架版本、Prompt 长度、Token 耗时和错误信息。建议每次更新模型后跑一遍标准测试集,生成一份基线报告。
日志同时要注意隐私边界。本地 LLM 虽然把数据留在了设备上,但日志中如果包含用户输入原文,依然可能造成敏感信息泄露。在多人使用或企业内网部署时,建议对日志中的 Prompt 做脱敏处理。
6.3 权限控制和最小化原则
如果 AI Cube 被部署成局域网内可访问的服务,需要设置身份认证和访问控制,避免任意进程加载模型或修改配置。不要直接使用默认端口和管理密码,也不要给推理服务分配不必要的系统权限。
涉及模型文件替换、系统固件升级等操作时,先备份原有权重和配置,在测试环境验证后再更新。模型文件往往有几个 GB 到几十 GB,备份策略要考虑磁盘占用,建议保留最近两个可用版本,方便快速回滚。
6.4 性能优化参考方向
部署完第一版后,可以从三个方向继续优化:
- 动态批处理:把多个并发请求拼成一个 Batch,提高整体吞吐,适合服务化场景。
- 投机采样:用小模型先生成候选 Token,再用大模型验证,降低延迟。
- 上下文压缩:对长文档做分段检索或摘要,减少 KV Cache 压力。
这些优化方向并不是互相排斥的,但它们对软件栈的要求更高,需要等设备 SDK 和推理框架适配完成后逐步引入。
7. 总结与后续关注
Xiaomi AI Cube 的 1.22 TB/s 近内存带宽,让本地 LLM 推理又多了一种值得参考的硬件路线。通过本文的拆解可以明确一个关键认知:大模型生成 Token 的瓶颈是内存带宽,而不是单纯的算力数字。高带宽设备如果配合量化模型和合理的上下文管理,完全可以在本地实现流畅的对话体验。
拿到真实设备或 SDK 之后,建议按下面的顺序做验证:
- 先跑
llama-bench,确认 Decode 阶段的基础带宽表现。 - 再跑一个标准测试集,评估不同量化模型的效果和速度。
- 最后做长上下文测试,观察 KV Cache 增长对生成速度的影响。
如果只是停留在纸面参数上,1.22 TB/s 只是一个好看的数字;只有把它放进真实推理链路里测试,才能确定它到底适合哪些模型、哪些场景。这也是本地 LLM 硬件选型中最值得投入时间的地方。