清晨六点,晨曦社区团购仓库的灯准时亮起。一辆大货车停在门口,运来了一车新鲜的蔬菜——西红柿、黄瓜、土豆……这就是“输入向量”,每种蔬菜的数量都不相同。仓库里住着160户人家,每户都有一张订单表,上面写着他们各自需要多少斤每种蔬菜——这张订单表就是“矩阵”。分拣员们要做的,是在最短时间内算出每家每户总共该拿到多少斤菜:把订单表上一行行的数字,和货车上对应的蔬菜数量相乘,最后累加成一个总数。这就是矩阵向量乘(Matrix-Vector Multiplication,MVM),也是整座仓库每天最核心的运算。 有趣的是,真正高效的“分拣”方式并不是请一群分拣员拿着计算器逐家逐户地算,而是把整个订单表直接印在传送带的分拣口上——货物经过时,每个分拣口自动按订单份量拨出相应蔬菜,流到各家的篮子里自然称重汇总。电流在芯片阵列中的流动,正如蔬菜在传送带上的汇聚,在一瞬间同时计算完所有家庭的账目。这就是存内计算掀开矩阵向量乘的方式:让物理规律替你算数,而不是用逻辑门一步步地加。

岗位关联

对于AI从业者,理解MVM在存内阵列上的实现原理,是设计高性能、低功耗AI芯片的基石,也是评估存算一体架构在真实推理场景中落地的核心能力。

目录
  1. 可视化演示
  2. MVM运算基础
  3. 电流累加原理
  4. 权重映射策略
  5. 并行规模设计
  6. 负权重处理
  7. 偏置项实现
  8. 性能对比分析
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

展示忆阻交叉阵列MVM电流累加原理、IR压降对精度影响及差分对负权重处理机制的完整流程。

本节配有交互动效(进入视口后自动加载,约 3KB)。

交叉阵列MVM电流累加 输入电压V 输出电流I Ij=Σ(Vi×Gij) 基尔霍夫电流定律实现一步完成矩阵向量乘

MVM运算基础

晨曦社区的仓库里,每家每户都有一张订单表。李阿姨家那一行写着:西红柿2斤、黄瓜0.5斤、土豆1斤;王叔叔家写着:西红柿1斤、黄瓜2斤、土豆0斤。这张订单表有160行、3列,就是一个典型的矩阵。货车运来的三种蔬菜数量(西红柿30斤、黄瓜20斤、土豆40斤)就是一个向量。所谓矩阵向量乘,就是把每个家庭那一行订单,逐栏与蔬菜数量相乘,再累加,得出这个家庭今天该拿几斤菜。这个“乘加累加”的操作,在AI计算里无处不在——神经网络每一层都重复着这个模式。

为什么说矩阵向量乘是AI的原子操作?因为无论是图像识别、语音理解还是大语言模型,神经网络的计算核心都可以拆解成一层层的矩阵向量乘。一次完整的前向推理,往往要执行几十次甚至上百次MVM。如果每次MVM都慢、都耗电,整个AI应用就会变得不可用。这正是存内计算要攻克的问题:让MVM以极低的能耗在极短时间内完成。

在存内计算阵列中,订单表被“印刷”在一张物理网格上——矩阵的行对应字线,列对应位线,每个交叉点是一个可编程的存储器件(SRAM单元或RRAM器件)。输入向量以电压形式施加在字线上,权重以器件状态存储在交叉点,输出电流在位线上自然汇聚。整个结构像一条条横向的货架通道与纵向的传送带走廊交织在一起,货物沿通道流动,在交错处被自动分拣到对应的走廊。

订单表的每一行与货车蔬菜数量的组合,就这样被压缩成了一个数字——一个家庭的今日收货量。这个计算模式,将在存内阵列中借助物理定律被重新演绎,获得远超数字电路的效率。

