写进裸盘的三百亿个参数 左边是把权重直接 dd 到 /dev/nvme1n1 的命令和参数个数 30,532,122,624;右边一根 M.2 固态盘上方放大出闪存单元的网格,其中几个亮起的单元伸出弯曲的连线,汇聚到一个像神经元胞体的圆点上。 $ dd if=qwen3-30b-a3b-q4.bin \ of=/dev/nvme1n1 oflag=direct 30,532,122,624 个参数,没有文件名,没有目录 LBA 0 … 3,727,067

Qwen3-30B-A3B 有 30,532,122,624 个参数1,用 BF16 存是 61 GB,量化到 4 位约 15 GB。假设我们已经把量化好的权重拼成了一个连续的二进制文件,拿一块新盘,不分区、不格式化,直接把它写进去:

Terminal window
dd if=qwen3-30b-a3b-q4.bin of=/dev/nvme1n1 bs=4M oflag=direct

写完以后,这块盘上没有文件名,也没有目录。从第 0 个扇区开始,就是这三百亿个数。拔掉电源放进抽屉,一年后插上,它们还在。

我们常说,大脑的长期记忆存在突触的强度里,而突触强度也是一个能保持很久的物理量。一个 4 位的权重和一个突触的强度,看起来都是“用一个物理量存住的一个数”。于是就有了下面几个问题:

  1. 没有文件系统时,这 30B 个参数在盘上是什么形态?落到物理介质上,它们和突触有多像?
  2. 盘里存着这些数,算不算像神经元那样“记住”了?两种记忆差在哪里?
  3. 不把参数全部搬进内存,直接从盘上边读边用,30B 能跑多快?
  4. 能不能让盘里的存储单元自己参与计算,甚至像突触一样边用边学?
  5. 如果真要把 30B 参数固化到盘上,什么样的模型、什么样的盘最合适?

本文就顺着这五个问题,一层一层往下讲。


一、裸盘上的三百亿个数

没有文件系统,盘就是一个大数组

在 Linux 下,一块不分区、不格式化的盘,就是 /dev/nvme1n1 这样一个块设备。对程序来说它只有一个属性:大小。读写时给出偏移量和长度,盘就把那一段字节交出来;偏移量除以扇区大小(今天的盘多是 4 KiB),就是 LBA(逻辑块地址)。

文件系统是在这个大数组上又加的一层:文件名、目录、权限,以及“这个文件的第 N 个字节在盘上哪里”的映射表。去掉文件系统,名字没了,但偏移量本身就是地址,不需要再查表。

对模型权重来说,名字这一层本来就可有可无。一个模型是一组形状和顺序都固定的张量。常见的 safetensors 格式,本身就是一个 JSON 头加一段连续的原始字节,头里记着每个张量的形状和起止偏移2。把它铺到裸盘上,什么都不会丢。

以 Qwen3-30B-A3B 为例。它有 48 层,每层 128 个专家,每个专家是三个矩阵:gate_proj 和 up_proj 是 768×2048,down_proj 是 2048×7681。一个专家共 4,718,592 个参数,按 4 位存是 2,359,296 字节,正好 576 个 4 KiB 扇区(为了算得整齐,这里不计量化格式里的缩放因子,实际的 4 位格式每个参数还要多出零点几位)。把专家按“层号、专家号”的顺序依次排好,第 layer 层第 e 个专家的位置就是:

offset = (layer × 128 + e) × 2,359,296

要读第 0 层的 1 号专家,算出 LBA 576,连续读 576 个扇区就行。

一个专家的权重怎样落到裸盘上 第 0 层 1 号专家的三个矩阵按 4 位存共 2,359,296 字节,按公式算出偏移量,除以 4096 得到 LBA 576;在裸设备上,专家按层号和专家号依次排开;SSD 内部再由 FTL 把 LBA 576 到 1151 映射到某颗芯片某个块的第 88 到 231 页,这一层主机看不到。 一个专家的权重(4 位) 主机按公式算地址,不查表 裸设备 /dev/nvme1n1 · 4 KiB 扇区 SSD 内部 · FTL(主机看不到) 专家 layers.0.experts.1 gate_proj768×2048786,432 B up_proj768×2048786,432 B down_proj2048×768786,432 B 合计2,359,296 B = 576 扇区 偏移量 offset = (layer×128 + e) × 2,359,296 layer = 0, e = 1 offset = 2,359,296 LBA = offset ÷ 4096 = 576 L0 · E0LBA 0 L0 · E1LBA 576 L0 · E2LBA 1,152 L0 · E3LBA 1,728 … L0 · E127LBA 73,152 L1 · E0LBA 73,728 … LBA 576–1151 → 芯片 2 · 块 1,407 · 页 88–231 虚线:控制器内部的映射(示意),会随垃圾回收改变
图 1 · 去掉文件系统,偏移量就是地址:主机按公式算出 LBA 直接读。但 SSD 的 LBA 只是逻辑地址,底下还有一层主机看不到的映射。

不过,“裸”只裸到接口这一层。在 SSD 里,LBA 只是一个逻辑地址:闪存不能原地改写,只能按页(常见 16 KiB)写、按块擦,所以控制器内部维护一张 FTL(闪存转换层)映射表,把每个 LBA 映射到某颗芯片、某个块、某一页,并且在垃圾回收和磨损均衡时不断搬动数据3。机械硬盘好一些,LBA 基本按顺序对应到磁道上的扇区,只有坏扇区会被重映射到备用区。所以,裸盘给主机的是一个平整的地址空间,但底下的介质并不长这个样子。

一个存储单元能存多少

再往下一层,到一个存储单元。今天的大容量 SSD 多用 QLC 闪存:每个单元是一个浮栅(或电荷俘获)晶体管,里面存着一些电荷,电荷多少决定了它的阈值电压。阈值电压是一个连续量,控制器把它划成 16 个窗口,于是一个单元能存 4 位。

按数量算,一个 4 位权重刚好对应一个 QLC 单元。30.5B 个参数就是 30.5B 个单元;一块 1 TB 的 QLC 盘大约有 2×10¹² 个单元,这个模型只占其中的 1.5%。

突触这边,有一项研究用电镜重建了大鼠海马里的突触,按突触的大小估计,它们大约能区分出 26 档强度,折合约 4.7 比特4。两边惊人地接近:都是一个断电后仍然保持的模拟量,都被分成了十几二十档,大约 4 比特。

