最近AI圈又冒出一个高频词:近内存计算。很多朋友问我它到底是什么,是不是厂商造出来唬人的新概念。我自己的第一反应是——这个词其实很老,只是AI大模型把这股火彻底点着了。它的核心要解决的是:算力增长飞快,但数据搬运速度跟不上,导致大量计算单元闲置。这篇文章我从内存墙讲起,把它和存内计算的概念边界、主流的硬件落地形态、工程评估方法一次性说清楚。适合正在做大模型推理、推荐系统、向量数据库和相关基础设施的工程师参考。
1. 内存墙:近内存计算这门“黑话”出现的直接原因
1.1 算力增长快,带宽增长慢
先说一个很多人在做项目时才真正体会到的现实:GPU的算力每年都在大幅上涨,但内存带宽的涨幅要温和得多。以NVIDIA A100为例,FP16稠密算力大约是312 TFLOPS,HBM2e的带宽在1.5~2 TB/s左右。拿312除以2,得到155 FLOP/Byte左右的“算力带宽比”。这个数字意味着什么?如果某个算法平均每读取1字节数据只做不足155次浮点运算,它就会被带宽卡住,GPU空有一身算力使不出来。
训练大模型时之所以整体还算顺畅,是因为矩阵乘法这类核心运算的算术强度很高,一块数据读进来可以被反复重用,可以做到几百甚至上千FLOP/Byte,远高于155这个阈值。但推理阶段完全是另一番光景:逐token生成时,模型权重每个token都要被重新读取一遍。7B参数的fp16权重就约14GB,batch size等于1时,每生成一个token都相当于把14GB数据从头搬一遍。这种场景下,带宽决定延迟,算力只是陪跑。
掉进过这个坑的人应该都有同感:你以为瓶颈在显卡不够快,升级到更高算力卡后,单token延迟几乎没变。问题不在算力,在数据搬运。
1.2 Transformer推理暴露的不只是算力问题
大模型推理里还有一批运算的算术强度低得离谱,比如自注意力中的QK相似度计算、Softmax、KV cache的读取、以及对注意力权重的聚合操作。这些操作往往被笼统归入“访存密集”型负载。实际用profiler看,GPU的DRAM占用率经常打到90%以上,而CUDA Core利用率只有百分之二三十。此时机器的状态像是:几十个厨师在厨房里等着,但食材都在三公里外的仓库,来回搬货的小车成了瓶颈。
- QK^T和Softmax:需要读取整个注意力矩阵和相关向量,但每个元素的计算量非常小。
- KV cache读取:长上下文对话时,每个生成步骤都要把此前所有token的Key和Value重新读一遍,这个数据量随上下文长度线性增长。
- 多轮交互中的状态切换:AI Agent、多模型协作这类场景本身就喜欢保持大上下文,导致KV cache巨大,带宽压力进一步叠加。
也正是从这些真实需求出发,近内存计算才被推到台前。它试图回答一个很直接的问题:如果瓶颈是数据搬运,那我们把计算放进内存旁边,不让数据跑那么远,行不行?
1.3 一个简单的算术题决定你是否需要近内存计算
判断一套系统是不是带宽受限,不需要很复杂的手段。先估算负载的算术强度,也就是平均每字节数据搬运对应多少次浮点运算。然后对比设备的算力带宽比阈值。
- 算术强度 > 阈值:算力受限,优先优化的应该是计算密度、算子实现、数据复用。
- 算术强度 < 阈值:带宽受限,这时候花力气做数据压缩、算子融合、量化都是正路,如果这些软件手段还不够,硬件层面就要考虑近内存计算这类方案。
我做过不少次这种粗略评估,一张Excel表就够了。先把算子拆开,统计每个算子的FLOPs和访存字节数,再算总账。你往往会发现:真正拖后腿的就是那么少数几个个位数的算子。把这些算子单独拎出来处理,比全量迁移到新硬件快得多。
2. “近内存计算”到底近在哪,它和存内计算有什么边界
2.1 按数据放的位置来定义
近内存计算的英文是near-memory computing,字面意思就是“在内存附近计算”。这里的关键不是“计算有多强”,而是“计算离数据有多近”。传统冯·诺依曼结构里,数据要经过内存总线、缓存层次、寄存器,最后才进ALU。每一步都是延迟和功耗的开销。
业界常引用的一组数据是:一次DRAM访问消耗的能耗,大约等于几十到几百次32位加法运算的能耗。具体的数值会随工艺节点变化,但数量级的差距一直存在。换句话说,搬运数据本身可能就是整个系统最贵的操作。
近内存计算的思路,是把计算单元放到存储阵列的边缘或附近。数据从存储单元读出后,直接在旁边被处理,不需要通过片外总线绕一大圈。和它经常被混为一谈的“存内计算”(in-memory computing/computational memory)则更激进:逻辑直接嵌进存储单元内部,甚至利用存储单元的物理特性直接完成乘加运算。
2.2 近内存、存内计算与传统架构的关系
为了方便对比,我把三者的差异整理成了表格:
| 对比维度 | 传统冯·诺依曼 | 近内存计算 | 存内计算 |
|---|---|---|---|
| 计算单元位置 | 远离存储阵列(独立计算die) | 存储die旁/片内边缘 | 存储阵列内部 |
| 数据搬运距离 | 最远,需要走片外总线 | 短,片上或封装内完成 | 极短,基本不出存储阵列 |
| 代表产品/技术 | CPU、GPU计算核心 | HBM-PIM、PIM DIMM、2.5D封装的chiplet | ReRAM/SRAM阵列的乘加阵列 |
| 通用性 | 最强 | 中上,可支持通用算子但受限 | 较弱,偏向特定AI算子 |
| 工艺难度 | DRAM和逻辑工艺分离 | 中,逻辑少量嵌入存储die | 高,需对存储单元做逻辑改造 |
从这个表格能看出来,近内存计算其实是“妥协后更可工程化的路线”。它不要求把存储单元的物理结构改得面目全非,只需要在靠近存储的位置增加有限的计算资源。相比存内计算,它的优势是更容易兼容现有存储工艺、更容易编程,代价是数据还是要做一次较短的搬运。
2.3 为什么不能把存储器和计算器“粘在一起”了事
既然数据搬运这么贵,为什么不直接做成一个巨大的芯片,把存储和最强算力焊在一起?这个问题几乎所有第一次接触近内存计算的人都会问,我当时的反应也一样。
答案有三层。第一层是工艺冲突:DRAM工艺追求极高的电容密度和低成本,逻辑工艺追求晶体管速度和能效,二者在晶圆厂里是两套完全不同的流程。直接混在一起,良率、密度、功耗都会付出代价。第二层是散热和供电:存储芯片里塞入大规模计算单元后,局部功耗密度猛增,散热设计难做。第三层是成本:即便技术可行,大批量生产的良率和成本也会劝退大多数客户。
做AI芯片的都清楚一个朴素道理:好架构是“在物理约束下做取舍”,不是在理想世界里做最优解。近内存计算的价值恰恰在于它能在不颠覆存储工艺的前提下,把计算拉近到数据旁边,属于一种可落地的次优解。这个“次优”,在实践中往往已经足够优秀。
3. 一张路线图看近内存计算的几种落地形态
3.1 HBM-PIM:把计算单元放进高带宽内存的堆栈里
目前在AI服务器领域讨论最多的是HBM-PIM这种形态。HBM本身是多个DRAM die垂直堆叠,通过硅通孔(TSV)实现高带宽连接。在这类内存die内部靠近bank的位置塞进可以完成一定浮点/整数计算的单元,就是HBM-PIM的基本思路。
三星公开资料里展示过HBM-PIM的方向,官方给出的数据是在某些特定工作负载下能够实现约3倍的性能提升、约60%的功耗降低。注意这个数字是特定负载下的相对收益,不是所有程序都能拿到的。它擅长的是那些“数据量大但操作规律”的任务,比如向量加法、逐元素乘、大规模归约这类访存密集算子。如果你想在上面跑复杂的控制流逻辑,基本没戏。
实际应用中,HBM-PIM的编程方式更接近“把算子下推到内存设备执行”,和GPU的kernel launch有相似之处,但生态还远没有CUDA成熟。
3.2 带计算单元的DIMM:把计算推进到内存条附近
另一个已经商业化的方向是PIM DIMM,代表是UPMEM推出的产品。它把可编程的DPU(数据处理单元)做进了标准DDR4 DIMM上,服务器可以直接插这种内存条加装内存计算能力。它的优势在于兼容现有服务器基础设施,不需要换主板、换CPU。
这类产品的典型应用包括数据库扫描、图处理、压缩/解压、基因测序比对等数据密集型任务。它的编程模型和GPU差异很大,通常需要通过厂商提供的SDK把任务映射到DPU上。优点是内存就近处理,减少了主CPU的负载和互连压力;缺点是需要接受厂商的工具链和数据分配方式。
3.3 2.5D/3D封装与芯粒化:让内存和计算芯粒做邻居
还有一个容易被忽略的落地形态是芯片封装层面的:把计算die和存储die放进同一个封装里,通过interposer基板或TSV互联。这就是2.5D/3D封装技术。原本需要经过PCB走线、片外总线的数据通路,现在可以在封装内部完成,距离缩短一个数量级。
近年来比较火的一个相关词汇是芯粒(chiplet)和UCIe互连标准。UCIe本来是为了解决不同芯粒之间互联的问题,它也在把芯片系统的设计从“单颗大芯片”推向“封装内的小系统”。当计算芯粒和内存芯粒通过这种短距互连通信时,工程上就是近内存计算的思路。
我判断,未来相当一部分AI芯片都会走这条路线:不需要把所有逻辑都集成进存储die,而是通过先进封装让计算与存储靠得更近。这种形态牺牲了极致的数据路径距离,但换来了更好的可扩展性和成本灵活性。
3.4 CXL:它算不算近内存计算
不少朋友会问:CXL内存扩展是不是近内存计算?严格来说不算。CXL解决的是内存容量池化和缓存一致性扩展问题,它让远处的内存看起来离CPU/GPU更近,但物理上数据还是在外部走着长距离互联。它和近内存计算的目标不完全一样:一个是在解决“内存不够用”,一个是在解决“数据搬不动”。
不过二者有很强的互补关系。我在实际项目中见过混搭的做法:用CXL扩展大容量内存池给冷数据用,用贴近计算侧的持久内存或者HBM处理热数据。理解清楚这个边界,能避免在技术选型时把不同层次的问题混在一起。
4. 真正动手评估时,我关注的三个工程问题
4.1 数据局部性:好算子一选就赢,差算子救不回来
近内存计算的硬件再先进,如果数据访问模式不好,收益也会被吃掉。带宽数字是理论峰值,实际能拿到多少取决于访存局部性。比如向量加法这种操作,每个元素读一次、写一次,数据是线性流式访问,非常适合近内存执行。而如果你的算法里每个数据要被反复从存储读到计算单元旁边,但因为索引跳来跳去导致缓存命中率低,那计算单元的利用率上不去,最终还是会被访存延迟拖死。
我在评估一个算子是否适合迁移到近内存设备时,会先做一个简单步骤:把算法按数据访问方式画一遍。只要我发现数据呈现出明显的“读一次算一次”或“小窗口内反复重用”的特征,就会认真评估;如果发现是稀疏随机访问、大量间接寻址,我会直接放弃,因为这类负载需要的是大规模片上缓存和复杂乱序处理能力,而不是内存附近的简单计算单元。
4.2 数据一致性:算完的结果怎么回到主核
近内存计算设备执行完计算后,结果要回到主处理器的可见内存空间。这就牵出另一个经常被低估的问题:一致性。主核怎么知道PIM设备已经算完了?什么时候它读到的才是最终结果?不同厂商的解决方案差别很大,有的靠显式同步,有的靠缓存刷新指令,有的需要软件维护一个“设备状态标志”。
这个同步开销在性能模型里很容易被漏掉。以前我看过一份近内存计算的评测报告,单个kernel的加速比很漂亮,但一旦把任务切碎成几千个小kernel,每个kernel之间的同步次数一多,整体收益就被互连延迟吃掉了。所以经验法则是:尽量把数据划分成大块、把操作批量提交给近内存设备,减少主核与设备之间的“握手”次数。
4.3 编程模型和工具链:别低估生态成本
做实际工程的人都明白,一个硬件方案再强,编程体验跟不上就很难落地。近内存计算目前还没有一个像CUDA那样统一的编程标准。不同实现有各自的SDK,有的让你用C语言扩展,有的基于OpenCL风格,有的直接给你封装好的算子库。
我自己的建议是:如果只是想验证近内存计算对某个负载有没有收益,先别急着写custom算子。直接看供应商有没有现成的高性能算子库,用库函数跑一遍实测。发现收益明显再考虑深挖自定义算子;如果库函数都没有覆盖你的场景,那大概率意味着很多隐藏的坑需要你自己踩。这时候要做的是重新评估ROI,而不是硬着头皮上。
5. 什么负载值得用近内存计算:我的判据和实测心得
5.1 Roofline模型:一张图判断该不该做
我一直觉得,做性能工程的人应该把Roofline模型当常识。它的核心是一条斜面:横轴是算术强度,纵轴是可达性能。设备有一个“算力带宽比”阈值,超过这个阈值后性能受算力限制,低于这个阈值则受带宽限制。
把你要做的负载放到Roofline图上,一眼就能看出它在哪个区域。如果它落在带宽限制区,且距离阈值还有很大距离,意味着算力基本在睡觉,近内存计算的收益就有理论依据。如果它早就落在算力限制区,硬件已经接近跑满算力,那再上近内存计算也没有意义,因为瓶颈不在搬运。
以7B参数大模型推理为例,KV Cache读取和权重读取让整个推理流程的平均算术强度非常低,完全落在带宽限制区。这也是我在实际项目里最推荐尝试近内存计算的场景之一。
5.2 推荐做的负载与不建议碰的负载
基于上面这套理论框架,我把实践中的负载分成三类:
| 负载类型 | 典型例子 | 近内存计算的适用性 |
|---|---|---|
| 流式数据扫描/聚合 | 数据库扫描、embedding表聚合、批量向量范数计算 | 非常合适,数据线性访问,计算简单 |
| 低算术强度AI推理子任务 | 注意力矩阵的QK^T、Softmax、KV Cache读取归约 | 合适,能明显改善延迟和带宽占用 |
| 高逻辑复杂度/不规则访问 | 图算法中大量随机邻居遍历、稀疏动态分支 | 不合适,计算单元弱,同步开销高 |
注意一个容易误判的点:大模型训练里的GEMM并不适合近内存计算。虽然它访存量也很大,但矩阵乘法可以通过分块实现极高的数据复用,算术强度高于设备阈值,GPU上的Tensor Core才是它的最佳归宿。只有把推理中那些“低算术强度、带宽瓶颈”的算子剥离出来后,近内存计算才有明显的发挥空间。
5.3 如果打算做第一版验证,我的建议流程
如果你对近内存计算产生了兴趣,打算评估它是否适合你的业务,我给一个自己反复使用过的操作顺序:
- 先做Roofline估算,不急着碰硬件。用profiler(比如NVIDIA的ncu或者系统perf工具)采出你真实负载的DRAM吞吐量、计算利用率,确认瓶颈确实是带宽。
- 优化软件,把能做的先做了:算子融合、量化、缓存blocking、数据排布调整。很多人做到这一层就已经解决了大部分问题,根本不需要换硬件。
- 如果软件优化完成后,带宽仍然是瓶颈,并且负载满足“流式访问、低算术强度、可批量并行”的条件,再去评估近内存计算设备。
- 在评估设备时,优先跑真实负载,其次跑供应商benchmark。厂商的benchmark挑的都是最能发挥硬件特性的算子,和你的真实数据分布之间可能差着十万八千里。
- 最后对比总拥有成本:近内存设备带来的性能和能效提升,是否抵消了额外的开发、部署和运维复杂度。
这套流程看起来朴素,但能帮我砍掉至少一半“看起来很美好”的方案。工程选型最怕的是被单点数字打动,忘了自己是在跟整个系统一起工作。
6. 关于近内存计算,我想说点UI设计之外的真话
最后再聊几句个人经验。我在前面多次提到“别被宣传数字骗了”,这不是客套话。近内存计算确实解决了真实问题,但它不是万能药。它本质上适合的是“搬运量极大但每个数据操作非常简单”的场景,比如推荐系统里的特征聚合、大模型推理里的attention和KV cache访问、数据库里的批量扫描。它不适合的场景也比比皆是,强行迁移只会徒增复杂度。
我的实操体会是:真正从近内存计算吃到红利的团队,都是先把系统拆得很清楚,把带宽瓶颈算得很明白的人。他们不会因为“AI黑话”而追热点,而是因为看清楚了计算模型和硬件物理限制的匹配关系才行动。如果你连自己负载的算术强度都说不清,我建议先别急着研究近内存计算,老老实实开一次profiler,看看数据到底是怎么流进流出处理器的。
另外一个非常有用的技巧:在混合负载里,把带宽受限的算子单独剥离出来评估,不要试图把整个应用都迁到近内存设备上。一次只优化一个瓶颈,收益会清晰得多。用真实业务数据测试,别用均匀随机数据,因为随机数据会高估缓存的作用,低估内存带宽压力。
关于近内存计算的讨论,短期内肯定还会继续升温。我个人的判断是,它不会替代GPU、CPU,而是成为数据密集型场景里的一张新牌。牌得打对地方,才能赢。