yi=∑j=1nWij⋅xj\displaystyle y_{i} = \sum_{j=1}^{n} W_{ij} \cdot x_{j}
这条公式的意思很直白:输出向量的第 i 个元素,等于权重矩阵第 i 行的每个元素,逐一与输入向量的对应元素相乘后求和。
  1. 输出分量 y_i表示第 i 个输出元素,对应订单表中第 i 户家庭今天应收到的蔬菜总斤数。
    yiy_{i}
  2. 权重矩阵元素 W_ij表示第 i 户家庭对第 j 种蔬菜的预订斤数,即订单表第 i 行第 j 列的数值。
    WijW_{ij}
  3. 输入向量分量 x_j表示货车运来的第 j 种蔬菜的总数量。
    xjx_{j}
  4. 累加求和 Σ从第 1 种蔬菜到第 n 种蔬菜,把每一栏的“预订斤数 × 运来数量”乘积全部加在一起。
    ∑j=1n\displaystyle \sum_{j=1}^{n}

电流累加原理

仓库的分拣员发现,与其人工逐户计算,不如设计一套自动分拣系统:每条通道的入口装一个可调节的分拣阀门,阀门的开度对应订单表上的斤数;蔬菜在通道上匀速前进时,经过阀门就被分流出一部分到对应的传送带。当所有蔬菜都经过后,每条传送带尽头的小篮子里自然积累了该户应得的蔬菜——这就是电流版MVM的图景。

在存内计算阵列中,这个“自动分拣”由两个物理学定律联手上演。第一个是欧姆定律:通过一个器件的电流等于其电导乘以两端电压(I = G × V)。在这里,输入向量的每个分量被转换为字线上的电压 V,权重的数值被映射为交叉点器件的电导 G,“乘法”就这样在物理层面瞬间完成——电流大小就是乘积的模拟表现。第二个是基尔霍夫电流定律:汇聚到同一条位线上的电流自动相加,如同多条传送带在一端汇入同一个小篮。于是“累加”也无需额外逻辑门,它从物理本质上就发生了。

每条位线末端连接一个读出放大器,将汇聚的电流转换为数字信号。由于所有字线同时施加电压,所有交叉点同时产生电流贡献,整次矩阵向量乘在一个模拟步骤内完成,而不是像数字电路那样逐行扫描计算。这意味着阵列的并行度直接等于交叉点的数量——一次MVM的全部乘加操作在阵列中同时发生。

电流的汇聚是瞬间的,如同几十条传送带同时往一个小篮子里倾泻蔬菜,篮子重量自然累加。这就是存内计算的魔力:把需要上千个时钟周期的矩阵运算,压缩为一次电荷重分布。欧姆定律做了乘法,基尔霍夫定律做了加法,两者加起来就是一次完整的MVM。

Ii=∑j=1mGij⋅Vj\displaystyle I_{i} = \sum_{j=1}^{m} G_{ij} \cdot V_{j}
位线 i 上的总电流,等于矩阵第 i 列所有交叉点的电导,分别乘以对应字线电压后的总和。
  1. 位线输出电流 I_i第 i 位线上汇聚的总电流,模拟了输出向量第 i 个元素的值。
    IiI_{i}
  2. 交叉点电导 G_ij第 j 条字线与第 i 条位线交叉处的器件电导,代表权重矩阵中对应的权重值。
    GijG_{ij}
  3. 字线驱动电压 V_j第 j 条字线上施加的电压,对应输入向量第 j 个分量的值。
    VjV_{j}
  4. 求和累加所有 j 从 1 到 m 的电流贡献在同一根位线上自然叠加,没有额外的加法器时钟周期消耗。
    ∑j=1m\displaystyle \sum_{j=1}^{m}

权重映射策略

订单表上的数字是抽象的“斤数”,要让它真实作用在分拣系统上,必须翻译成阀门的开度大小。这个翻译过程就是权重映射。在RRAM阵列中,权重通常被映射为交叉点器件的电导值:器件被编程为某个电阻状态,对应一个电导。电导的范围不是无限的——一个RRAM器件的电导通常在1微西门子(µS)到100微西门子之间可调,相当于阀门只能在“几乎关闭”到“全开”之间连续调节。