但盘并不让“一个权重的值”等于“一个单元的电荷量”。控制器写入之前,先把数据和一段伪随机序列做异或(加扰),避免全 0、全 1 这类图案加重单元之间的干扰,再加上 ECC 校验位。而在 QLC 的一条字线上,一个单元的 4 位分属 4 个不同的页,同一页里相邻的位落在相邻的单元里3。结果是:一个权重的 4 位分散在 4 个单元里,每个单元又混着另外 3 页里不相干的数据。

一个 4 位权重在 QLC 闪存里的样子 权重 −0.0126 量化成 4 位码 0101,控制器加扰后变成 0011,写进 lower 页,落在一条字线上第 4 到第 7 个单元的最低位。每个单元的另外 3 位来自 middle、upper、top 三个页,单元的档位由 4 位共同决定,于是这 4 个单元分别处在 L4、L8、L14、L10。 写入之前 QLC 的一条字线(示意) 一个权重 w−0.0126 缩放 s0.0042 w/s + 85 4 位码0101 控制器 加扰0101 ⊕ 0110 = 0011 校验另附 ECC 位 写到lower 页 加扰序列和页的分配都由盘决定 单元 0 1 2 3 4 5 6 7 lower 页 1011 0011 middle 页 01101001 upper 页 11001101 top 页 00100111 档位 L6L4L13L1 L4L8L14L10 阈值电压 L0 L15 16 个窗口,一个单元落在其中一个 这个权重的 4 位只占 4 个单元各自的最低位; 每个单元的档位还取决于另外 3 页里不相干的数据。
图 2 · 按数量算,一个 4 位权重对应一个 QLC 单元;但写进盘以后,它的 4 位分散在 4 个单元里,每个单元的电荷量混着 4 页的数据。档位编码按格雷码示意,实际排列由厂商决定。

所以,按数量算,这块盘装得下 30B 个“突触”,每个单元的精度也和突触差不多;只是值和物理量之间的对应关系,被控制器有意打乱了。那么,盘里存着这些数,算不算像神经元那样“记住”了它们?


二、两种记忆:按地址读取与按内容回忆

盘的记忆:给出地址,取回一块

从盘里取东西,唯一的办法是给出地址。如果你只记得内容的一部分,比如“那条记忆大概是 1011 0010 开头的”,盘帮不上忙,只能把整块盘读出来,由 CPU 一条条去比。比较这件事发生在 CPU 里,不在盘里。

盘上的存储单元还被刻意设计成互不影响。机械硬盘的磁性颗粒之间隔着非磁性的晶界,免得一个颗粒的磁化方向带动邻居;闪存里,相邻单元之间的电容耦合被当成一种错误来源,控制器要花力气去补偿它3。互不影响带来了局部性:一个扇区的数据只在那一个地方,坏了就是坏了。ECC 纠不回来时,盘返回的是整个扇区的读错误,不会给你“大致对的”数据。

神经元的记忆:给出一部分,回忆出全部

神经网络里最经典的记忆模型是 1982 年的 Hopfield 网络5。它有 N 个神经元,每个取值 ±1,任意两个神经元之间有一个连接权重 WijW_{ij}。要存 P 条记忆 ξ1,…,ξP\xi^1, \dots, \xi^P,用 Hebb 规则(一起激活的神经元,连接就加强)把它们叠加到同一个权重矩阵里:

W=1N∑μ=1Pξμ(ξμ)⊤,Wii=0W = \frac{1}{N}\sum_{\mu=1}^{P} \xi^{\mu} \left(\xi^{\mu}\right)^{\top}, \qquad W_{ii} = 0

回忆时,从一条线索 ss 出发,反复做 s←sign⁡(Ws)s \leftarrow \operatorname{sign}(W s),直到状态不再变化。只要存的条数不超过约 0.138N,每条记忆都是一个稳定的吸引子6:线索落在它附近,就会被拉回到它本身。

这里有两点和盘完全不同。第一,每条记忆都摊在全部 N² 个权重上,每个权重也都承载着所有记忆的一小部分,没有“第 17 条记忆存在哪”这回事。第二,取回记忆靠的不是地址,而是内容:给出一个有错、不全的版本,网络自己演化到最近的那条。

按地址读取与按内容回忆 左边是扇区方式:50 条记忆各占一个扇区,地址是内容的 SHA-256;第 17 条记忆错了 1 位,哈希就从 bd86…a3 变成 3438…f6,查不到。右边是 Hopfield 网络:第 17 条记忆错了 30%,与原记忆重合 70.0%,经过 s ← sign(Ws) 一轮变成 96.5%,两轮变成 100%。 硬盘:给地址,取回一块 Hopfield:给一部分,回忆出全部 没有这个地址 s ← sign(W s) s ← sign(W s) 扇区 地址 = SHA-256(内容) e6bf…64#161001 0000 … bd86…a3#170001 1001 … 47ed…9e#181101 1101 … … 共 50 个扇区 线索:#17 错了 1 位 内容0001 1001 … (第 k 位翻转) SHA-2563438…f6 线索:#17 错了 30% 与 #17 重合 70.0% 第 1 轮 96.5% 第 2 轮:#17 100% 50 条记忆都叠在同一个 1024×1024 的 W 里, 没有“第 17 条存在哪”这回事。 数字取自文中实验的第 17 条记忆
图 3 · 盘只认完整的地址,错 1 位的线索换来一个完全不同的哈希;Hopfield 网络从错了 30% 的线索出发,两轮就回到原来的记忆。

实验:同样 50 条记忆,两种存法

光说不够直观,我们做一个小实验。随机生成 50 条记忆,每条 1024 位,分别用两种方式存:

  • 扇区方式:每条记忆占一个扇区,用内容的 SHA-256 当地址。这是在按地址存储上做“按内容找”最直接的办法。
  • Hopfield 方式:N = 1024 个神经元,50 条记忆用 Hebb 规则叠进一个 1024×1024 的权重矩阵,负载 50/1024 ≈ 0.049,远低于容量上限。

然后测两件事:线索有错时能不能取回,以及介质坏掉一部分以后还能取回几条。介质损坏在扇区方式里是随机坏掉一部分扇区,在 Hopfield 方式里是随机剪断一部分连接(把权重置零)。

50 条 1024 位的记忆,两种存法
条件扇区:完整取回Hopfield:完整取回Hopfield:平均每条对的位数
线索有错,介质完好
错 0%50 / 5050 / 50100%
错 1%0 / 5050 / 50100%
错 10%0 / 5050 / 50100%
错 30%0 / 5050 / 50100%
错 40%0 / 5046 / 5098.13%
介质坏掉一部分(Hopfield 的线索另有 10% 的错)
坏 10%45 / 5049 / 50> 99.99%
坏 30%35 / 5043 / 5099.99%
坏 50%25 / 5027 / 5099.91%
坏 70%15 / 500 / 5099.10%
坏 90%5 / 500 / 5085.46%

