端到端 4 位训练
训练大语言模型需要计算并存储大量数字。对每个数值使用更少的比特,可以减少内存占用,并让 GPU 更快地执行计算。然而,这里存在权衡:比特数越少,也意味着可表示的数字越少,从而需要更激进的舍入。更低精度的表示最终会通过给计算引入误差来损害准确性。
例如,假设我们想存储数字 3.2,但我们的数值格式所能表示的最近值只有 3 和 4。将其舍入到 3 会引入 量化误差 −0.2-0.2−0.2,也就是实际值与量化格式中可表示值之间的差异。单次这样的误差看起来可能很小,但随着训练进行,舍入会在各层和优化步骤中反复发生,这些误差会不断累积,从而损害学习过程。
这正是低精度训练的核心挑战:我们如何在享受更快算术运算的同时,不引入会干扰学习的误差?
我们通过在训练中使用三种关键数值格式来管理这种权衡:BF16、MXFP8 和 NVFP4。每种格式的精度是固定的,但其速度取决于所使用的硬件。我们在 NVIDIA 的 Grace Blackwell Ultra 平台 GB300 上进行训练,该平台专为使用 NVFP4 优化矩阵乘法而设计。值得注意的是,NVFP4 的存储位数比 BF16 少 3.6 倍,但在 GB300 上运行速度最高可达其 6 倍。
| 数值格式数值格式 | 每个值的比特数 | GB300 PFLOPS |
|---|---|---|
| NVFP4 | (4 × 16 + 8) ÷ 16 = 4.5 | 15 |
| MXFP8 | (8 × 32 + 8) ÷ 32 = 8.25 | 5 |
| BF16 | 16 | 2.5 |
GB300 上的 NVFP4 加速在高吞吐推理中非常有用,因为此时权衡更偏向速度。但与 BF16 和 MXFP8 相比,这种格式会大幅增加量化误差。这种误差在训练的不同阶段影响程度不同,因此必须分别考虑各阶段中的权衡:预训练和监督微调(SFT)中的前向与反向传播,以及强化学习(RL)中的采样与训练。
| 我们在训练不同阶段的优先事项 | 风险 | 回报 |
|---|---|---|
| 最小化误差 | 最小化偏差 | 提升速度 |
| 预训练前向传播 | 3 个勾 | — |
| 预训练反向传播 | 1 个勾 | 3 个勾 |
| RL 采样器 | 3 个勾 | — |
| RL 训练器 | 1 个勾 | 3 个勾 |
速度在高吞吐步骤中最为重要:预训练会运行在数万亿 token 上,而 RL 采样则会在每次 rollout 中生成数万个 token。每个采样出的 token 还需要从全局内存中加载模型权重,而这项成本会随着存储权重所需比特数的增加而扩大。
用于更新权重的反向传播会对一个 batch 中的许多 token 求平均,这会稀释随机分布舍入误差的影响。然而,反向传播对量化偏差非常敏感;这种偏差是在量化过程中数值持续向上或向下舍入时引入的。与随机误差不同,这种偏差不会被平均掉,而是可能在层、样本和训练步骤之间不断叠加。
在训练 Inkling 2 Small 时,我们做出了以下决定:
- 在前向传播中,对 expert 层使用 NVFP4 精度,并配合专用 kernel。
- 在反向传播中使用 MXFP8 精度,并采用重新量化与随机舍入等降低梯度偏差的技术。
- 使用量化技术来加速 GPU 间通信,从而缓解我们提升计算速度后暴露出的瓶颈。
据我们所知,Inkling 2 Small 是目前规模最大的、以原生 4 位前向传播 端到端 训练的模型。从预训练开始到最终 RL rollout,我们始终以相同方式配置数值格式。这使训练过程更简单,也消除了在训练结束交付量化 checkpoint 时进行校准的需要。在我们最大的任务中,与完整 MXFP8 训练相比,这套方案在预训练中带来了 8% 的实际墙钟时间加速,在 RL 中带来了 20% 的加速。在本文中,我们将解释使这一切成为可能的细节。
选择量化目标
理想情况下,我们希望在对模型准确性影响最小的地方降低精度,同时又能带来显著的整体加速。最符合这一特征的层是专家混合(MoE)层,因为它们计算开销大,并且从经验上看,相比其他层,在被量化时对准确性的损害更小。
今年早些时候,我们对 MoE 层实现了完整的 MXFP8 训练,发现它几乎不影响模型的计算效率(CE),CE 是衡量引入新技术后训练和评估损失如何变化的指标。Recipes for Pre-training LLMs with MXFP8, Mishra et al., 2025, Scaling Laws for Neural Language Models, Kaplan et al., 2020 然而,我们最初进行的完整 NVFP4 训练实验对模型 CE 造成了非常大的打击,使准确性下降到我们无法接受的程度。
在将 NVFP4 量化对前向和反向传播的影响分离开来后,我们发现,聚焦于前向传播通常能在速度与准确性之间提供更好的权衡。但只量化前向传播会对与反向传播的交互、GPU 通信等方面带来一系列影响。为了理解这些问题,我们先来详细看看 NVFP4 是如何工作的。
Blackwell 上的低精度格式
4 位最多可以表示 16 个不同的值:对于 FP4 来说,这些值是 ±{0,0.5,1,1.5,2,3,4,6}\pm\{0, 0.5, 1, 1.5, 2, 3, 4, 6\}±{0,0.5,1,1.5,2,3,4,6}。显而易见的限制在于无法表示大于 6 的数字,而这个问题通过 块缩放 得到解决:存储一个缩放因子,用它去乘连续块中的所有值。NVFP4 会根据每个由 16 个连续值组成的块中最大的那个值(按绝对值)来缩放整个块。例如,如果该值是 −54-54−54,它会被表示为 −6-6−6,并配上缩放因子 9,而块中的每个值都会基于这个缩放因子进行舍入。
Blackwell GPU 还提供了微缩放(MX)格式,例如 MXFP4 和 MXFP8,它们对每 32 个值组成的块进行缩放。OCP Microscaling Formats (MX) Specification, Rouhani et al., 2023 这些缩放因子所使用的格式也不同:NVFP4 的缩放因子是 E4M3,因此精度更高但范围受限;而 MXFP4/MXFP8 的缩放因子是 E8M0,精度低得多,但能够表示极宽范围的数值。E4M3 表示一种 8 位浮点格式,包含一个隐式符号位、4 个指数位和 3 个尾数位。E8M0 则有 8 个指数位、没有符号位,也没有尾数位。NVFP4 缩放因子提供的更高精度,通常能在 LLM 工作负载中更准确地表示输入数据,因此比 MXFP4 产生更少的量化误差。
下面的工具展示了 NVFP4 的块缩放是如何工作的,以及它如何导致量化误差:本文中的所有图都使用 Inkling 2 Small 制作。
高精度值
96×6=576
量化误差:−17.7
E4M3 缩放因子
0
符号
1101
指数
100
尾数
(−1₂)0₂ × 10₂(1101₂ − 0111₂) × 1.100₂
= 96
E2M1 值
0
符号
11
指数
1
尾数
(−1₂)0₂ × 10₂(11₂ − 01₂) × 1.1₂
= 6
JavaScript 已关闭,因此位、字段框和公式显示的是预先计算好的示例(593.7 → 96 × 6 = 576),不会随编辑变化。
一个由 FP4 数字和 FP8 缩放因子重建出的 NVFP4 值。编辑输入值或单独的比特位即可探索这种表示方式。灵感来自 float.exposed。
FP4 与 FP8 的这种组合使 NVFP4 能表示低至 2−102^{-10}2−10、高至 2688 的数值幅度。实际中,我们往往需要表示超出这一范围的值,因此 NVFP4 通常还会配合第二层外部缩放因子使用,这个因子以 FP32 保存,并作用于一个非常大的值组,例如整个张量。这样,每个量化值都可以被重建为 xiFP4×xi//16FP8×xFP32x^{\text{FP4}}i \times x^{\text{FP8}}{i//16} \times x^{\text{FP32}}xiFP4×xi//16FP8×xFP32,这实际上允许我们将可表示范围整体上移或下移。例如,将 xFP32x^{\text{FP32}}xFP32 设为 2,会把可表示幅度范围从 [2−10,2688][2^{-10}, 2688][2−10,2688] 移到 [2−9,5376][2^{-9}, 5376][2−9,5376];将其设为 0.5 则会向相反方向移动。
块缩放反向传播
网络中的一次前向传播会将量化后的激活与量化后的权重相乘: y=xqwqTy = x_q w_q^Ty=xqwqT。使用 NVFP4 计算点积时,会从 xqx_qxq 的一行和 wqTw_q^TwqT 的一列中各取 16 个值组成块,将对应值相乘,然后再将求和结果乘以各自块的缩放因子。
为了计算反向传播,我们需要对前向传播中的张量进行转置: dx=gwqdx = g w_qdx=gwq 和 dw=gTxqdw = g^T x_qdw=gTxq。此时,块会从 xqx_qxq 的 列 和 wqTw_q^TwqT 的 行 中各取 16 个值:每个值会与另外 15 个不同的邻居分组,从而得到不同的缩放因子和不同的量化表示值。下图展示了将块缩放从按行切换为按列所带来的影响,在这个例子中,这会导致绝大多数值被舍入为零。
1×16 缩放因子16×1 缩放因子
高精度
0141664
一个 16×16 的高精度数据 tile
NVFP4
0141664
256 个值中有 256 个保留下来:每个行组都适配自己的缩放因子
大行被保留下来:19 个小值也被保留下来;其余 221 个被舍入为零
**保留的值 **大值 **被舍入为零 **缩放因子分组
JavaScript 已关闭——切换功能需要它;上方显示的是预先计算好的 1×16 分组视图。
对一个包含整行大值的相似 tile 进行量化。为每一行使用单独的 1×16 缩放因子可以保留所有值;而改为每一列使用 16×1 缩放因子时,大值所在行会决定每一列的缩放因子,导致大多数小值被冲刷为零。纵轴采用对数尺度,并放大了小值差异。
这会在前向和反向传播所使用的张量之间造成不匹配,从而导致梯度计算不准确。对于权重张量,NVIDIA 提出了一个直接的解决方案:他们不是为每个 1×16 块计算缩放因子,而是基于每个 16×16 方形 tile 中的最大值计算单一缩放因子,从而在张量转置时保持缩放因子不变。Pretraining Large Language Models with NVFP4, NVIDIA et al., 2025; also see the FP8 formulation in DeepSeek-V3 Technical Report, DeepSeek-AI et al., 2024.
这种方法的主要缺点是,它可能导致大量数值下溢。将块大小从 16 个值增大到 256 个值后,它会对离群值变得高度敏感:256 个值中只要有一个特别大的值,就可能把缩放因子抬高,导致其余值都被舍入为零。
1×16 缩放因子16×16 缩放因子
高精度
0141664
一个 16×16 的高精度数据 tile
NVFP4
0141664
256 个值中有 241 个保留下来:离群值所在的 1×16 分组周围被舍入为零
只有离群值被保留下来:所有其他值都被舍入为零
**保留的值 **大值 **被舍入为零 **缩放因子分组
JavaScript 已关闭——切换功能需要它;上方显示的是预先计算好的 1×16 分组视图。
对一个包含单个大离群值的 tile 进行量化。为每个 1×16 分组使用单独缩放因子,相比对整个 16×16 tile 使用单一缩放因子,能减少小值的损失。纵轴采用对数尺度,并放大了小值差异。
我们尝试过这种方法,但最终发现基于 16×16 tile 计算缩放因子过于粗糙,对 CE 的损害超出了我们愿意接受的范围。要让 NVFP4 训练可行,我们需要在使用 1×16 缩放因子量化权重的同时,避免块缩放转置所引入的不匹配。
使用随机舍入的重新量化
使用 16×16 tile 可以通过让前向和反向传播之间的表示在比特级完全一致来消除不匹配—— wq=(wqT)Tw_q = (w_q^T)^Twq=(wqT)T——但严格的完全一致其实并非必要。真正重要的要求是,前向和反向传播中使用的张量在 期望意义上 相等: E[wq]=E[(wqT)T]E[w_q] = E[(w_q^T)^T]E[wq]=E[(wqT)T]。保持期望不变可以解决反向传播中的偏差问题,而放宽对比特级相等的约束,则为前面提出的转置问题提供了几种不同的解决思路。
我们选择了一个直接的方案:将前向传播中的张量反量化,在更高精度下转置,然后使用 随机舍入(SR)重新量化。与标准量化(也称为最近值舍入量化)不同,SR 会根据每个值到相邻可表示值的距离,以反比概率将其向上或向下舍入。
例如,假设前向传播张量中有一个值 5.4,它是在缩放因子为 9 的块中量化的。5.4 除以 9 等于 0.6,这会被舍入到最近的 FP4 值 0.5。因此,前向传播中使用的量化值是 4.5,而这正是我们希望在反向传播中(在期望意义上)恢复的值。
我们可以先将这个值反量化,使其以高精度表示,但在反向传播中,这个值现在会被分到另一个块里。假设它的新缩放因子为 2。如果我们用 NVFP4 重新量化,4.5÷2=2.254.5 \div 2 = 2.254.5÷2=2.25 现在需要被量化到 FP4。确定性舍入会将其表示为 2,因此量化值为 2⋅2=42 \cdot 2 = 42⋅2=4。而随机舍入则会有四分之三的概率将其舍入为 2,有四分之一的概率将其舍入为 3(即它上方最近的邻居)。这样,前向传播中的 4.5 在重新量化后仍能在期望意义上得到保留: 2scale⋅(0.75⋅2+0.25⋅3)=4.52_{\text{scale}} \cdot (0.75 \cdot 2 + 0.25 \cdot 3) = 4.52scale⋅(0.75⋅2+0.25⋅3)=4.5。关键在于,随机舍入在 Blackwell GPU 上同样有硬件加速支持。
在设计这一方法时,我们借鉴了 TetraJet-v2 和 Quartet II,它们也会对前向传播中的张量进行重新量化。TetraJet-v2: Accurate NVFP4 Training for Large Language Models with Oscillation Suppression and Outlier Control, Chen et al., 2025, Quartet II: Accurate LLM Pre-Training in NVFP4 by Improved Unbiased Gradient Estimation, Panferov et al., 2026 直接对反量化后的值应用 SR 的一个好处是,它让我们可以在重新量化时自由选择任意精度。我们发现,将权重和激活以随机舍入方式重新量化到 MXFP8,然后使用 MXFP8 矩阵乘法计算梯度,能在准确性和速度之间提供最佳权衡。
从第 i − 1 层BF16激活按 token 量化到带 4/6 的NVFP4FPROPNVFP4 GEMM到第 i + 1 层按 expert 量化到NVFP4FP32权重反量化转置以 SR 量化到MXFP8反量化转置以 SR 量化到MXFP8DGRADMXFP8 GEMMWGRADMXFP8 GEMM优化器到第 i − 1 层从第 i + 1 层BF16梯度以 SR 量化到MXFP8转置以 SR 量化到MXFP8
FP32BF16MXFP8NVFP4
我们的量化线性层:前向传播中使用 NVFP4 计算,反向传播中使用 MXFP8 计算,并在对保存的激活和权重重新量化时采用随机舍入。
量化通信
有了新的 NVFP4 矩阵乘法(GEMM)后,理论上我们的 MoE 层前向传播相较于 MXFP8 实现应该快大约三倍。但在降低精度之后,我们注意到自己碰到了一个瓶颈:expert 并行中的通信。
由于 MoE 层通常非常大,因此常见做法是将 experts 分散到不同 GPU 上。在计算 MoE 层时,一个小型路由器会决定每个 token 应该送往哪里,然后 token 会被 分发 到包含相应 expert 的 GPU 上。完成 GEMM 后,这些被路由 expert 的计算结果会返回源 GPU,并被 合并 以形成 MoE 层的最终输出。在 NVIDIA GB300 NVL72 系统上,这些 token 通常会通过 NVLink 传输,其双向带宽均为 900 GB/s。与此同时,NVFP4 GEMM 的运行速度最高可达 15 PFLOPS。将两者相除可知,每块 GPU 在接收 1 个字节所需的时间内,最多可以执行 16,000 次浮点运算。除非每个到达的字节都携带至少这么多计算量,否则 Tensor Core 就会空转,等待 NVLink。
我们发现,这种失衡造成了瓶颈:要么 MoE GEMM 因等待接收分发来的 token 而无法执行,要么后续操作(在 Inkling 2 Small 中是短卷积)因等待接收合并后的 token 而无法启动。在 dispatch 阶段,我们通过以 NVFP4 格式分发 token 来避免这个问题。与 TetraJet-v2 和 Quartet II 一样,我们的反向传播使用的是前向传播中量化后的激活,而不是高精度激活(见图 4 中权重梯度,即 WGRAD 计算的输入),这减少了通过 NVLink 发送的数据量,从而足以缓解 dispatch 瓶颈。然而,在 combine 阶段,输出激活需要保持较高精度(默认是 BF16),以避免损害模型性能。
我们通过对 combine 阶段传输的数据也进行量化来缓解通信瓶颈。我们最初尝试将结果激活量化为 MXFP8,但发现由于 MXFP8 对离群值的表示能力较差,这会对性能造成过大损害。后来我们发现,先执行一个 32 维随机 Hadamard 变换(RHT),再量化到另一种 8 位格式——块缩放 S2F6——在训练中不会带来可测量的准确性下降。
16 位 combine8 位 combine
Dispatch计算CombineDispatchw13Qw2w13Qw2w13Qw2CombineCombineCombineExpert Wave 1Expert Wave 2Expert Wave 3
- Dispatch all-to-all
- w13 GEMM
- 量化
- w2 GEMM
- Combine all-to-all
JavaScript 已关闭——当前显示的是 16 位 combine;切换功能需要 JavaScript。
细粒度重叠与 expert 波次,类似于 DeepSeek-V4。DeepSeek-V4: Towards Highly Efficient Million-Token Context Intelligence, DeepSeek-AI et al., 2026 在 combine 期间对数据进行量化,通过缩短图右侧 combine 的尾部来加速 MoE。
RHT 会施加一种旋转,倾向于让输入数据更加平滑。当输入数据包含离群值时,这可以减少量化误差。已有研究表明,在低精度下,整数格式往往比浮点格式更能准确表示经过 RHT 变换后的数据。INT v.s. FP: A Comprehensive Study of Fine-Grained Low-bit Quantization Formats, Chen et al., 2025, Bridging the Gap Between Promise and Performance for Microscaling FP4 Quantization, Egiazarian et al., 2025 S2F6 是一种定点格式,包含 2 个带符号整数位和 6 个小数位,能够表示从 −128/64-128/64−128/64 到 127/64127/64127/64 的线性插值值,与整数格式非常相似。下图展示了 Hadamard 变换如何平滑输入数据,使我们能够使用更小的缩放因子进行量化,从而减少量化误差。
播放正在播放…重播
高精度数据
RHT 之后
−500−2500250500−500−2500250500
值离群值(|v| ≥ 200)
随机 Hadamard 变换会在保持总能量不变的同时,让数值分布得更均匀;并且由于它是正交变换,之后可以精确求逆以恢复原始数据。红点标出了变换前属于离群值的那些数值。
方便的是,Blackwell GPU 包含专门的 PTX 指令,可高效地在带 FP8 缩放因子的块缩放 S2F6 与其他格式之间进行转换:cvt.rn.dst.src 表示从 src 到 dst 的数据类型转换。更多细节请参见 PTX ISA。
cvt.frnd2.satfinite{.relu}{.scaled::n2::ue8m0}.s2f6x2.f32
d, a, b{, scale-factor};
cvt.frnd2.satfinite{.relu}{.scaled::n2::ue8m0}.s2f6x2.bf16x2
d, a{, scale-factor};
cvt.rn{.satfinite}{.relu}{.scaled::n2::ue8m0}.bf16x2.s2f6x2
d, a{, scale-factor};
这使我们能够为这种数据类型实现非常高效的 kernel。在每块 GPU 上计算完 MoE 输出后,我们会在 w2 分组 GEMM 的 epilogue 中高效计算 RHT,并量化到块缩放 S2F6,每 32 个值使用一个缩放因子。在数据接收过程中,它会被即时反量化并聚合,之后再对 RHT 求逆。这样就将 combine 阶段传输的数据量从每个值 16 位降到了每个值 8.25 位,缩短了 combine 尾部,并如图 5 所示加速了 MoE 层。
低精度训练的 kernel
要充分发挥 NVFP4 的优势,需要专门的 kernel,而这些 kernel 是我们围绕低精度方案自主开发的。我们的 MoE 融合 kernel 栈代号为 BBBK,即 Big Beautiful Blackwell Kernel。它在保持完全确定性计算的同时,以峰值硬件利用率支持训练和推理。
计算 MoE 层的过程通常主要由矩阵乘法主导。我们使用 GB300 独有的最大 2SM UMMA 指令(K=96)来榨满 Tensor Core,并配合一个 6 级乘数流水线和一个 7 级缩放因子流水线。然而,我们的精度方案也对 GPU 的算术逻辑单元(ALU)提出了很高要求。即使 Tensor Core 已经饱和,kernel 仍可能在 ALU 密集步骤上停顿,例如计算缩放因子、重新量化权重、应用随机舍入以及合并数据传输。
为了消除这些停顿,BBBK 会尽可能让更多硬件流水线同时保持饱和。例如,我们将 RHT 和 S2F6 量化直接融合进 w2 GEMM 的 epilogue。更广泛地说,我们将激进的 epilogue 融合与 ALU 向量化、指令调度、寄存器规划与打包,以及推测式 megakernel 调度结合起来。在训练中,BBBK 能同时榨满 NVLink、ALU 和 Tensor Core;而在 RL 采样中,它达到了由 NVLink 和 HBM 决定的延迟下限。
方案细节
为了完善我们的方案,我们还借鉴了其他一些关于 NVFP4 训练的现有工作。我们将最后 16.6% 的层保留在更高精度下,并用 MXFP8 而不是 BF16 来计算。NVIDIA 的方案将这一比例设为 15%,但在我们的预训练阶梯中,层数按 6 倍缩放,因此将比例设为 ⅙ 在我们的设置中很合适。在量化激活时,我们使用 Four Over Six(4/6),这是一种在 NVFP4 量化过程中在两个缩放因子之间进行选择、以减少量化误差的技术。Four Over Six: More Accurate NVFP4 Quantization with Adaptive Block Scaling, Cook et al., 2025; also see Ziang Li’s writeup for a nice explanation of the technique. 在量化权重时,我们不使用 4/6。
受 Composer 2 启发,我们在量化权重时使用按 expert 的外部缩放因子,在量化激活时使用按 token 的外部缩放因子,从而实现更高效率、batch 不变性,并且无需担心因果性泄漏。Composer 2 Technical Report, Cursor et al., 2026 在我们最大的训练任务中,这套方案在 SFT 和 RL 阶段都无需修改即可工作。在预训练 Inkling 2 Small 时,它会带来约 2% 的计算效率损失,也就是说,与使用 MXFP8 训练相比,模型若采用 MXFP8 训练,大约可以用少 2% 的 FLOPs 达到同样的损失;而作为交换,我们获得了 NVFP4 带来的速度提升。在 RL 中,收益则大得多:端到端速度显著提升,而奖励没有可辨别差异。
结束思考
十年前,人们还不清楚神经网络是否能使用少于 32 位的参数进行训练:直到 2020 年,默认格式仍然是 FP32,而 BF16 也是在那时才随着 Ampere 架构首次进入 NVIDIA GPU。NVIDIA Ampere Architecture In-Depth, Krashinsky et al., 2020 如今,我们常常把 BF16 称为“高精度”,并且已经找到了使用 8 位甚至 4 位格式进行训练的稳健应用场景!我们受到 NVIDIA 前瞻性硬件设计的启发,正是这些设计让上述进展成为可能。我们将继续向前推进:我们正在积极探索能够让反向传播也使用 FP4 计算的方案,以及我们的方案将在 NVIDIA 最新的 Vera Rubin 系统上如何演进。
我们在预训练和后训练两个阶段的加速,来自科学与工程上一系列改进的共同作用,这些改进触及整个技术栈的每一个部分,并彼此叠加。几个月前,一个与 Inkling 2 Small 规模相近的模型训练任务还需要数周时间;而 Inkling 2 Small 在 GB300 NVL72 机架上仅用 68 小时就完成了预训练。我们的数值方案只是这些众多改进中的一部分,而且我们仍在持续迭代它。
我们在每一次实验和训练运行中都在学习新的经验,也期待在未来的文章中与大家分享更多内容。
引用
请按如下方式引用本工作:
Cook, Jack and Thinking Machines Lab, "End‑to‑End 4‑Bit Training",
Thinking Machines Lab: Connectionism, Nov 2026.
或者使用以下 BibTeX 引用:
@article{cook2026lowprecision,
author = {Jack Cook and Thinking Machines Lab},
title = {End‑to‑End 4‑Bit Training},
journal = {Thinking Machines Lab: Connectionism},
year = {2026},
note = {https://thinkingmachines.ai/blog/end-to-end-4-bit-training/},
}