映射的核心策略是线性缩放。系统先找出权重矩阵中绝对值最大的权重 W_max,把它映射为器件的最大电导 G_max,其余的权重按比例线性映射。这好比订单表上把“最多的一户订了10斤”定为阀门全开的基准,“5斤”就是半开。对于SRAM存内计算,权重则通常以多位数字形式存储在单元中,通过不同数量的导通单元来模拟模拟量。无论是RRAM的连续电导还是SRAM的多位组合,本质都是把数字权重转换为可在物理上产生作用的模拟量。

映射精度直接决定了计算精度。电导的量化步长越细(比如从1µS量化到0.1µS),权重表达越精确,但器件编程的难度和成本也上升。此外,RRAM电导在反复读写后可能发生漂移,导致映射的权重偏离原始值——就像阀门用久了开度会不太准确。实际芯片设计中需要在映射精度、器件可靠性和面积开销之间找平衡。

订单表上不同的斤数变成了阀门的开度,一斤不多、一两不少。但这份“翻译”并非完美——阀门精度有限、会老化,映射只能做到近似。设计者在映射精度和实现成本之间做出的取舍,将直接决定最终计算结果的准确程度。

Gij=∣Wij∣Wmax⁡×Gmax⁡\displaystyle G_{ij} = \frac{|W_{ij}|}{W_{\max}} \times G_{\max}
权重绝对值与全局最大权重的比例,乘以器件最大电导,得出该权重对应的电导映射值。
  1. 权重绝对值 |W_ij|取权重的大小值,因为电导不能为负,负权重需要另作处理。
    ∣Wij∣|W_{ij}|
  2. 全局最大权重 W_max整个权重矩阵中绝对值最大的那个权重,作为比例基准。
    Wmax⁡W_{\max}
  3. 器件最大电导 G_max存储器件可编程的最大电导值,对应权重映射的上限。
    Gmax⁡G_{\max}
  4. 比例缩放权重在矩阵中的相对大小,被线性映射到电导的相对大小。
    ∣Wij∣Wmax⁡×Gmax⁡\frac{|W_{ij}|}{W_{\max}} \times G_{\max}

并行规模设计

仓库管理者要考虑一个现实问题:分拣系统应该建多大?如果只建一条通道,一次只能处理一种蔬菜,效率太低;如果建100条通道,虽然所有蔬菜同时分拣,但仓库面积和造价急剧上升,且每条通道都需要独立的电子设备。阵列的规模设计,就是在并行度、面积、精度之间的精妙权衡。

阵列的行数(字线数)决定了单次MVM能处理的输入向量维度,列数(位线数)决定了输出维度。一个 R 行 C 列的阵列,每个时钟周期就能完成 R×C 次乘加运算——这是数字处理器无法企及的并行度。但阵列并非越大越好。位线本身有寄生电阻,电流从交叉点流向读出放大器的过程中会衰减,行数越多,远离读出放大器的贡献电流衰减越严重,造成输出误差累积。这就是为什么实际芯片往往用一个一个较小的子阵列拼接成大规模计算系统,每个子阵列单独读出,而不是做一块巨大的单一阵列。

面积开销同样制约阵列规模:RRAM器件本身密度高,但外围电路,包括数模转换器、读出放大器、编程电路等,占据了大片面积。一个1K×1K的阵列,外围电路面积可能占到整个宏单元的一半以上。吞吐率与精度的权衡在工程设计中需要反复迭代——就像仓库既想多装货架,又得留出人行走道和分拣设备的空间。

阵列规模的设计,像决定仓库货架的密度——既要装下足够多的菜(并行度),又要保证通道宽敞(精度)和造价可控(面积)。聪明的做法是“小仓拼接”:用多个适中尺寸的阵列模块拼成大规模系统,每块独立称重(读出),避免因单一阵列过大而引入累计误差。

T=R×C\displaystyle T = R \times C
这个简单的连乘说明:阵列每周期完成的乘加运算数,等于行数乘以列数,即交叉点总数。
  1. 阵列行数 R字线数量,决定输入向量的维度支持范围。
    RR
  2. 阵列列数 C位线数量,决定输出向量的维度支持范围。
    CC
  3. 一次并行的乘加量R × C 个交叉点同时工作,每个交叉点完成一次乘加。
    R×CR \times C