扇区方式里,坏掉的扇区整块读不出来,没坏的完整无误,所以没有“对了多少位”这一列。Hopfield 方式里的“坏”是随机剪断这一比例的连接。脚本见文末,随机种子固定,结果可复现。

表 1 · 按地址存,线索必须一位不差,坏掉的记忆整条消失;按 Hopfield 存,错 30% 的线索也能回忆,连接剪掉 70% 时每条记忆仍有 99% 的位是对的

表 1 说明了三件事。

按内容取,盘只认完全一样的线索。 错 1 位,哈希就完全不同,50 条一条也找不回来;Hopfield 网络在线索错了 30% 时仍然全部回忆正确。

坏的方式不一样。 扇区坏掉一半,就有一半记忆整条消失,剩下的一半完好无损;Hopfield 的连接剪掉 70%,没有一条记忆还能一位不差,但每条平均仍有 99.1% 的位是对的。前者是“要么全有、要么全无”,后者是所有记忆一起慢慢变模糊。

神经元式的记忆很贵。 扇区方式用 51,200 位存了 51,200 位;Hopfield 用了 1,048,576 个权重(每个还不止 1 位),是前者的 20 倍以上。每回忆一次,还要做好几次 1024×1024 的矩阵乘向量。

差别在“读”的方式,不在存储单元

把这个实验拆开看:Hopfield 网络的“记忆”,是权重矩阵 WW 加上更新规则 s←sign⁡(Ws)s \leftarrow \operatorname{sign}(W s) 两部分合起来才有的。只有 WW,它就是一百万个数;把 WW 写进盘,盘有了 WW,却没有那个规则。

大模型也是这样。有研究发现,Transformer 的前馈层就像一组键值记忆:隐藏向量和每个“键”做内积,衡量当前输入和某种文本模式有多匹配,再按匹配程度把对应的“值”加权求和7。注意力的更新规则,也已经被证明和现代 Hopfield 网络的更新等价8。在这些模型里,“按内容回忆”都是靠矩阵乘法完成的。

所以,对第二个问题的回答是:盘有了突触,但没有神经元。 写进盘的 30B 个参数,要变成记忆,必须有什么东西拿着它们去做矩阵乘法。最直接的分工,就是盘只负责存,CPU 或 GPU 负责算。那么,每生成一个 token,要从盘里搬多少数据?


三、盘只存储、处理器计算:每个 token 的读盘量

稠密模型:每个 token 都要把权重读一遍

大模型生成文字是一个 token 一个 token 往外吐的。每生成一个 token,每个权重都要参与一次乘加。只服务一个用户时,从存储里读出的每个字节只换来一两次运算,速度几乎完全由读权重的带宽决定。

如果是一个 30B 的稠密模型,4 位量化后约 15.3 GB,那么每生成一个 token 就要把这 15.3 GB 读一遍。

MoE:一个 token 只用到一小部分专家

Qwen3-30B-A3B 是 MoE(混合专家)模型:每一层有一个路由器,根据当前 token 的隐藏向量,从 128 个专家里挑 8 个来算1。专家参数一共 28,991,029,248 个,占全部参数的 95%;每个 token 只用到其中的 48 × 8 = 384 个专家,按 4 位算是 0.91 GB。剩下的 1.54B 个非专家参数(注意力、词嵌入、路由器)4 位后约 0.77 GB,每个 token 都要用,常驻内存。

生成一个 token 要从盘上读哪些专家 48 行代表 48 层,每行 128 格代表 128 个专家,每格 2.36 MB,按层号和专家号依次存放在裸盘上。生成一个 token 时每层只亮 8 格,共 384 格,0.91 GB,而全部专家有 6,144 格,14.5 GB。 Qwen3-30B-A3B 的专家在裸盘上的排布 专家 0 · LBA 0 专家 127 第 0 层 第 12 层 第 24 层 第 36 层 第 47 层 这个 token 读 384 块 × 2.36 MB = 0.91 GB 全部专家 6,144 块 = 14.5 GB 地址从左上角开始,先走完一行(一层的 128 个专家,302 MB),再换到下一行。 亮的格子是路由器为当前 token 选中的专家,每层 8 个;位置为示意。
图 4 · 一个 token 只用到 6,144 个专家里的 384 个。它们散落在盘上的 384 个位置,每个位置连续读 2.36 MB。

这和神经元的工作方式有一点像:大脑里的神经元在任一时刻也只有一小部分在放电。

算账:不同的盘,每个 token 要等多久

只看读盘时间,不算计算,也不考虑缓存,结果如表 2。

生成一个 token,光读权重要多久
存储读带宽稠密 30B(读 15.3 GB)Qwen3-30B-A3B(读 0.91 GB)
内存:DDR5-5600 双通道89.6 GB/s0.17 s0.010 s
NVMe:三星 990 PRO7,450 MB/s2.0 s0.12 s
SATA 固态盘约 550 MB/s28 s1.7 s
本文的云盘(实测)163 MB/s94 s5.6 s
7200 转机械硬盘约 250 MB/s61 s8.3 s

只算读权重的时间,不算计算,不考虑缓存;MoE 一列不含常驻内存的 0.77 GB 非专家参数。内存和三种盘按标称或典型带宽估算,机械硬盘每次随机读另加约 12 ms 的寻道和旋转等待;云盘一行是实测。

表 2 · 同样是 30B,MoE 每个 token 只读十七分之一的数据。NVMe 上每秒能出约 8 个 token,机械硬盘每个 token 要等 8 秒以上

机械硬盘那一行要多解释一句。它的顺序读能到 250 MB/s 左右,但每次随机读都要先移动磁头、再等盘片转到位置:7200 转的盘转一圈 8.33 ms,平均要等半圈 4.17 ms,再加上平均约 8 ms 的寻道,每次随机读要多花约 12 ms。MoE 每个 token 要做 384 次这样的随机读,光等磁头就要 4.7 秒。

云盘那一行是实测的:我写这篇文章用的是一台 4 核的云主机,系统盘是一块 50 GB 的云盘(lsblk 显示型号为 PersistentDisk)。用文末的脚本按上面的布局写了 8 层专家(2.42 GB),用 O_DIRECT 绕过页缓存读回来,顺序读和按 MoE 模式随机读都是 160 MB/s 左右,折算到 48 层每个 token 要 5.6 秒。这块盘被限速了,2.36 MB 一次的读也足够大,所以随机读没有比顺序读慢。

让常用的专家留在内存里

上面的算法有一个明显的浪费:相邻的几个 token 往往会用到大量相同的神经元和专家,每次都从盘上重新读,等于把同样的数据搬了很多遍。

苹果的 LLM in a flash 就是从这里入手的9。它把最近几个 token 激活过的神经元留在内存里(窗口化),每个新 token 只从闪存读新增的那部分;再把一起被用到的行和列存在相邻位置,让每次读都尽量大、尽量连续(行列捆绑)。这样能跑比内存大一倍的模型,比朴素的按需加载在 CPU 上快 4–5 倍,在 GPU 上快 20–25 倍。PowerInfer-2 用类似的思路,按神经元簇来调度计算和 I/O,在手机上跑起了 47B 的模型,11.68 token/s10。

到这里,第三个问题有了答案:用 NVMe 固态盘配 MoE 模型,把 30B 参数平铺在裸盘上、边读边算,是可以跑起来的,每秒几个 token;机械硬盘每个 token 要等好几秒,不实用。 但是在这种分工里,盘只是一块慢一点的内存,“回忆”这件事仍然发生在处理器里。能不能不把数据搬出来,让参数在盘里就地参与计算?


四、让存储单元参与计算

浮栅单元本来就能做乘法

一个浮栅晶体管存的电荷,决定了它在给定电压下能导通多大的电流,可以把它看成一个可调的电导 GG。在它两端加一个电压 VV,流过的电流就是 I=G⋅VI = G \cdot V,一次乘法就完成了。把一列单元并联在同一根位线上,各自的电流在位线上自然相加(基尔霍夫电流定律),于是这根位线上的总电流就是一个内积 ∑iGiVi\sum_i G_i V_i。整个阵列一次读出,就完成了一次矩阵乘向量。

这样的实验早就有人做过。2016 年,Strukov 和 Likharev 等人把商用 180 nm NOR 闪存改造成模拟计算阵列,用 101,780 个浮栅单元当突触,每个单元的电导可以调到约 1% 的精度。在 MNIST 手写数字识别上,芯片做到了 94.65% 的准确率(仿真为 96.2%),分类一张图不到 1 微秒,耗能约 20 纳焦11。在这里,一个权重的值就是一个单元的状态,图 2 里被控制器打乱的那种对应关系又回来了。

NOR 阵列和 NAND 串 左边是 NOR 阵列:三个输入电压 0.2、0.5、0.1 伏加在三行上,每个单元的电导是一个权重,同一根位线上的电流相加,位线 1 的电流是 4×0.2 + 1×0.5 + 7×0.1 = 2.0 微安,一次读出就是一次内积。右边是 NAND 串:六个单元串联在位线和源极之间,读第 3 条字线时,其余字线加导通电压,电流只由被读的单元决定,不能相加。 NOR 阵列:单元并联,电流在位线上相加 NAND 串:单元串联 位线 1 位线 2 V₁ = 0.2 V V₂ = 0.5 V V₃ = 0.1 V G = 4 G = 1 G = 7 G = 2 G = 6 G = 3 I₁ = 2.0 μA I₂ = 3.7 μA I₁ = 4×0.2 + 1×0.5 + 7×0.1 = 2.0 μA 电导 G 的单位是 μS;数值为示意 位线 WL0 · V_pass WL1 · V_pass WL2 · V_pass WL3 · V_read(被读) WL4 · V_pass WL5 · V_pass 源极 其余单元加导通电压,电流只看被读的那个; 同时读几条字线,全都导通才有电流,等于“与”。
图 5 · NOR 阵列里,欧姆定律做乘法、基尔霍夫电流定律做加法,一次读出就是一次矩阵乘向量;SSD 里的 NAND 把单元串起来换密度,电流不能相加,只能做按位运算。

SSD 里的 NAND:串联结构只适合按位运算

问题在于,SSD 用的不是 NOR,而是 NAND。NAND 为了密度,把几十到上百个单元串联成一串,共用一根位线。读其中一个单元时,要给串上其他所有单元加一个足够高的导通电压,让它们全部导通,只留被读的那个决定电流。串联的单元电流不会相加,只会被最弱的那个卡住。

串联也不是全无用处。Flash-Cosmos 发现,同时感应一串里的多条字线,只有每个单元都导通时才有电流,相当于对这些位做“与”;同时感应挂在同一根位线上的多个块,任何一串导通就有电流,相当于做“或”。作者在 160 颗真实的 3D NAND 芯片上验证了这种做法12。但这只是按位运算,不是乘加。

要在闪存里跑大模型,就得改芯片。Cambricon-LLM 设计了一颗专门的 NAND 闪存芯片,在片内加入计算单元和 ECC,让闪存负责轻量的片上运算,NPU 负责其余的矩阵运算和特殊函数。在它的评估里,70B 模型能跑到 3.44 token/s,7B 模型 36.34 token/s,比从闪存卸载权重的方案快 22–45 倍13。

这些都是专门设计的芯片。买来的 SSD 只通过 NVMe 或 SATA 接口收发数据块,主机没有办法让它的闪存去做乘加。机械硬盘更不行:磁头一次只能沿一条磁道串行地读,介质本身没有可以利用的并行物理过程。机械硬盘这条路,到这里就走到头了。

模拟计算还有它自己的代价:单元的电导会随温度漂移,每根位线都要配一个模数转换器,1% 的精度大约只相当于 6–7 位。4 位量化的大模型能容忍一定的噪声,但要在几十层里层层累积,误差能不能控制住,仍是这类芯片要解决的问题。

单元能算了,下一步自然想问:它能不能像突触一样,边用边学?


五、在盘上学习:写入的代价

突触可以双向调整,闪存单元只能单向写

突触的强度可以增强(长时程增强,LTP),也可以减弱(长时程抑制,LTD),调整只发生在这一个突触上,不影响旁边的。

闪存单元做不到。编程(写)是往浮栅里注入电子,只能让阈值电压升高,而且以页为单位进行;要让阈值电压降回来,只能把整个块擦除,一个块里有成百上千个页3。梯度下降的每一步,都要让每个权重或增或减,落到闪存上,就只能把新值写到新的页里,旧页标记作废,等以后整块搬走、擦除。