负权重处理

仓库的订单系统遇到了新麻烦:有些家庭昨天订了菜,今天要退掉一部分,也就是负的订单量。分拣阀门的开度只有“打开”和“关闭”的正向状态,电导也代表不了负数——一条通道怎么执行“减去两斤土豆”的操作?

存内计算对负权重的标准答案是差分阵列:把正权重和负权重分开存放,用两个阵列分别记录订单的“正向需求”和“退货需求”。实际计算时,正阵列的电流 I+ 和负阵列的电流 I− 并行产生,在读出端用减法电路相减:I_net = I+ − I−。这就像设置了“正向传送带”和“退货传送带”两条路径,家庭最后收到的是正传送带送来的蔬菜减去退货传送带走掉的菜。

差分阵列的代价是面积翻倍——一个负权重需要一对器件来存储。此外,两个阵列的器件特性如果不完全匹配(比如正阵列的电导偏高、负阵列偏低),会产生额外的共模偏置误差。另一种实现方式是参考位线方法:保持一个基准电流,被减的器件电导越多,位线电流与参考电流的差值越大,从而隐含了负权重的效果。差分方案精度更高、延迟更低,但面积代价明显;参考位线方案面积紧凑,但需要精心设计偏置电路。选择哪种方案,取决于应用对精度和成本的侧重。

“退货传送带”解决了负数的物理表示问题,但代价是一套系统要建两条传送带。差分阵列成了当今存内计算处理负权重的主流方式,它用可接受的面积开销换来了符号的正确表达——正如仓库宁愿多租一条传送带,也不愿让退货流程堵塞正常分拣。

Inet=I+−I−=∑jG+jVj−∑jG−jVj\displaystyle I_{\text{net}} = I_{+} - I_{-} = \sum_{j} G_{+j}V_j - \sum_{j} G_{-j}V_j
最终输出电流等于正阵列贡献的电流减去负阵列贡献的电流,从而实现负权重的模拟计算。
  1. 正阵列电流 I+正权重器件在输入电压下产生的电流贡献总和。
    I+=∑jG+jVjI_{+} = \sum_{j} G_{+j}V_j
  2. 负阵列电流 I−负权重同样以正电导形式存储,但最终会被减去。
    I−=∑jG−jVjI_{-} = \sum_{j} G_{-j}V_j
  3. 两者相减I+ 减 I− 得到净电流,等价于正权重求和减去负权重求和。
    Inet=I+−I−I_{\text{net}} = I_{+} - I_{-}

偏置项实现

在神经网络计算中,每个输出往往还要额外加一个常数——偏置项 b。回到仓库比喻,这相当于小区物业决定:不论每户订了多少菜,每家额外赠送一小袋葱。这个“固定赠品”与订单表无关,但每一个家庭的最终收获里都得加上它。

在存内阵列中实现偏置有多种方式。最直观的是附加列方案:在权重阵列的最右边添加一列特殊的“偏置列”,这列的输入电压固定为1(最大电压),器件电导被编程为偏置值 b 映射的电导。这样偏置列的电流贡献就是一个常数,直接累加到输出中。从矩阵角度看,这等价于把输入向量扩展一个维度(补一个1),把权重矩阵加一列(填入偏置向量)——技巧在于把偏置项伪装成“一种特殊的输入”。

另有设计选择使用固定电流源在读出端直接注入偏置电流,这种方法不需要占用额外的阵列面积,但每个输出都需要独立的电流源电路,且偏置值调整需要修改电路参数。输入扩展法也可以不增加硬件列,而是将偏置权重预先并入真实权重列中——不过这会占用一条原本可用的数据列。设计者需要在面积、灵活性和精度之间取舍。

附加列方案就像仓库里增设的“赠品专柜”——每家路过直接领一袋葱,不用分拣员计算。这一列投入小、见效快,已经成为存内计算芯片中实现偏置的标准做法,让神经网络的表达能力得以完整保留。

yi=∑j=1nWijxj+bi\displaystyle y_{i} = \sum_{j=1}^{n} W_{ij}x_{j} + b_{i}
输出等于权重矩阵与输入向量的点积结果,再加上该输出的偏置项。
  1. 基础点积结果权重矩阵第 i 行与输入向量的乘积累加,偏置作用之前的部分。
    ∑j=1nWijxj\displaystyle \sum_{j=1}^{n} W_{ij}x_{j}
  2. 偏置项 b_i第 i 个输出对应的固定偏移量,与输入无关。
    bib_{i}
  3. 相加操作点积结果加上偏置,得到最终输出值。
    yi=∑j=1nWijxj+biy_{i} = \sum_{j=1}^{n} W_{ij}x_{j} + b_{i}

性能对比分析

仓库运营了一个季度,管理者手里有了三种分拣方案的数据:纯人工计算(模拟数字处理器)、单传送带自动分拣(小规模阵列)、多通道全自动分拣(大规模阵列)。哪个方案更优?答案取决于评价的尺子是什么。

从精度来看,数字计算最精确,但能效最低;存内模拟计算精度受限于器件电导的量化噪声和电流累加误差,但能效高出1到2个数量级。从吞吐率看,大规模阵列单周期完成全部MVM,吞吐率最高,但大阵列带来的寄生电阻效应会让精度下降。从可扩展性看,小阵列模块拼装比单片大阵列更灵活,良率也更高——制作一块没有缺陷的大面积阵列远比拼装小模块困难。

实际工程中,业界逐渐形成了一套组合拳:核心层采用中小规模阵列(如128×128)以获得精度与速度的平衡,多个阵列以2D网格互连构成大规模计算系统,偏置和激活函数在数字域完成。这种“模拟做粗活、数字做精活”的混合策略,既保留了存内计算的能效优势,又避免了纯模拟方案在精度上的短板。正如仓库最终选择的方案往往是“自动传送带分装+人工品控抽查”而不是一条路走到黑。

不同的评价尺子会选出不同的最佳方案,但存内计算的独特优势在于:当“能效比”成为关键指标时,电流累加的并行魔力让它在AI推理的功耗敏感场景中独占鳌头。订单分拣的终极方案,是用最少的电费完成最多的配送——这正是存内计算写给AI时代的宣言。

η=吞吐率功耗\displaystyle \eta = \frac{\text{吞吐率}}{\text{功耗}}
能效比定义为单位功耗下能完成的运算吞吐量,是衡量存内计算方案综合竞争力的核心指标。
  1. 吞吐率每秒完成的乘加运算次数,反映计算速度。
    吞吐率\text{吞吐率}
  2. 功耗运行阵列所需的平均电功率,反映能量消耗。
    功耗\text{功耗}
  3. 能效比 η两者相除,值越大代表每瓦功耗能提供的算力越多。
    η=吞吐率功耗\eta = \frac{\text{吞吐率}}{\text{功耗}}

AI 应用场景

边缘AI语音唤醒芯片

阶段:模型推理加速

解决的问题:智能音箱、手机助手需要7×24小时监听唤醒词,传统CPU/GPU方案功耗高达数百毫瓦,导致设备发热、续航骤降。存内计算利用MVM的电流累加原理,将唤醒词检测网络的权重直接映射到RRAM阵列中,一次推理仅需要数次MVM——无需持续在内存与计算单元间搬运数据。

具体案例:某款TWS耳机中的存内计算芯片嵌入了一个128×128的RRAM阵列,运行一个三层的唤醒词识别神经网络。相比DSP方案,推理功耗从15mW降至0.4mW,待机功耗降低38倍,电池续航从3天延长到两周。用户说出“你好小X”时,阵列在约5微秒内完成MVM运算,唤醒延迟人耳完全无感。

大语言模型推理加速卡

阶段:LLM推理的GEMM算子加速

解决的问题:大语言模型推理的瓶颈在于庞大的权重矩阵与激活向量的MVM运算。传统方案需要从HBM中反复读取权重(memory-bound),存内计算将权重“焊”在计算单元内部,SRAM存内计算宏单元以极高的带宽执行MVM,大幅缓解访存墙问题。