突触和闪存单元怎样改一个值 突触的强度可以就地增强或减弱,只影响这一个连接。闪存单元编程只能抬高阈值电压,要把一个值改小,只能写到新页、旧页作废,等整块擦除。按每步重写 366 GB 计算,一块 1,200 TBW 的盘只够训练约 3,300 步。 突触:就地增强,也能就地减弱 闪存单元:写只能加,减要整块擦 寿命算账:用 Adam 训练 30B,状态放在 990 PRO 2 TB 上 一个突触 当前强度0.42 增强 LTP0.42 → 0.47 减弱 LTD0.42 → 0.38,就地完成 影响范围只有这一个连接 一个 NAND 单元 编程(写)按页,只能抬高阈值电压 改小一个值写到新页,旧页作废 擦除整块,成百上千页一起 代价每次擦写消耗一次寿命 每步重写30.5B × 12 B = 366 GB 标称写入寿命1,200 TBW 够训练1,200 TB ÷ 366 GB ≈ 3,300 步 12 B = FP32 主权重 + 两份动量。 预训练动辄几十万步。
图 6 · 梯度下降每一步都要让权重有增有减;突触能就地减弱,闪存单元只能把新值写到别处,再整块擦掉旧的,寿命经不起训练的消耗。突触的数值为示意。

寿命算账

这不只是理论上的别扭。ZeRO-Infinity 确实把训练时的参数和优化器状态放到 NVMe 上,以此在有限的 GPU 上训练超大模型14。但如果 30B 模型用 Adam 训练,FP32 主权重和两份动量每个参数 12 字节,每一步都要重写 366 GB。三星 990 PRO 2 TB 款的标称写入寿命是 1,200 TBW15,够写约 3,300 步。预训练一个大模型动辄几十万步,这块盘撑不过开头。

闪存适合“写一次、读很多次”

反过来,只读的推理正是闪存擅长的。按 JEDEC 的规定,消费级 SSD 即使用完了标称寿命,断电放在 30°C 下数据也要能保持一年16;新盘的保持时间还要长得多。长期反复读同一块数据,会因为读干扰让邻近单元慢慢偏移,但控制器会定期把数据刷新到新位置3。

所以对“能不能在盘上学习”的回答是:可以写,但每次更新都是整页搬迁,写入寿命经不起训练的消耗。“固化”这个词其实很准确:在 GPU 上训练好,把参数一次写进盘里,以后只读。顶多再挂一个很小的 LoRA 适配器,只更新这一小部分参数。

既然盘最适合“训练完写一次、以后只读”,那要把 30B 固化到盘上,模型应该长成什么样?


六、适合固化在盘上的模型结构

前面几节提出的要求

把前面的结论收拢一下,一个适合放在盘上的模型应该满足四点:

  1. 按地址读,而不是按内容搜(第二节)。内容到地址的换算由处理器来做,盘只负责“给地址、还一块”。
  2. 每个 token 读得少(第三节)。读盘量决定速度。
  3. 地址要早知道(第三节)。机械硬盘每次随机读要等 12 ms,NVMe 也有几十微秒的延迟,越早知道要读什么,越能把等待藏在计算后面。
  4. 参数训练好以后不再改(第五节)。

MoE 满足前两点的一部分:每个 token 只读 0.91 GB。但它的路由器要用当前层的隐藏向量来选专家,要读哪些专家,直到这一层开始算之前才知道,没有提前预取的余地。

记忆层与 Engram:把查表做成模型的一层

另一类结构直接把“查表”做成了模型的一层。2019 年的乘积键记忆层(Product Key Memory)给 Transformer 加了一张最多十亿参数的大表,每个 token 只按键取出其中几行;加了这一层的 12 层模型,效果超过了 24 层的基线,推理还快一倍17。2024 年 Meta 把这种记忆层扩到了 128B 参数,在计算量相当时,效果超过了计算量多一倍以上的稠密模型,也超过了计算量和参数量都相当的 MoE,在事实类任务上提升尤其明显18。

2026 年初 DeepSeek 发表的 Engram 更进一步19。它把经典的 N-gram 嵌入现代化:取当前位置前面的几个 token 组成 N-gram,用几个哈希函数算出它在一张大嵌入表里的行号,取出那几行,再由一个门控根据当前隐藏向量决定用多少。论文把 Engram 扩到 27B 参数,在总参数量和计算量都相同的条件下超过了纯 MoE 的基线。

对盘来说,Engram 最关键的性质是:行号只取决于输入的 token,不取决于隐藏向量。前向计算一开始,甚至在它开始之前,就知道要读哪些行,可以提前取。论文的实验是把一张 100B 参数的表整个放在主机内存里,通过 PCIe 预取,8B 骨干的吞吐只降了 2.8%。论文还指出,N-gram 的出现频率服从 Zipf 分布,常用的少数行可以缓存在显存或内存里,长尾放到 NVMe SSD 上19。

把 Engram 式的嵌入表放在裸盘上 当前位置的 2-gram“能 像”和 3-gram“硬盘 能 像”经过哈希,分别得到嵌入表的行号 7,301,442 和 912,077。如果一行正好 4 KiB,行号就是 LBA。行号只取决于输入的 token,第 1 层还在计算时就能向盘发出读请求,取回的嵌入在第 2 层经过门控加进隐藏状态。 GPU / 内存:骨干网络 裸盘:嵌入表(只读) 当前位置的 N-gram 输入:… 硬盘 能 像 2-gram能 像哈希 → 行 7,301,442 3-gram硬盘 能 像哈希 → 行 912,077 合计每阶 4 个哈希头,共 8 行 第 1 层计算中,同时预取 第 2 层 · Engram 门控 第 3 层 … 取回的嵌入 行号只取决于输入的 token,第 1 层还在算时, 读请求就可以发给盘了。 嵌入表 行 912,077LBA 912,077 行 7,301,442LBA 7,301,442 一行2048 维 × 16 位 = 4 KiB … 一行正好一个扇区,行号就是 LBA。 每个 token:8 行 × 4 KiB = 32 KiB。 尺寸和行号均为示意,不是论文的配置。
图 7 · 记忆层把“按内容找”拆成两半:处理器把 N-gram 哈希成行号,盘按行号还回一个扇区。地址在计算开始前就已知,读盘的等待可以藏在前几层的计算后面。

这正好满足了上面的四点要求:按地址读,每个 token 只读几行,前向一开始就知道地址,表训练好以后不再改。分工也随之清楚了:留在内存或显存里的是一个较小的骨干网络,放到盘上的是那张大表。按图 7 的示意,每个 token 从盘上只读几十 KB,比 MoE 的 0.91 GB 小四个数量级。不过要说明:论文实测的是主机内存,长尾放在 SSD 上只是论文提出的方向;表放在裸盘上能跑多快,是本文的推断,还没有人测过。

有意思的是,engram 这个词在神经科学里,指的正是一段记忆在大脑里留下的物理痕迹。

固化的另一端:把参数做成电路