具体案例:某初创公司发布的LLM推理加速卡集成了256个存内计算宏单元,每个宏单元为64×64的SRAM阵列。在运行7B参数的对话模型时,该加速卡相比同工艺GPU推理能效提升11倍,首token延迟降低至原来的四分之一,使得在单张PCIe卡上实时运行70B量化模型成为可能。

Python 演示

python50 行
import numpy as np class RRAMArray:    """模拟RRAM差分存内计算阵列的矩阵向量乘"""     def __init__(self, weight, g_max=100e-6, v_read=0.2, noise=0.02):        self.weight = np.array(weight, dtype=float)        self.w_max = np.max(np.abs(self.weight))        self.g_max = g_max        self.v_read = v_read        self.noise = noise        # 正负权重分别映射到两个子阵列的电导        self.g_plus = self._map_weights(np.where(self.weight > 0, self.weight, 0))        self.g_minus = self._map_weights(np.where(self.weight < 0, -self.weight, 0))     def _map_weights(self, w):        """将权重线性映射为电导值,并量化到1uS步进"""        g = w / self.w_max * self.g_max        return np.round(g / 1e-6) * 1e-6     def mvm(self, x):        """执行矩阵向量乘:I = G @ V"""        v = np.array(x, dtype=float) * self.v_read        i_plus = self.g_plus @ v        i_minus = self.g_minus @ v        # 模拟读出电路的随机噪声        i_plus *= (1 + np.random.randn(*i_plus.shape) * self.noise)        i_minus *= (1 + np.random.randn(*i_minus.shape) * self.noise)        i_net = i_plus - i_minus        # 电流换算回权重乘加结果        return i_net / (self.g_max * self.v_read) * self.w_max  if __name__ == "__main__":    np.random.seed(42)    # 含负权重的 3x3 权重矩阵    W = np.array([        [0.5, -0.2, 0.8],        [-0.3, 0.6, 0.1],        [0.4, -0.7, 0.2]    ])    x = np.array([0.8, 0.3, -0.5])     array = RRAMArray(W)    y = array.mvm(x)    y_ideal = W @ x     print("存内计算输出:", y)    print("理想计算结果:", y_ideal)    print("绝对误差:", np.abs(y - y_ideal))
目的:模拟RRAM差分阵列中“权重→电导映射→电流乘加→电流差输出”的完整MVM流程,直观展示模拟计算的误差来源。
  1. np.where(self.weight > 0, self.weight, 0)提取正权重子矩阵,负权重置零,生成正阵列的映射源。
  2. w / self.w_max * self.g_max核心的权重映射公式:按最大值归一化后线性放缩到电导范围。
  3. np.round(g / 1e-6) * 1e-6模拟实际器件的电导量化:器件只能以约1µS的步进编程。
  4. self.g_plus @ v矩阵乘法器直接计算电流贡献:电导矩阵乘以电压向量,一步完成所有乘加。
  5. i_plus - i_minus差分阵列的关键:正负阵列电流相减,得到含负权重的净输出。
  6. * (1 + np.random.randn(...) * self.noise)在电流域注入2%的随机噪声,模拟读出放大器的热噪声。

常见误区

误区既然MVM在阵列中瞬间完成,那么结果应该和CPU上算出来的完全一致,精度问题只是软件没调好。

正解存内计算本质是模拟计算,电导的量化步长、编程误差、电流噪声、位线寄生电阻等都会引入不可避免的误差。一个8-bit的RRAM阵列实际有效精度往往只有6-bit左右。这就好比传送带的阀门开度本身就有±2%的偏差,分拣出来的菜不可能精确到克。精度损失的补偿需要依靠网络量化训练、校准算法等软件手段。

为何常见:人们习惯了数字电路“0/1严格区别”的确定性,忽视了模拟信号连续变化的本质,容易默认计算结果应该是精确的。

误区既然并行度等于阵列行数乘以列数,那我直接把阵列做到1024×1024,吞吐率不就翻倍了吗?

正解阵列增大后,位线上的寄生电阻和电容显著增长,远离读出放大器的单元贡献电流衰减严重,计算误差随之增大;同时大阵列的制造良率下降、外围电路面积占比攀升,整体能效可能反而下降。实际设计通常采用128×128或256×256的中小阵列,再通过多核拼接扩展规模。

为何常见:直觉上“更多人干活更快”是对的,但忽略了大团队协作的沟通损耗(寄生效应)和管理成本(外围电路面积),这在存内阵列中同样存在。

误区RRAM器件的电导只有正值,负权重无法直接表示,那是不是就在字线上施加负电压就能实现负数?

正解主流方案并非负电压,而是差分阵列结构——把正权重和负权重拆开存储在两个子阵列中,分别产生正向来流I+和反向电流I−,再用减法电路取差。这是因为器件本身是两端无源元件,施加负电压在物理上不改变电导的正值属性,反而让外围驱动电路复杂化。差分方案则完全不需要修改器件的物理特性。

为何常见:人们习惯用数学上的“符号”概念去套物理实现,没有意识到“正负”在模拟器件中需要依靠电路结构来体现,而非简单加个符号位。

误区偏置是在矩阵乘之后单独加的,所以存内计算需要额外一个时钟周期来执行偏置加法,影响整体延迟。

正解附加列的偏置实现让偏置计算与MVM同时完成——偏置列的电导是固定的,输入恒为1(满幅电压),它产生的电流直接在列线上与其他贡献电流相加,完全不需要额外的时间开销。这就像租用了一个专门的“赠品通道”,和正常分拣同时进行。

为何常见:人们把软件中的“两步操作”照搬到硬件上,忽略了模拟电路中的信号可以在物理上叠加,加法天然免费。

面试题

Q1. 在存内计算中,矩阵向量乘法的核心运算本质是什么?

单选题 · easy

  • A.将权重矩阵逐元素与输入向量相加
  • B.每一行权重与输入向量的乘积累加← 正确答案
  • C.将输入向量广播复制为矩阵
  • D.对权重矩阵做转置后取平均值

答案:B。MVM的输出第 i 个分量等于权重矩阵第 i 行与输入向量的点积,即逐元素相乘再累加(乘加)。这与社区订单表中“每户各栏数量×对应蔬菜总量再求和”完全对应。A是加法而非乘加,C是广播操作,D只是矩阵变换,都不符合MVM核心定义。

Q2. 存内计算利用了什么物理定律直接在阵列中完成乘加运算?

单选题 · easy

  • A.牛顿第二定律和万有引力定律
  • B.欧姆定律和基尔霍夫电流定律← 正确答案
  • C.法拉第电磁感应定律
  • D.阿基米德浮力定律

答案:B。欧姆定律 I=G×V 完成电压与电导的乘法,基尔霍夫电流定律使汇聚到同一位线的电流自动相加。这两条定律共同把矩阵向量乘的“乘”和“加”都物理化。牛顿定律管力学,法拉第定律管电磁感应,浮力定律管流体,都与电荷守恒下的电流累加无关。

Q3. 存内计算的高并行性从根本上来源于什么?

单选题 · easy

  • A.所有阵列单元同时执行乘加运算← 正确答案
  • B.CPU多核指令级并行
  • C.GPU流水线指令重叠
  • D.多个芯片串联协同工作

答案:A。存内阵列中所有交叉点在同一时刻被字线电压驱动,同时产生电流贡献,并行度等于阵列交叉点总数。这不同于CPU多核或GPU流水线这类指令级并行。多芯片串联虽然能扩大规模,但并行性本源仍是单阵列所有单元同时工作。

Q4. RRAM阵列中,权重值通常通过什么物理量来表示?

单选题 · mid

  • A.器件的电容值
  • B.器件的电阻或电导值← 正确答案
  • C.器件的电感值
  • D.器件的阈值电压