如果把“固化”推到极致,就是连盘也不要了,直接把参数做成电路。Taalas 在 2026 年 2 月发布的 HC1 芯片,把 Llama 3.1 8B 硬连线进了硅片,采用 3 位和 6 位混合量化,单用户能跑到每秒 17,000 个 token;参数本身不能改,只保留了上下文长度的配置和 LoRA 微调20。在这里,存储和计算彻底合成了一件事,和突触最像,代价是一个芯片只能是一个模型。

把这几种“固化”的程度放在一起比较:

“固化”的几种程度
方式参数在哪谁来计算速度(例)能不能改
权重文件文件系统里,用前整个加载进内存或显存CPU / GPU取决于内存带宽随时替换
裸盘平铺,按需读盘上,按偏移量寻址CPU / GPU 边读边算Qwen3-30B-A3B 在 NVMe 上约 8 token/s(本文估算的上限)重写盘即可
闪存内计算专用闪存芯片的单元里闪存片上 + NPUCambricon-LLM:70B 3.44 token/s能重新编程,受写入寿命限制
硬连线芯片电路本身电路本身Taalas HC1:Llama 3.1 8B 17K token/s不能改,只能挂 LoRA
表 3 · 参数和计算靠得越近,速度越快,能改的余地也越小

七、回到那块写满权重的盘

现在可以回答开头的问题了。那块 dd 过的盘上,确实存着 30B 个“突触”:每个 QLC 单元的精度和一个突触差不多,断电一年也不会丢。但它记住这些数的方式,是图书馆的方式,不是大脑的方式:

  • 它只能按地址取,不能按内容回忆;错一位的线索,什么也找不回来。
  • 坏掉的扇区整块丢失,不会“大致记得”。
  • 它不会自己用这些数做任何计算,“回忆”要靠处理器完成。

要让这块盘真正派上用场,有三条路:

  • NVMe 加 MoE,处理器边读边算,Qwen3-30B-A3B 每秒能出几个 token。今天就能做,llama.cpp 用 mmap 加载模型,其实就是让操作系统替你做这件事,只不过中间隔着文件系统。
  • 在闪存芯片里计算,让单元的电荷直接参与乘加。这已经接近一个突触阵列,但要专门的芯片,不是买来的 SSD。
  • 换一种模型结构,像 Engram 那样把知识放进一张按 token 寻址的大表,让盘只做它最擅长的事:给地址,还一块。

至于在盘上学习,闪存单向写、整块擦的特性和有限的写入寿命,决定了它只适合训练好以后写一次。“固化”这个词,恰好描述了盘能做的事。


小结

从一块写满权重的裸盘出发,我们一路追问到了:

  1. 裸盘上的参数是什么形态? 一个按偏移量寻址的大数组,适合按层、按专家平铺。往下一层,一个 QLC 单元约存 4 位,和一个突触约 4.7 比特的精度很接近,但控制器的加扰和页编码把“一个值对应一个单元”打乱了。
  2. 盘算不算“记住”了? 它有突触,没有神经元。按地址读取,错一位就找不回来,坏一块就丢一块;Hopfield 网络按内容回忆,线索错 30% 仍能想起,代价是 20 倍以上的存储和每次回忆都要做矩阵乘法。
  3. 盘只存储、处理器计算,30B 能跑多快? 稠密模型每个 token 要读 15.3 GB,NVMe 上要 2 秒;MoE 只读 0.91 GB,NVMe 上每秒约 8 个 token 的上限,机械硬盘每个 token 要 8 秒以上。
  4. 存储单元能不能就地计算、就地学习? NOR 闪存可以靠欧姆定律和基尔霍夫定律做模拟乘加,SSD 里串联的 NAND 只适合按位运算,要算大模型就得用专门的芯片。闪存只能单向写、整块擦,写入寿命经不起训练,只适合写一次。
  5. 怎样固化 30B 最合适? 选按地址查表、地址只取决于输入的结构,比如记忆层和 Engram;放在 NVMe 上,热的行留在内存里。

如果想自己验证,下面是文中用到的两个脚本,只依赖 NumPy。

第一个是第二节的实验,比较按扇区存和用 Hopfield 网络存(4 核机器上约 8 秒):

Python
"""同样 50 条 1024 位的记忆,分别按“扇区”和按 Hopfield 网络存,比较两件事:
1. 拿一条有噪声的线索去取,能不能取回原来那条;
2. 存储介质坏掉一部分以后,还能取回几条。
"""
import hashlib
import numpy as np
N, P = 1024, 50 # 每条记忆 1024 位,共 50 条
rng = np.random.default_rng(0)
patterns = rng.choice([-1, 1], size=(P, N)).astype(np.int8)
def flip(x, frac, rng):
"""随机翻转 frac 比例的位,模拟一条不完整、有错的线索。"""
y = x.copy()
idx = rng.choice(N, size=int(frac * N), replace=False)
y[idx] *= -1
return y
# ---------- 方式一:按地址存(扇区) ----------
# 用内容的哈希当地址:这是“按内容找”在按地址存储上最直接的做法。
def addr(x):
return hashlib.sha256(x.tobytes()).hexdigest()
disk = {addr(p): p for p in patterns}
sector_of = {addr(p): i for i, p in enumerate(patterns)} # 每条记忆占一个扇区
def disk_recall(cue, dead=frozenset()):
a = addr(cue)
if a not in disk or sector_of[a] in dead:
return None
return disk[a]
# ---------- 方式二:Hopfield 网络 ----------
W = (patterns.T.astype(np.float32) @ patterns.astype(np.float32)) / N # Hebb 规则
np.fill_diagonal(W, 0)
def hopfield_recall(W, cue, steps=20):
s = cue.astype(np.float32)
for _ in range(steps): # 同步更新,直到不再变化
s_new = np.where(W @ s >= 0, 1.0, -1.0)
if np.array_equal(s_new, s):
break
s = s_new
return s.astype(np.int8)
def exact(out, p):
return out is not None and np.array_equal(out, p)
print(f"N={N} 位/条, P={P} 条")
print(f"扇区方式占用: {P * N} 位; Hopfield 权重: {N * N} 个")
print()
print("实验一:线索有噪声(不坏介质)")
print("噪声比例 扇区:完整取回 Hopfield:完整取回 Hopfield:平均每条对的位数")
for noise in [0.0, 0.01, 0.05, 0.10, 0.20, 0.30, 0.40]:
r = np.random.default_rng(1)
cues = [flip(p, noise, r) for p in patterns]
d = sum(exact(disk_recall(c), p) for c, p in zip(cues, patterns))
outs = [hopfield_recall(W, c) for c in cues]
h = sum(exact(o, p) for o, p in zip(outs, patterns))
acc = np.mean([np.mean(o == p) for o, p in zip(outs, patterns)])
print(f"{noise:>6.0%} {d:>4}/{P} {h:>4}/{P} {acc:.2%}")
print()
print("实验二:介质坏掉一部分(扇区用干净线索;Hopfield 用 10% 噪声的线索)")
print("损坏比例 扇区:完整取回 Hopfield:完整取回 Hopfield:平均每条对的位数")
for dmg in [0.0, 0.10, 0.30, 0.50, 0.70, 0.80, 0.90]:
r = np.random.default_rng(2)
# 扇区:坏掉的扇区整块读不出来(ECC 纠不回来时,盘返回的是读错误)
dead = frozenset(r.choice(P, size=int(dmg * P), replace=False).tolist())
d = sum(exact(disk_recall(p, dead), p) for p in patterns)
# Hopfield:随机剪断 dmg 比例的“突触”(权重置零,保持对称)
mask = r.random((N, N)) >= dmg
mask = np.triu(mask, 1); mask = mask | mask.T
Wd = W * mask
cues = [flip(p, 0.10, r) for p in patterns]
outs = [hopfield_recall(Wd, c) for c in cues]
h = sum(exact(o, p) for o, p in zip(outs, patterns))
acc = np.mean([np.mean(o == p) for o, p in zip(outs, patterns)])
print(f"{dmg:>6.0%} {d:>4}/{P} {h:>4}/{P} {acc:.2%}")