答案:B。RRAM(忆阻器)的核心特性是其可编程电阻,权重被映射为器件电导(电阻倒数),通过电流 I=G×V 参与乘加。电容存储电荷、电感抵抗电流变化、阈值电压是晶体管开关属性,它们都不是RRAM权重存储的主要机制。

Q5. 偏置项在存内计算阵列中最常见的实现方式是什么?

单选题 · mid

  • A.在阵列中增加一列固定输入为1的单元← 正确答案
  • B.在输出端串联一个大电阻分压
  • C.直接调整输入向量的幅度比例
  • D.利用软件在读出后单独添加

答案:A。附加列法将偏置权重存入一列专用的器件中,该列的输入电压恒为满幅(即1),产生的电流在列线上与正常乘积电流自然相加,不占用额外时间。B串联分压会同时衰减所有信号,C改变输入幅度会影响所有权重计算,D软件后处理会增加延迟和功耗。

Q6. 使用差分阵列处理负权重时,最终输出电流是什么?

单选题 · mid

  • A.正阵列电流与负阵列电流之和
  • B.正阵列电流减负阵列电流← 正确答案
  • C.负阵列电流减正阵列电流再取平方
  • D.正负阵列电流的平均值

答案:B。差分阵列的核心思路是 I_net = I+ − I−:正权重的贡献来自正阵列,负权重的贡献在负阵列中以正电导形式存储,最终通过减法电路合并,等效于“正向传送带减去退货传送带”。求和会把负权重错误地变成更大正值,平方和平均更是完全偏离数学定义。

Q7. 阵列尺寸增大到一定程度后,计算精度反而明显下降,主要原因是?

单选题 · hard

  • A.权重值自身随阵列大小发生变化
  • B.位线寄生电阻导致电流累积误差← 正确答案
  • C.输入向量维度与阵列不匹配
  • D.读出放大器的时钟频率自动降低

答案:B。位线是长金属线,本身有寄生电阻。阵列越大,交叉点电流到达读出放大器需要流经的寄生电阻越多,压降越大,导致远端器件的电流贡献被衰减,产生系统性误差。权重值不随阵列尺寸改变,输入维度不匹配会报错而非精度降低,时钟频率与精度无因果联系。

Q8. 以下哪些方案可以实现存内计算中的偏置项?

多选题 · mid

  • A.在阵列中增设偏置列,输入固定为1← 正确答案
  • B.使用固定电流源在读出端注入← 正确答案
  • C.扩展输入向量加入恒为1的维度← 正确答案
  • D.将偏置编码进所有权重的平均值中

答案:ABC。附加列(A)和输入扩展(C)本质上是同一思路的两种描述——把偏置伪装成一个额外的输入维度。固定电流源(B)是从电路层面直接注入恒定电流,也可行。D求平均值会将偏置平均到每个权重中,破坏原有权重值,不可行。

Q9. 关于存内计算中“电流累加”的过程,描述正确的是?

多选题 · hard

  • A.每个交叉点的电流与权重电导和输入电压成正比← 正确答案
  • B.同一列上的贡献电流在位线上自然求和← 正确答案
  • C.输出电流等于各位线电流的乘积
  • D.累加过程不需要额外的时钟周期← 正确答案

答案:ABD。I=G×V 保证每个交叉点电流正比于电导和电压(A正确);基尔霍夫定律使同列电流在导线中自然叠加(B正确);物理累加发生在信号传输过程中,无需计时(D正确)。C把“累加”错写成“累乘”,电流是标量求和不是求积,违反基尔霍夫定律。

Q10. 在SRAM存内计算中为减少位线电流累加误差,下列哪种方法最有效?

单选题 · extreme

  • A.增大输入电压幅值
  • B.划分子块并增加读出放大器← 正确答案
  • C.将SRAM单元全部换成RRAM单元
  • D.将数据从模拟域转为全数字域计算

答案:B。划分子块缩短了位线长度,降低寄生电阻路径;增加读出放大器让每个子块独立电流读出,避免长位线上远端电流大幅度衰减。增大电压会推高功耗且不解决寄生问题,换器件改变了存储介质但未解决结构问题,全数字域则放弃了存内计算的能效优势。