第二个是第三节的读盘实验。先 write 把 8 层专家按文中的布局写进去,再 read 测顺序读和 MoE 模式的读,并折算到 48 层。目标可以是一个普通文件,也可以是一块空盘的裸设备(会覆盖上面的数据):

Python
"""把一个 MoE 模型的专家权重平铺到裸盘(或一个大文件)上,再按“生成一个 token”的访问模式读回来,
测每个 token 要在 I/O 上花多少时间。
布局照 Qwen3-30B-A3B:每层 128 个专家,每个专家 3 个 768×2048 的矩阵,
4 位量化后正好 2,359,296 字节 = 576 个 4 KiB 扇区。专家 (layer, e) 放在
offset = (layer * 128 + e) * 2,359,296
没有文件系统,地址就是偏移量。
用法:
python3 disk_stream.py write /path/to/target --layers 8
python3 disk_stream.py read /path/to/target --layers 8 --tokens 20
target 可以是 /dev/nvme1n1 这样的裸设备(会覆盖上面的数据,需要 --i-know-this-erases),
也可以是普通文件。读写都用 O_DIRECT,绕过页缓存,测的是盘本身。
"""
import argparse, mmap, os, sys, time
import numpy as np
EXPERTS, TOPK, FULL_LAYERS = 128, 8, 48
EXPERT_BYTES = 3 * 768 * 2048 // 2 # 4 位量化:两个参数一个字节
assert EXPERT_BYTES % 4096 == 0
def offset(layer, e):
return (layer * EXPERTS + e) * EXPERT_BYTES
def open_direct(path, write):
flags = (os.O_RDWR | os.O_CREAT) if write else os.O_RDONLY
return os.open(path, flags | os.O_DIRECT, 0o644)
def cmd_write(a):
if a.target.startswith("/dev/") and not a.i_know_this_erases:
sys.exit("写裸设备会覆盖上面的数据,确认后加 --i-know-this-erases")
fd = open_direct(a.target, True)
buf = mmap.mmap(-1, EXPERT_BYTES) # mmap 出来的内存按页对齐,O_DIRECT 需要
rng = np.random.default_rng(0)
t0 = time.perf_counter()
for layer in range(a.layers):
for e in range(EXPERTS):
buf[:] = rng.integers(0, 256, EXPERT_BYTES, dtype=np.uint8).tobytes()
os.pwritev(fd, [buf], offset(layer, e))
os.fsync(fd)
dt = time.perf_counter() - t0
total = a.layers * EXPERTS * EXPERT_BYTES
print(f"写入 {total / 1e9:.2f} GB,用时 {dt:.1f} s,{total / dt / 1e6:.0f} MB/s")
def cmd_read(a):
fd = open_direct(a.target, False)
buf = mmap.mmap(-1, EXPERT_BYTES)
rng = np.random.default_rng(1)
# 1) 顺序读:稠密模型每个 token 要把全部权重扫一遍,就是这种模式
total = a.layers * EXPERTS * EXPERT_BYTES
t0 = time.perf_counter()
for i in range(a.layers * EXPERTS):
os.preadv(fd, [buf], i * EXPERT_BYTES)
seq = total / (time.perf_counter() - t0)
print(f"顺序读:{seq / 1e6:.0f} MB/s")
# 2) MoE 模式:每层随机挑 8 个专家,每个专家是一次 2.36 MB 的读
lat = []
for _ in range(a.tokens):
t0 = time.perf_counter()
for layer in range(a.layers):
for e in rng.choice(EXPERTS, TOPK, replace=False):
os.preadv(fd, [buf], offset(layer, int(e)))
lat.append(time.perf_counter() - t0)
per_layer = np.median(lat) / a.layers
moe_bytes = a.layers * TOPK * EXPERT_BYTES * a.tokens
print(f"MoE 读:{moe_bytes / sum(lat) / 1e6:.0f} MB/s,每层 {per_layer * 1e3:.1f} ms")
print(f"折算到 {FULL_LAYERS} 层:每个 token 读 {FULL_LAYERS * TOPK * EXPERT_BYTES / 1e9:.2f} GB,"
f"I/O 约 {per_layer * FULL_LAYERS:.2f} s,上限 {1 / (per_layer * FULL_LAYERS):.2f} token/s")
dense = 30.5e9 / 2
print(f"对照:稠密 30B(4 位,{dense / 1e9:.1f} GB)按顺序读速度,每个 token {dense / seq:.1f} s")
p = argparse.ArgumentParser()
p.add_argument("cmd", choices=["write", "read"])
p.add_argument("target")
p.add_argument("--layers", type=int, default=8)
p.add_argument("--tokens", type=int, default=20)
p.add_argument("--i-know-this-erases", action="store_true")
a = p.parse_args()
cmd_write(a) if a.cmd == "write" else cmd_read(a)

参考资料

Footnotes

  1. Qwen3-30B-A3B config.jsonHugging Facehuggingface.co ↗48 层,每层 128 个专家,每个 token 选 8 个,专家中间维度 768,隐藏维度 2048。模型页给出的总参数量是 30,532,122,624(BF16)。https://huggingface.co/Qwen/Qwen3-30B-A3B/blob/main/config.json ↩ ↩2 ↩3

  2. safetensorsGitHub · Hugging Facegithub.com ↗文件格式:8 字节的头长度,一段 JSON 头(每个张量的 dtype、shape、data_offsets),后面是连续的原始字节。https://github.com/huggingface/safetensors ↩

  3. Error Characterization, Mitigation, and Recovery in Flash Memory Based Solid-State DrivesYu Cai, Saugata Ghose, Erich F. Haratsch, Yixin Luo, Onur Mutlu · Proceedings of the IEEE 105 · 2017arxiv.org ↗多级单元的页编码、单元间干扰、读干扰、数据加扰、按页编程按块擦除等,都可以在这篇综述里找到。https://arxiv.org/abs/1706.08642 ↩ ↩2 ↩3 ↩4 ↩5

  4. Nanoconnectomic upper bound on the variability of synaptic plasticityThomas M Bartol Jr 等 · eLife 4:e10778 · 2015elifesciences.org ↗大鼠海马突触大约能区分出 26 档强度,约合 4.7 比特。具体数字凭领域知识整理,发文前可再核对原文。https://elifesciences.org/articles/10778 ↩

  5. Neural networks and physical systems with emergent collective computational abilitiesJ. J. Hopfield · PNAS 79(8) · 1982doi.org ↗https://doi.org/10.1073/pnas.79.8.2554 ↩

  6. Storing infinite numbers of patterns in a spin-glass model of neural networksDaniel J. Amit, Hanoch Gutfreund, H. Sompolinsky · Physical Review Letters 55 · 1985doi.org ↗Hopfield 网络的容量约为 0.138N。凭领域知识整理,发文前可再核对。https://doi.org/10.1103/PhysRevLett.55.1530 ↩

  7. Transformer Feed-Forward Layers Are Key-Value MemoriesMor Geva, Roei Schuster, Jonathan Berant, Omer Levy · EMNLP 2021arxiv.org ↗https://arxiv.org/abs/2012.14913 ↩

  8. Hopfield Networks is All You NeedHubert Ramsauer 等 · ICLR 2021arxiv.org ↗连续状态的现代 Hopfield 网络,其更新规则与 Transformer 的注意力等价。https://arxiv.org/abs/2008.02217 ↩

  9. LLM in a flash: Efficient Large Language Model Inference with Limited MemoryKeivan Alizadeh 等 · ACL 2024arxiv.org ↗窗口化(windowing)和行列捆绑(row-column bundling),能跑比 DRAM 大一倍的模型,比朴素加载在 CPU 上快 4–5 倍、GPU 上快 20–25 倍。https://arxiv.org/abs/2312.11514 ↩

  10. PowerInfer-2: Fast Large Language Model Inference on a SmartphoneZhenliang Xue 等 · arXiv · 2024arxiv.org ↗在手机上跑 47B 模型,11.68 token/s。https://arxiv.org/abs/2406.06282 ↩

  11. Sub-1-us, Sub-20-nJ Pattern Classification in a Mixed-Signal Circuit Based on Embedded 180-nm Floating-Gate Memory Cell ArraysF. Merrikh Bayat, X. Guo, M. Klachko, M. Prezioso, K. K. Likharev, D. B. Strukov · arXiv · 2016arxiv.org ↗由商用 180 nm NOR 闪存改造的浮栅阵列,101,780 个浮栅单元当突触,调节精度约 1%,MNIST 94.65%。https://arxiv.org/abs/1610.02091 ↩

  12. Flash-Cosmos: In-Flash Bulk Bitwise Operations Using Inherent Computation Capability of NAND Flash MemoryJisung Park 等 · MICRO 2022arxiv.org ↗多字线同时感应(Multi-Wordline Sensing),在 160 颗真实 3D NAND 芯片上验证。https://arxiv.org/abs/2209.05566 ↩

  13. Cambricon-LLM: A Chiplet-Based Hybrid Architecture for On-Device Inference of 70B LLMZhongkai Yu 等 · MICRO 2024arxiv.org ↗专用 NAND 闪存芯片做闪存内计算,配合 NPU:70B 模型 3.44 token/s,7B 模型 36.34 token/s。https://arxiv.org/abs/2409.15654 ↩

  14. ZeRO-Infinity: Breaking the GPU Memory Wall for Extreme Scale Deep LearningSamyam Rajbhandari 等 · SC 2021arxiv.org ↗训练时把参数和优化器状态卸载到 CPU 内存和 NVMe 上。https://arxiv.org/abs/2104.07857 ↩

  15. Samsung NVMe SSD 990 PRO Data SheetSamsung Semiconductordownload.semiconductor.samsung.com ↗顺序读 7,450 MB/s;写入寿命 1 TB 款 600 TBW、2 TB 款 1,200 TBW,按 JESD218 测试。https://download.semiconductor.samsung.com/resources/data-sheet/Samsung_NVMe_SSD_990_PRO_Datasheet_Rev.1.0.pdf ↩

  16. JESD218: Solid-State Drive (SSD) Requirements and Endurance Test MethodJEDECjedec.org ↗消费级 SSD 在用完标称写入寿命后,断电 30°C 下数据保持 1 年。该页面需要登录,数字凭领域知识整理,发文前可再核对。https://www.jedec.org/standards-documents/docs/jesd218b01 ↩

  17. Large Memory Layers with Product KeysGuillaume Lample 等 · NeurIPS 2019arxiv.org ↗https://arxiv.org/abs/1907.05242 ↩

  18. Memory Layers at ScaleVincent-Pierre Berges 等 · arXiv · 2024arxiv.org ↗https://arxiv.org/abs/2412.09764 ↩

  19. Conditional Memory via Scalable Lookup: A New Axis of Sparsity for Large Language ModelsXin Cheng 等(DeepSeek) · arXiv · 2026arxiv.org ↗Engram:用哈希过的 N-gram 查嵌入表。推理时把 100B 参数的表放在主机内存里,8B 骨干的吞吐只降 2.8%;论文第 2.5 节建议把长尾放到 NVMe SSD 上。https://arxiv.org/abs/2601.07372 ↩ ↩2

  20. The path to ubiquitous AILjubisa Bajic · Taalas · 2026-02taalas.com ↗HC1 把 Llama 3.1 8B 硬连线进芯片,3 位和 6 位混合量化,单用户 17K token/s;保留上下文长度配置和 LoRA 微调。https://taalas.com/the-path-to-ubiquitous-ai/ ↩

延伸阅读