康奈尔-ECE5545-机器学习硬件系统笔记-全-
康奈尔 ECE5545 机器学习硬件系统笔记(全)
机器学习硬件与系统:001:课程介绍 🎯

在本节课中,我们将学习《机器学习硬件与系统》这门课程的整体框架、学习目标、评估方式以及核心动机。我们将了解为什么在算法之外,硬件和系统对于机器学习的实际应用至关重要。
课程概述与动机
欢迎来到《机器学习硬件与系统》课程。这是本课程首次开设。我作为康奈尔理工学院的新助理教授,这也是我首次授课。希望我能通过这门课程,让大家对机器学习硬件与系统感到兴奋。
核心思想在于,虽然我们常听到人工智能、深度学习和机器学习正在改变世界,但其实际运行依赖于硬件、系统以及我们将在本课程中学到的优化技术。在计算机科学中,你可能学过算法层面的课程,但如何让算法在计算机上实际运行,以及如何构建运行这些算法的计算机,正是我们在这里要尝试学习的。
让我分享一个简单的动机案例。2013年,谷歌的一些顶尖工程师发现,如果用户每天仅使用三分钟的深度学习语音识别服务,谷歌就需要将其数据中心容量翻倍。这意味着需要建造两倍于现有规模的庞大基础设施。
这告诉我们两件事:
- 这类应用的计算负载非常沉重。
- 现有的数据中心架构并不适合这类应用。
因此,谷歌的工程师们没有选择扩建数据中心,而是设计了一款定制芯片,即TPU。通过重新思考运行这些程序的硬件,他们在语音识别这一特定工作负载上实现了10到100倍的性能提升。相比现有的CPU和GPU,他们无需扩建数据中心,只需将新芯片置入现有设施即可满足需求。


课程核心内容
为了让这样的芯片发挥作用,涉及的远不止硬件设计。本课程将涵盖以下四个主要方面:
1. 硬件架构 🖥️
大约四分之一的课程将专注于硬件架构。我们将学习如何分析现有硬件、比较不同硬件对特定工作负载的适用性,以及如何设计高效的硬件架构。我们也会浅层涉及微架构(如何构建执行实际数学运算的电路)以及这类芯片的内存设计。
2. 系统 🚀
课程名为“机器学习硬件与系统”,因此我们也将讨论系统层面。一旦有了单颗芯片,如何将它们组合起来以分布式方式训练深度神经网络?分布式训练对于当今的超大规模模型至关重要。我们还将探讨联邦学习,这是一种具有安全隐私保障的分布式学习方式,例如如何利用手机数据安全、私密地训练神经网络。此外,我们也会讨论神经网络前后的预处理与后处理系统,以及这些系统对环境的影响和碳足迹问题。
3. 神经网络优化 🧠
仅孤立地讨论硬件和系统是不够的,因为软件和算法层面也有大量工作。在神经网络层面,我们将讨论如何实现高效的、针对特定硬件目标优化的神经网络。具体技术包括:
- 量化:在神经网络中使用更低的数值精度。
- 剪枝与稀疏化。
- 知识蒸馏等技术。
- 自动化机器学习,特别是神经架构搜索,即如何找到最适合特定硬件的最佳神经网络拓扑结构。
4. 软件 💻
没有软件的硬件只是一块砖头。我们将学习如何为我们构建的新芯片编程。这部分将重点讨论专为深度学习涌现的领域特定语言和编译器。虽然也存在针对计算机视觉等其他应用的DSL和编译器,但我们将关注更通用、不局限于单一领域或模态的深度学习任务。
讲师与助教介绍
我是穆罕默德·阿卜杜,康奈尔大学电气与计算机工程系的新助理教授。我的背景主要在硬件架构领域,曾在英特尔参与构建基于FPGA的首个深度学习加速器(涉及硬件、软件、编译器),之后在三星英国AI中心工作,专注于自动化机器学习以及为三星手机创建高效机器学习模型。我将尽力在课程中传递这些工业界的实践经验。
我很荣幸有助教杨光道(康奈尔理工学院三年级博士生,计算机视觉专家)协助,他将主要帮助处理作业,特别是那些涉及较多部分的作业。
此外,在课程准备阶段,还得到了Rebecca、Z、She、Yaoki和Alan的帮助,他们协助设计了作业和编程部分。
课程先修要求与教材
先修知识
- 计算机架构基础:我们将选择与深度学习加速器相关的主题进行深入。如果你对此毫无了解,可能需要与我沟通。
- 机器学习基础:你应该上过机器学习入门课程,了解基本概念,实际训练并运行过神经网络,最好熟悉PyTorch并编写过代码。
教材
我们将使用教材《Efficient Processing of Deep Neural Networks》,并在课程中阅读大量论文。该教材可通过康奈尔大学在线图书馆获取PDF版本。

课程评估方式
本课程的评估侧重于学期中的作业和项目:
- 作业(占比最大):共有五次作业,每次都是一个迷你项目。
- 作业0:熟悉设计工具和编程工具(2分)。
- 作业1:聚焦硬件,进行硬件基准测试和研究,学习使用屋顶图。
- 作业2:训练和优化神经网络模型,并将其部署到微控制器单元上进行测试。
- 作业3:聚焦软件编译,使用TVM工具。
- 作业4:实现和对比不同的深度学习算子(如卷积)算法,并观察其在不同硬件目标上的运行情况。

-
期末论文(20%):自选主题,对至少10篇相关研究论文进行批判性评估。
-
课堂报告(10%):10分钟报告,讲解一篇或两篇论文,最好与期末论文主题相关。

- 每周论文总结(5%):每周提交不超过半页的论文摘要,需涵盖指定问题。

- 课堂参与(5%):鼓励课堂互动、提问和贡献想法。
额外奖励:作为首次开课,如果你发现讲义或作业材料中的重大错误(非拼写错误),或纠正课程内容中的错误,将获得加分。
课程技术栈与哲学
技术平台
- 课程网站:包含所有重要链接(Zoom、讨论区、GradeScope)。
- GitHub Classroom:用于发布和提交作业代码。
- Google Colab:用于编码作业,提供方便的GPU访问环境。建议从作业2开始购买Colab Pro(每月10美元),以方便后台模型训练。
- GradeScope:用于提交作业报告和每周论文总结。
课程哲学
- 紧跟前沿与研究导向:课程需要保持最新状态,我们将讨论论文,你需要课后阅读以跟上领域发展。
- 实践性:作业包含大量动手编码,因为这是一个非常应用的学科。
- 趣味性:作业设计力求有趣,可能还会举办一两次竞赛。
学术诚信
禁止作弊和抄袭代码。允许与同学讨论想法,但直接复制代码是不可接受的。我们将使用工具检查作业代码和文本的抄袭情况。
深度学习简介:为何需要专用硬件与系统?
深度学习的特殊性
深度学习是机器学习的一个子集,而深度神经网络是其中的主流技术。本课程虽名为“机器学习硬件与系统”,但实际聚焦于深度学习硬件与系统。
深度学习之所以特殊,是因为它在众多领域取得突破:
- 推荐系统(如亚马逊、谷歌、Netflix)。
- 计算机视觉(如自动驾驶、图像分割)。
- 语音识别(已可部署于手表等小型设备)。
- 自然语言处理(如翻译、文本生成,甚至在法律文档自动化等领域应用)。
这些应用都依赖于硬件来运行。例如,手机中的“神经引擎”、特斯拉的FSD芯片、亚马逊的定制AI芯片、谷歌的TPU Pod等,都说明了专用硬件和系统对于深度学习发展至关重要。
深度学习的历史与复兴
深度神经网络并非新概念,早在20世纪40年代就已提出,80年代已有成功应用(如LeNet用于MNIST)。那么,为何在2012年(AlexNet出现)才迎来爆发?
关键原因有二:
- 大数据:互联网和移动设备产生了海量训练数据。
- GPU:Alex Krizhevsky发现如何用GPU编程神经网络,GPU的并行计算特性完美匹配了深度学习的需求。
自此,AI研究和产业投资呈指数级增长。这不仅是学术热点,更是获得巨额投资的现实技术。
案例深入:语音识别系统
考虑一个语音识别系统(如“Hey Google”):
- 手机端:语音数据预处理(如生成频谱图)。一个关键挑战是如何在手机端本地高效运行神经网络,以节省数据中心成本和功耗,并保障用户数据隐私(这引出了联邦学习)。
- 数据传输:数据传至数据中心的过程本身也可能涉及基于AI的通信协议(如信道编码、压缩)。
- 数据中心端:面临与手机端类似但规模更大的硬件、软件、分布式训练等问题。
- AI税:神经网络前后的预处理和后处理同样重要,常被忽视。
这个案例展示了在硬件、系统、神经网络、软件每个层面进行优化的必要性和紧迫性。
各专题的紧迫性
硬件:后摩尔定律时代
摩尔定律(晶体管数量每两年翻倍)和登纳德缩放定律(功耗密度恒定)曾让我们免费获得性能提升。但约在2008年后,登纳德缩放定律失效,晶体管微小化导致漏电和发热严重,功耗密度飙升。这意味着我们无法再单纯依靠制程进步来获得更快芯片。
因此,我们必须转向架构创新,设计领域特定架构,将晶体管专门用于深度学习等特定任务,从而提升效率。硬件架构研究正因此迎来复兴。
神经网络:巨大的优化空间
比较五年前的VGG16和现在的EfficientNet等网络,在计算量(FLOPs)和模型大小上出现了数个数量级的缩减,同时精度还有所提升。这得益于量化、剪枝、神经架构搜索等技术。我们在三星进行超分辨率网络优化时,仅应用这些技术就实现了30倍的计算量减少。神经网络拓扑和计算组织方式的优化潜力巨大。
软件:百花齐放的生态
涌现出大量专为深度学习设计的领域特定框架、语言和编译器(如图中众多Logo)。理解其背后的概念和必要性至关重要。
系统:分布式与隐私保护
- 分布式训练:如何跨多台机器分割数据或模型进行协同训练,涉及梯度同步、参数更新等复杂问题。
- 联邦学习:如何在保护用户隐私的前提下,利用分散在亿万设备上的数据进行学习,是一个日益重要的研究方向,既有隐私安全考量,也有经济因素(将计算负担转移到用户设备)。
课程安排与总结
课程将按以下顺序进行:
- 硬件
- 神经网络优化
- 软件
- 系统
这样安排是为了让大家首先建立硬件为中心的思维方式。

本节课总结:
我们一起学习了《机器学习硬件与系统》课程的总体介绍。我们了解了课程的核心动机:在算法突破的背后,专用硬件和高效系统是深度学习得以实际应用和持续发展的关键驱动力。我们明确了课程将涵盖硬件架构、神经网络优化、软件栈以及分布式系统四大板块,并清楚了课程的评估方式、先修要求和技术平台。最后,我们通过历史回顾和案例分析,深刻认识到学习本课程内容在当今后摩尔定律时代和AI普及化背景下的重要性与紧迫性。
机器学习硬件和系统:002:DNN计算概述与核心层分析 🧠

在本节课中,我们将学习如何从计算和内存的角度理解深度神经网络。我们将建立一个简单的“DNN计算机”心智模型,分析前向传播与反向传播的计算/内存开销,并探讨常见神经网络层的计算特性。
第一部分:DNN计算机的心智模型 💻
上一节我们介绍了课程的基本信息,本节中我们来看看如何为运行深度神经网络建立一个简单的计算机心智模型。
冯·诺依曼架构与瓶颈
在计算机体系结构中,一个普遍使用的模型是冯·诺依曼架构(或称普林斯顿架构)。其核心组件包括:
- 中央处理单元:包含控制单元和算术逻辑单元。
- 外部存储单元:存储程序和数据。
- 低带宽总线:连接CPU和外部内存。
该架构的瓶颈在于冯·诺依曼瓶颈:计算单元必须通过低带宽总线从外部内存加载数据和指令,这通常成为性能的主要限制。
为了缓解此瓶颈,现代计算机采用了多种技术:
- 在芯片上集成大容量缓存,将数据预加载到计算单元附近。
- 针对机器学习,新兴芯片设计趋向于领域专用架构,例如构建没有外部内存的大芯片,或将计算单元嵌入内存中(即存内计算)。
内存受限 vs. 计算受限
评估一个工作负载时,关键要判断它是内存受限还是计算受限。
- 内存受限:从外部内存获取数据所需的时间,超过了在芯片上进行计算的时间。此时,即使增加计算单元,也无法提升整体速度。
- 计算受限:计算本身所需的时间,超过了数据加载的时间。此时,内存总线可能处于空闲状态。
一个高效的硬件设计应尽可能重叠内存访问与计算,以充分利用所有资源。
片上内存与双缓冲

由于片上内存容量远小于外部内存(通常相差数个数量级),高效管理片上内存至关重要。一种常见技术是双缓冲(或称乒乓缓冲):
- 当使用缓冲区A中的数据执行当前层计算时,同时通过总线将下一层所需的数据预取到缓冲区B中。
- 计算完成后,交换缓冲区角色,实现计算与数据加载的重叠。
重要概念:在GPU上遇到“CUDA out of memory”错误时,通常意味着模型参数、训练数据和中间激活值无法全部放入GPU的显存(即外部内存)中,而非片上缓存。

第二部分:前向传播与反向传播 🔄
上一节我们建立了硬件的基本心智模型,本节中我们来分析神经网络训练过程中两个核心阶段的计算与内存特性。

计算开销对比

以一个简化的神经元为例,考察一次乘法和激活操作:
- 前向传播:执行一次乘法操作。
- 反向传播:为了计算梯度,需要应用链式法则,大约涉及两次乘法操作。
因此,反向传播的计算量大约是前向传播的2倍。参数更新(如梯度下降)通常只涉及廉价的加法/减法操作,开销相对较小。
内存开销对比
在训练过程中,内存开销主要来自存储中间激活值以用于反向传播的梯度计算。
- 理论上,前向传播和反向传播需要存储的值数量大致相同(前者存激活值,后者存梯度值)。
- 然而,训练时需要同时存储前向的激活值用于反向计算,因此峰值内存占用约为单纯推理时的两倍。
为了节省内存,可以采用模型检查点技术:只存储部分层的激活值,在反向传播需要时,根据存储的检查点重新计算中间激活值。这是一种用计算时间换取内存空间的典型权衡。
第三部分:常见神经网络层分析 🧱
上一节我们分析了训练流程的整体开销,本节中我们深入看看构成现代神经网络的几种核心层的计算与内存特性。
以下是几种关键神经网络层的对比分析:
| 层类型 | 核心操作 | 计算量 (FLOPs) 示例 | 参数量 | 通常属于 | 特点 |
|---|---|---|---|---|---|
| 标准卷积 | 滤波器与输入块的点积 | 2 * H * W * C * R * S * K |
R * S * C * K |
计算受限 | 参数复用性高,计算密集。 |
| 深度可分离卷积 | 逐通道卷积 + 逐点卷积 | 显著少于标准卷积 | R * S * C + C * K |
趋向平衡 | 高效网络基础,大幅减少计算量。 |
| 全连接/线性层 | 矩阵-向量乘法 | 2 * (输入维度) * (输出维度) |
(输入维度) * (输出维度) |
内存受限 | 参数量大,复用性低。可通过批处理转为计算受限。 |
| 自注意力层 | Q, K, V 的矩阵乘与缩放点积 | 与输入令牌数的平方相关 | 相对较少 | 通常计算受限 | Transformer核心,序列建模能力强。 |


复合层与数据依赖
现代网络由上述基础层组合成更复杂的块,如ResNet的残差块、MobileNet的倒残差块、Inception块等。这些块中的跳跃连接会引入数据依赖,影响片上内存的调度策略:需要将跳跃连接的数据在内存中保留更长时间,以供后续分支使用。
循环神经网络(如LSTM)具有更复杂的层内和跨时间步的数据依赖,这使得其在GPU等并行架构上的优化更具挑战性。
注意力机制与Transformer
注意力机制,特别是Transformer中使用的缩放点积注意力,已成为NLP、语音和视觉领域的基石。其核心公式如下:
Attention(Q, K, V) = softmax(Q * K^T / sqrt(d_k)) * V
其中Q(查询)、K(键)、V(值)均是输入的线性投影。尽管注意力机制功能强大,但其计算量随输入令牌数呈平方级增长。因此,如何高效地近似或优化注意力计算是当前的研究热点。


总结 📝
本节课中我们一起学习了:
- 建立心智模型:将DNN计算机抽象为计算单元、片上内存和外部内存,并通过冯·诺依曼瓶颈理解数据搬运的关键性。
- 分析训练开销:认识到反向传播的计算量约为前向传播的2倍,而训练的内存峰值约为推理时的2倍。
- 剖析核心网络层:理解了卷积层通常是计算受限的,而全连接层常是内存受限的,并了解了通过批处理、深度可分离卷积等技术进行权衡。
- 认识现代架构:了解了注意力机制的基本原理以及Transformer如何通过自注意力层和全连接层组合构成。

掌握这些从计算和内存角度分析神经网络的能力,是设计高效硬件和系统的重要基础。在接下来的课程中,我们将学习具体的硬件度量和设计技术,以应对这些计算与内存的权衡挑战。
机器学习硬件和系统:003:硬件分析指标与性能模型

在本节课中,我们将深入学习设计深度神经网络加速器时涉及的重要硬件和计算机架构概念。我们将从分析硬件性能的指标开始,逐步深入到用于评估芯片性能的屋顶线模型,并探讨如何优化硬件以获得更高的效率。
课程概述与回顾
上一讲我们开始构建硬件加速器的思维模型,主要基于冯·诺依曼架构。这意味着我们有一个计算单元、一个内存单元,它们通过一条低带宽总线连接,这通常被称为冯·诺依曼瓶颈。我们通过添加片上内存来绕过这个瓶颈,让数据更接近计算,并尽可能重叠内存访问和计算。
我们还从计算视角审视了重要的神经网络原语,讨论了卷积、全连接层等组件的内存与计算需求,并简要介绍了注意力机制和更复杂的模块。上一讲的目的不是穷举所有原语,而是改变我们看待这些原语的视角。
今天,我们将思考如何重新设计计算机芯片以专门用于机器学习或深度神经网络。我们将从用于评估芯片的分析和指标开始,然后讨论如何针对深度学习工作负载优化硬件效率,最后通过一些现有或正在开发的芯片案例研究来巩固理解。
硬件分析:性能指标
首先,我们需要了解如何衡量一个芯片在深度学习工作负载上的速度。

计算性能:FLOPS 与 OPS

我们常提到 FLOPS,它代表 每秒浮点运算次数。这是指硬件每秒能执行的浮点运算数量。在深度学习推理中,常使用降低的数值精度(如8位整数),此时则使用 OPS(每秒运算次数)。

另一个常见指标是 MAC/s(每秒乘加运算次数)。因为点积是我们最基本的计算单元,一次乘加运算通常等于两次浮点运算。因此,峰值 MAC/s 通常是峰值 FLOPS 的一半。
重要概念:芯片通常标称的是 峰值 FLOPS/OPS。这是假设芯片100%利用率时能达到的理论上限。在实际工作负载中,由于各种因素,几乎无法达到峰值性能。
计算每秒运算次数的公式为:
运算次数/秒 = 时钟频率 (Hz) × 处理单元数量 × (1 / 每运算所需周期数)

其中,处理单元 可以理解为能并行执行乘法运算的单元数量。
内存性能:容量与带宽
除了计算,内存同样关键。
- 内存容量:指连接到加速器的外部内存能存储多少数据。对于需要大模型的训练任务,内存容量不足会成为瓶颈。现代GPU通常有数十GB的内存。
- 内存带宽:指数据从外部内存传输到芯片的速度,通常以 GB/s 衡量。这是决定数据供给计算单元速度的关键指标。GPU的内存带宽远高于CPU。
在我们的简化模型中,我们主要关注外部内存。实际上,系统还有复杂的存储层次结构,包括缓存、暂存器和寄存器等。
核心分析工具:屋顶线模型
将计算和内存性能结合起来的主要分析工具是 屋顶线模型。它对于计算密集型任务(如深度学习)的评估和设计非常有用。
屋顶线图的 X轴 是 运算强度,这是应用程序的属性,而非硬件属性。它表示 每字节内存访问所能完成的运算次数。对于一个神经网络层,运算强度 = 总运算次数 / 总内存访问量(包括参数和激活值)。
屋顶线图的 Y轴 是 性能,即在特定硬件上实际达到的运算速度(如 FLOPS)。

屋顶线图由两条线构成:
- 斜线部分(内存带宽限制):当运算强度较低时,性能受限于从外部内存读取数据的速度。这条斜线的斜率等于硬件的 内存带宽。
- 水平线部分(计算性能限制):当运算强度足够高时,性能受限于芯片的 峰值计算性能。
两条线的交点称为 平衡点。在此点,内存带宽和计算性能达到完美匹配。

屋顶线模型的应用
假设我们有一个神经网络工作负载,其运算强度落在图中A点。从A点向上画垂直线,它与屋顶线相交于斜线部分,这表明该工作负载是 内存瓶颈 的。
如何加速一个内存瓶颈的应用?
- 使用更快的内存芯片:提高内存带宽,使斜线变得更陡峭,可能将工作负载转变为计算瓶颈。
- 改变工作负载本身:例如,使用更低的数值精度。这不会改变运算次数,但减少了需要加载的字节数,从而提高了运算强度(工作负载在X轴上右移),可能使其进入计算瓶颈区域。
相反,如果一个工作负载是计算瓶颈的(如B点),则需要提升芯片的峰值计算性能,例如通过增加处理单元数量或提高时钟频率。
实际性能与理论峰值
实际上,达到的性能点通常低于屋顶线。原因包括:
- 内存访问效率低:非连续的内存访问无法有效合并,无法达到峰值带宽。
- 计算利用率低:计算单元未被充分利用(例如,通道数不是处理单元数量的整数倍)。
- 控制流开销:尽管神经网络控制流简单,但仍可能存在数据或控制冲突导致的停顿。
在作业1中,你将实际绘制和分析不同硬件上的屋顶线,以深入理解这些概念。

硬件效率优化技术

从CPU到专用加速器,我们追求更高的能效。研究表明,在CPU上执行一次加法运算,绝大部分能量消耗在指令缓存、寄存器访问、控制逻辑等“开销”上,实际加法器消耗的能量微乎其微。

如何提升硬件效率?以下是几种关键技术方向:


1. 算术优化:分摊开销

核心思想是:用一次“开销”执行更多的计算。
- 专用指令集:从单次加法,到融合乘加,再到4元素点积指令,最后到 矩阵乘法指令。例如,GPU的Tensor Core和Google TPU的矩阵乘法单元,能在单个指令/周期内完成16x16甚至256x256的矩阵运算,极大地分摊了控制开销。
- 趋势:工业界正朝着更粗粒度的操作单元发展,将整个神经网络层(如卷积)作为单个指令来执行。
2. 内存优化:利用数据局部性
对于内存瓶颈的应用,关键在于 数据复用 和 数据局部性。
- 数据复用:确保数据被加载到片上后,在被替换出去之前被多次使用(例如,一个权重被用于计算多个输出)。
- 数据局部性:通过巧妙的硬件数据流设计,使计算需要的数据总是存放在离计算单元最近的位置(如寄存器或片上缓存中)。
3. 跳过无效操作
如果运算结果无效(例如乘以0),理想情况下应跳过该运算以节省能耗和计算资源。如何高效地检测并跳过稀疏网络中的无效操作,是当前深度学习硬件研究的一个开放问题。
4. 模型优化
通过改变神经网络模型本身来更好地适配硬件,例如:
- 减少运算量:设计更高效的网络架构(如从VGG到EfficientNet)。
- 调整拓扑结构:使数据流更符合硬件的并行模式。
这些属于算法-硬件协同设计范畴,将在后续课程中详细讨论。
总结
本节课我们一起学习了评估和优化机器学习硬件的基础知识。
我们首先介绍了关键的硬件性能指标:计算性能 和 内存性能。然后,我们深入探讨了强大的分析工具——屋顶线模型,它揭示了工作负载的运算强度如何与硬件的内存带宽和峰值计算能力相互作用,从而确定性能瓶颈所在。

最后,我们概述了提升硬件效率的几种主要技术:通过 更粗粒度的指令分摊开销、优化内存访问以利用 数据局部性、探索 跳过无效操作 的方法,以及进行 模型优化。



理解这些概念是分析和设计高效深度学习加速器的基石。在接下来的课程中,我们将运用这些知识,深入分析一些具体的现代机器学习硬件架构案例。
机器学习硬件和系统:004:硬件效率(下)
在本节课中,我们将继续探讨如何提升机器学习硬件的效率。我们将重点介绍通过控制数值格式与精度、优化内存访问以及跳过无效计算这三种核心方法来提升能效。


上一节我们介绍了屋顶线模型,它结合了硬件峰值性能与工作负载的计算强度,帮助我们判断应用是受限于内存带宽还是计算能力。本节中,我们将深入探讨提升硬件效率的具体技术。
数值格式与精度优化
提升硬件效率的第一个关键技术是控制数值格式和精度。传统上,科学计算和深度学习通常使用浮点数(如FP32),因为它能提供宽广的动态范围和足够的精度。
一个FP32数由1个符号位、8个指数位和23个尾数位组成,其数值表示为:(-1)^s * (1.m) * 2^(e-127)。

然而,人们发现深度学习模型通常不需要如此高的精度。降低精度可以显著减少硬件(尤其是乘法器)的面积和能耗,因为乘法器的电路规模通常与位数的平方成正比。

以下是几种常见的低精度格式:
- FP16:使用5位指数和10位尾数。与FP32相比,其乘法器面积和能耗大幅降低。
- INT8/INT16:使用纯整数或定点数表示,仅包含尾数部分(无指数)。其动态范围有限(例如有符号INT8的范围是-128到127),但计算能效极高。
从FP32量化到INT8,在乘法运算上能带来巨大的能效提升。一个关键问题是:为何浮点数加法比整数加法昂贵得多?这是因为浮点数加法需要先对齐两个操作数的指数(通过移位尾数),然后才能进行尾数相加,最后可能还需要规格化结果。这个对齐和规格化的过程需要复杂的硬件(如桶式移位器、多路复用器),远超出简单整数加法器的成本。
内存访问优化
提升硬件效率的第二个关键技术是优化内存访问。我们必须认识到,在能耗方面,数据搬运的成本远高于计算本身。
下图清晰地展示了不同操作的近似能耗。访问一个32位数,即使是从片上SRAM读取,其成本也可能高于进行两个32位数的乘法。随着内存容量增大或访问片外DRAM,这个成本会急剧上升。

因此,优化内存访问至关重要,主要策略有以下两点:
- 提升数据局部性:尽量让数据靠近计算单元。现代处理器采用分层存储结构(寄存器 -> 片上缓存/SRAM -> 片外DRAM),越靠近计算单元,存储容量越小,但带宽越高,访问延迟和能耗也越低。目标是将数据尽可能保留在层次结构的顶端。
- 提高数据复用率:一旦数据被加载到靠近计算单元的位置,应尽可能多次使用它,以分摊数据搬运的能耗开销。
数据复用主要有两种类型:
- 时间复用:同一处理单元(PE)多次使用同一数据。
- 空间复用:同一数据被广播到多个处理单元(PE)同时使用。
复用的有效性可以用“复用距离”来衡量。复用距离越小,意味着数据被重用的间隔越短,对缓存或寄存器容量的压力越小,也越有可能避免重复从低速内存中加载数据。
基于复用的思想,产生了“数据驻留”的设计模式,即在计算过程中,将一种类型的数据长时间保留在PE中。主要有三种模式:
- 权重驻留:权重存储在PE中,输入数据流经PE进行计算。这在卷积层中很有效,因为同一滤波器权重需要与大量输入数据相乘。
- 输入驻留:输入数据存储在PE中,权重数据流经PE。这在批大小为1的全连接层等场景中可能有用。
- 输出(部分和)驻留:部分和结果累积在PE中,输入和权重数据流经PE。这是脉动阵列等数据流架构的常见模式。
计算架构类型:SIMD与数据流
硬件架构大致可分为两类,它们以不同的方式组织计算和数据流:
SIMD(单指令多数据):这是GPU的经典模式。一个控制单元向多个ALU广播同一条指令,所有ALU对不同的数据执行相同的操作。数据通常通过一个大型的共享寄存器文件进行交换和同步。
数据流/空间架构:这种架构类似于MISD(多指令单数据)。计算操作在空间上布局,数据像流水一样依次流过这些处理单元。一个PE产生的结果可以直接作为下一个PE的输入,无需写回中央寄存器。脉动阵列是数据流架构的典型代表,广泛应用于TPU等AI加速器。
在脉动阵列进行矩阵乘法时,输入矩阵A的行和矩阵B的列分别从阵列的左侧和顶部流入。每个PE执行乘加运算,并将部分和累积在本地,同时将输入数据传递给相邻的PE。在这种模式下,输出(部分和)是驻留的,而权重和输入都在移动。
跳过无效操作
提升硬件效率的第三个关键技术是跳过无效操作,即利用模型中的稀疏性。
深度学习模型中的稀疏性主要分为两类:
- 激活稀疏性:由于使用ReLU等激活函数,会产生大量零值。
- 权重稀疏性:通过剪枝、正则化等技术,可以将不重要的权重置零。
然而,要高效利用稀疏性在硬件上跳过计算,并非易事:
- 细粒度稀疏性:零值随机分布在张量中。要跳过这些零值,需要复杂的索引和门控逻辑,开销很大。例如,即使有50%的稀疏性,由于元数据和控制逻辑的开销,实际获得的加速比可能远低于理想的2倍,通常只有1.1-1.2倍。
- 块稀疏性:零值以规整的块(如8x8)形式出现。这是更硬件友好的稀疏模式。只需一个额外的比特来标识整个块是否为零,开销极小(约1.6%),控制逻辑简单,可以轻松跳过整个块的计算,从而获得显著的能效和性能提升。
总结
本节课我们一起学习了提升机器学习硬件效率的三种核心方法:
- 降低数值精度:通过量化(如从FP32到INT8)大幅降低计算能耗,尤其是乘法运算。
- 优化内存访问:通过提升数据局部性和复用率,降低能耗占比最高的数据搬运成本。数据驻留(权重、输入或输出驻留)是重要的设计模式。
- 利用稀疏性:跳过对零值的无效计算以提升效率。块稀疏性因其硬件友好性,比细粒度稀疏性更实用、高效。

理解这些基础技术,是分析和设计高效机器学习硬件系统的关键。
机器学习硬件和系统:005:机器学习硬件 III(案例研究)📊

在本节课中,我们将学习如何将之前讨论的硬件效率原则应用于实际案例。我们将分析来自行业和初创公司的多种机器学习加速器芯片,了解它们的设计选择、优化策略以及面临的挑战。
上一节我们介绍了算术优化、内存优化和稀疏性等硬件效率概念。本节中,我们来看看这些概念在真实芯片设计中的具体应用。
压缩稀疏列格式
在深入案例研究之前,我们先补充一个关于稀疏矩阵表示的细节。这是一种常用于稀疏矩阵乘法的特定格式。
以下是其工作原理:
- 压缩稀疏列格式 的核心思想是避免存储矩阵中的所有零值。
- 它通过存储非零值、相对行索引(指示下一个非零元素前有多少个零)和列指针(指示每列开始前有多少个元素)来实现压缩。


例如,对于一个矩阵,我们可以将其表示为:
- 数值数组:
[A, B, C, D, E, F, G, H] - 相对行索引:
[0, 1, 0, 10, 0, 1, 0, 1] - 列指针:
[0, 3, 4, 6, 6]
这种格式的好处包括:
- 节省存储空间:当矩阵中有大量零时尤其有效。
- 便于点积运算:对于需要整行或整列与向量相乘的点积运算,这种格式相对友好,易于构建专用电路来处理。
硬件设计原则总结
遵循教科书指南来设计机器学习芯片,可以总结为以下五点原则:
- 使用专用内存:利用片上内存提高数据的局部性和重用率,最小化数据移动的距离和频率。
- 投资算术单元和内存:移除CPU中复杂的控制逻辑(如预取、指令缓存),将芯片资源用于提供实际计算能力的算术单元和内存。
- 使用匹配领域的并行策略:根据应用特性(如权重固定、输入固定、输出固定)和数据流模式来选择并行架构。
- 减小数据尺寸:通过降低精度、量化等技术来减少数据位宽。
- 使用领域特定编程语言:这有助于更高效地将算法映射到硬件上。
行业案例研究
现在,让我们应用这些原则,分析几个具体的硬件案例。
谷歌张量处理单元
TPU是教科书式应用上述原则的典范。与包含复杂控制单元、缓存等结构的通用CPU核心不同,TPU的设计极度专注于神经网络计算。
其核心设计包括:
- 巨大的矩阵乘法单元:占据了芯片约一半的面积,用于执行大规模乘累加运算。
- 大型片上缓冲区:约24MB,占芯片面积的30%,用于存储权重和激活值,减少访存。
- 极简的控制逻辑:指令非常粗粒度(如“执行256x256矩阵乘法”),因此控制部分占比很小。
这种设计移除了不必要的通用功能,将绝大部分芯片面积用于直接提升神经网络性能的算术和内存单元。
英伟达GPU的演进

GPU是推动现代深度学习革命的关键硬件。近年来,其设计越来越倾向于深度学习加速。

其演进趋势主要体现在:
- 支持更低精度:从仅支持FP32/FP64,到增加对FP16、INT8、BF16等格式的支持,显著提升单位面积算力。
- 引入复杂指令:如
FDP4(4元素浮点点积)指令和张量核心(专用于小矩阵乘法),以分摊控制开销。 - 提升内存带宽:不断增加片外内存带宽,以喂饱更多的计算单元。
- 增强芯片间互联:引入NVLink等高速直连技术,避免通过CPU进行多GPU通信。
- 探索稀疏性支持:例如支持2:4的细粒度稀疏模式,但仍是待完善的开放问题。
这种软硬件协同优化,使得GPU能持续获得显著的性能提升。

其他初创公司案例

除了行业巨头,许多初创公司也提出了有趣的设计。
- Tenstorrent:注重软件灵活性和可编程性。其芯片结合了高效的计算引擎与多个RISC-V核心,通过数据包处理引擎在芯片内灵活移动和压缩数据。
- Groq:采用了一种空间展开架构。它不是将多个相同核心放在芯片上,而是将整个计算数据流图在物理上展开布局到芯片的不同区域。它没有片外内存,完全依赖大型片上SRAM(200MB)和多芯片互联来扩展。
- Untether:强调近内存计算。其设计包含大量片上内存块,专注于最大化内存带宽和降低数据访问能耗。
- Cerebras:以其晶圆级引擎而闻名。他们直接使用几乎整个硅晶圆作为单个芯片,尺寸远超传统GPU。这带来了巨大的片上内存(18GB)和计算核心数量(约40万个),但同时也面临良率、功耗和散热等严峻挑战。他们通过禁用整行/整列有缺陷的核心来简化软件映射。
- 微软Brainwave:采用了一种独特的“线中 bump”架构。他们在数据中心服务器的网络接口卡和CPU之间插入FPGA。数据流经网络时,可被FPGA实时处理后再转发,从而在数据中心内形成一个可编程的硬件加速平面,部署侵入性小。
专用集成电路的成本考量

开发一款专用集成电路成本高昂。研究发现:
- 制造成本(约500万美元)并非最主要部分。
- 最大的成本来自于软件开发,即如何为芯片编写编译器和工具链。
- 硬件设计、EDA工具、IP授权等也占相当比例。
降低这些成本的技术正在发展,例如采用领域特定语言、开源指令集架构、硬件敏捷开发方法以及利用大型FPGA进行原型验证等。
总结



本节课中,我们一起学习了多种机器学习硬件加速器的实际案例。我们从TPU的教科书式设计出发,探讨了GPU为适应深度学习而做的持续演进,并分析了几家初创公司具有创新性的架构选择,如空间展开、近内存计算和晶圆级集成。最后,我们了解了ASIC开发的主要成本构成。通过这些案例,我们应能更好地分析、评论乃至优化未来的机器学习硬件架构。
机器学习硬件和系统:006:微架构设计 🧠



在本节课中,我们将深入探讨机器学习加速器的微架构设计。我们将从构建一个基本的处理单元(PE)开始,然后讨论片上内存的组织方式,最后简要介绍一些新兴的计算范式。通过本节课,你将理解如何设计高效的硬件单元来执行机器学习计算。
构建处理单元(PE)
上一节我们介绍了硬件架构的高层概念,本节中我们来看看如何构建一个具体的处理单元(PE)。PE是执行核心计算(如点积)的基本单元。
点积是卷积和矩阵乘法的基础操作,其公式为:
[
\text{dot_product} = \sum_{i=0}^{n-1} A_i \times B_i
]

一个最简单的PE包含一个乘法器和一个累加器。乘法器用于计算两个元素的乘积,累加器则用于累加这些乘积以得到最终结果。

为了提升性能,我们可以对计算进行并行化(也称为向量化)。以下是构建高效PE的关键步骤:
- 向量化:通过增加乘法器的数量来并行计算多个乘积。例如,使用4个乘法器可以同时计算4对元素的乘积。
- 加法树:为了将多个并行乘法器的输出累加起来,我们需要一个加法树。一个包含
n个输入的加法树大约需要log₂(n)个加法器。 - 累加器:加法树的输出会送入一个累加器,该累加器持有中间状态,并将新的部分和累加到之前的结果上。
一个支持8位整数(int8)推理的PE,其不同部分的精度可能不同:
- 乘法器:通常为int8精度。
- 加法树:可能使用比int8更宽的精度(如int16或int32)。
- 累加器:几乎总是使用更宽的精度(如int32或浮点数),以防止在累加多个数值时发生溢出。
提升PE吞吐量:流水线与交错
仅仅并行化还不够,我们还需要确保PE能够每个时钟周期都启动新的操作,以实现高吞吐量。这涉及到两个关键概念:流水线和交错。
流水线 通过将长延迟操作分解为多个阶段,并在阶段间插入寄存器,使得尽管单个操作完成需要多个周期,但每个周期都可以开始一个新的操作。对于一个完全流水线化的电路,其启动间隔(II)为1。
然而,对于包含反馈循环的电路(如累加器),简单的流水线可能不够。如果累加操作本身的延迟大于1个周期,那么在下一次加法开始前,必须等待当前加法的结果,这会导致停顿。
交错 是解决此问题的方法。通过复制累加器的状态寄存器,我们可以让累加器同时处理多个独立的累加序列。例如,如果累加器延迟为2个周期,我们可以添加一个额外的寄存器,从而交错处理两个不同的点积计算。这样,吞吐量仍可达到每个周期一次操作。
片上内存组织
我们的PE需要快速访问数据(如权重和激活值)。为了匹配PE的高吞吐量,内存系统必须能够每个周期提供足够的数据。

最简单的内存单元是单端口SRAM(一个读端口和一个写端口)。为了同时向多个并行乘法器提供数据,一个直观的想法是增加内存的读端口数量。但这种方法会导致内存面积增大、速度变慢且功耗增加。



更实用的方法是使用 内存分块。我们将一个大内存划分为多个更小、更快的独立内存块(称为“存储体”)。通过一个交叉开关逻辑,我们可以将读写请求路由到正确的存储体。这样,多个存储体可以同时被访问,从而在整体上提供了类似多端口内存的高带宽,同时避免了单一多端口大内存的缺点。
在机器学习加速器中,由于数据访问模式通常较有规律,我们可以显式地管理这些存储体,设计更高效的仲裁逻辑,而不是依赖通用的内存编译器。


新兴计算范式简介
在讨论了传统数字计算架构后,我们简要展望几种与深度学习相关的新兴计算范式。
感内计算:将计算单元直接集成在图像传感器芯片上。这样可以在数据产生的地点立即进行处理,避免了将大量原始图像数据(如数百万像素)传输到处理器所消耗的巨额能量和带宽。这对于只需要图像分析结果(如分类标签)的应用(如机器人视觉)特别有吸引力。
近内存计算:通过3D堆叠或硅中介层等先进封装技术,将计算芯片(如加速器)与多个DRAM芯片紧密集成在一起。这极大地增加了处理器可用的内存带宽,非常适合内存受限的机器学习应用。苹果的M1芯片就采用了类似的封装技术。

存内计算:这是一种更激进的方法,直接在内存阵列中进行模拟计算。例如,将激活值编码为电压,利用内存单元(如SRAM或RRAM)的物理特性执行乘加运算。这种方法可以极大减少数据移动,但面临数字-模拟转换开销大、精度控制复杂等挑战,目前仍处于研究阶段。

总结

本节课中我们一起学习了机器学习加速器的微架构设计。我们从构建一个基本的向量化处理单元(PE)开始,探讨了如何通过流水线和交错技术来最大化其吞吐量。接着,我们了解了如何通过内存分块技术来组织高效的片上内存系统,以满足PE对数据带宽的高需求。最后,我们简要介绍了感内计算、近内存计算和存内计算等新兴范式,它们为未来机器学习硬件的能效提升提供了新的可能性。掌握这些微架构概念,是设计和优化高效机器学习硬件的基础。
机器学习硬件和系统:第6讲:TinyML 🧠

在本节课中,我们将要学习一个与之前截然不同的主题:TinyML。我们将探讨如何在最轻量级的计算硬件上运行机器学习,了解其独特的挑战、应用场景以及相关的软硬件栈。
概述

到目前为止,我们的课程重点一直放在数据中心和用于处理大型工作负载的重型硬件上。然而,今天的课程将转向另一个极端:我们将讨论最轻量级的计算机硬件,以及如何在其上运行机器学习。这项挑战如此之大,以至于人们为它起了一个专门的名字——TinyML。


什么是嵌入式系统?🔌
在深入了解TinyML之前,我们需要先理解什么是嵌入式系统。
嵌入式系统是一种以处理器为核心,但输入来自实际传感器,输出则控制执行器的系统。这与常规计算机不同,常规计算机通常通过以太网、鼠标或键盘等设备进行交互。嵌入式系统被设计成可以与周围环境互动。
以下是嵌入式系统的几个例子:
- 智能手表:其传感器包括加速度计、GPS和心率监测器。它有一个微小的处理器,输出则显示在LCD屏幕上。
- 智能恒温器:输入来自旋转调节、温度和湿度传感器。输出是控制温度的控制信号。
- 日常设备:如电视遥控器、洗衣机、微波炉等,内部都包含微控制器。
什么是TinyML?🤖
TinyML是嵌入式系统与机器学习的结合。人们认为机器学习非常重要,它将成为我们编写软件的新方式,也是理解环境中各种传感器输入的新方法。将机器学习部署到嵌入式系统上,就是所谓的TinyML。


上一节我们介绍了嵌入式系统,本节中我们来看看TinyML与传统机器学习在输入感知上的区别。
感知输入
传统机器学习主要关注两个领域的传感器:麦克风(语音)和摄像头(图像)。此外还有一些其他数据输入,如文本。
对于嵌入式设备,我们拥有更广泛的传感器阵列:
- 我们仍然有语音和图像传感器。
- 我们还拥有惯性测量单元。IMU通常包含加速度计、陀螺仪和磁力计,用于许多应用,如运动检测、计步,甚至可以替代传统传感器(例如,某些耳机在外部环境嘈杂时,会切换到内部的IMU来检测耳内振动以传输声音)。
- IMU等传感器的功耗比小型摄像头低一个数量级,更适合低功耗嵌入式系统。
然而,处理这些嵌入式传感器数据也面临挑战:
- 可解释性:图像和语音数据人类可以直接理解,但IMU等传感器的数据有时更难解读。
- 传感器漂移:随着时间的推移,测量振动、磁性或方向等的传感器可能会性能下降,需要重新校准。
TinyML的处理核心与约束 ⚙️
我们讨论了输入感知,现在让我们谈谈处理部分,这也是在TinyML系统上实现机器学习的主要约束所在。
以下是不同处理设备的尺寸和功耗对比:
- 高端GPU:芯片面积约为数百平方毫米,功耗约为300瓦。
- 手机处理器:芯片面积约为83平方毫米,功耗约为10瓦。
- 智能手表处理器:芯片面积约为30平方毫米。
- 微型微控制器:例如,一款运行在48MHz、具有32KB闪存和20个引脚的ARM MCU,尺寸仅为3.2毫米 x 3.2毫米。与大型GPU相比,它小了约100倍。
这些MCU虽然微小,但数量庞大,无处不在。其使用趋势正在上升,价格低廉(有些低于1美元),预计未来需求会更大。功耗方面,可以从GPU的数百瓦降至MCU的数百微瓦,这使得它们能够使用纽扣电池运行长达一年。
TinyML开发套件介绍 🧰
你们面前都有一套开发套件,我们将用它来完成第二次作业。以下是套件中包含的主要组件:
- 开发板:基于ARM Cortex-M4处理器,具有1MB闪存和256KB RAM。
- 多种传感器:包括颜色、光线、接近、温度、湿度传感器和麦克风。
- 蓝牙模块。
- 摄像头模块:0.3兆像素,可用于形状检测和分类等。
- 扩展板:用于连接MCU板、电源、USB模块、额外按钮、LED和其他外设。
在作业中,我们将主要使用麦克风来实现一个简单的关键词检测应用。该应用将检测几个单词(如“开”、“关”、“音量增”、“音量减”),并根据检测结果点亮不同的LED。
TinyML软件栈 🖥️
了解了硬件之后,本节我们来看看TinyML的软件部分,它也与常规软件有很大不同。
在嵌入式系统上,软件栈通常包括:
- 操作系统:不是Windows、Linux或Android,而是非常简单的专用操作系统,甚至是“裸机”运行(无操作系统)。
- 应用程序与库:例如Arduino软件库。
一个关键的考虑因素是内存使用。在关键词检测应用中,大部分内存用于音频输入缓冲,模型本身也占用一部分,因此需要通过量化、压缩和剪枝等技术使模型尽可能小。此外,还需要为应用程序、库和框架代码预留内存。
我们将使用TensorFlow Lite Micro框架来部署模型。其关键优势包括:
- 与TensorFlow兼容(我们将通过ONNX从PyTorch转换而来)。
- 无需操作系统,可在裸机上运行。
- 设计为可移植到多种平台。
TFLite Micro的工作流程如下:
- 定义模型中实际使用的操作(层),以节省内存。
- 将模型加载到TFLite Micro解释器中。
- 将模型输入(如缓冲的语音数据)复制到输入张量。
- 调用
Invoke函数运行模型。 - 获取模型输出并根据其执行相应操作(如点亮LED)。
模型以FlatBuffer格式(一个字节数组)存储,包含了所有权重、层类型和连接信息。部署步骤是:在PyTorch/TensorFlow中训练模型 -> 转换为FlatBuffer -> 由嵌入式系统上的TFLite Micro解释器加载运行。
内存管理与优化 🧠
我们反复提到要关注内存,这主要是因为MCU具有非常受限的内存限制,并且需要长时间持续运行。
一个关键问题是内存碎片化。在长时间运行且动态分配/释放内存的程序中,即使总空闲内存足够,也可能无法分配一块大的连续内存,导致程序无法运行。
在TFLite Micro中,通过使用张量竞技场来解决这个问题。开发者预分配一个固定大小的缓冲区(竞技场)交给框架,框架在初始化时分配好所有内存,并保证之后不会动态分配,从而避免碎片化并确保内存使用有明确的预算。
如何确定张量竞技场的大小?这取决于模型大小、解释器状态等因素。通常的工程方法是:先分配一个较大的空间,运行程序并分析其实际使用量,然后根据分析结果调整到合适的大小。
模型部署与优化工作流 🔄
最后,我们来概述一下将机器学习模型部署到MCU的完整工作流,这也会在你们的作业中体现。
整个工作流包括以下步骤:
- 数据收集与预处理:收集数据并进行预处理(如对于语音,转换为MFCC谱图)。
- 模型设计与训练:设计神经网络架构并在PyTorch中训练。
- 模型评估与优化:使用剪枝、量化等技术优化模型。
- 模型转换:通过提供的脚本将PyTorch模型转换为TFLite Micro可用的FlatBuffer格式。
- 部署与推理:将模型部署到MCU,并在实际硬件上进行推理。
在关键词检测应用的主循环中,流程如下:
- 麦克风输入:持续从麦克风捕获音频。
- 特征提取:将音频波形转换为MFCC谱图。
- 模型推理:将谱图输入神经网络模型进行分类。
- 输出处理:根据分类结果(如“是”、“否”、“上”、“下”)执行相应动作(如点亮红色或绿色LED)。
总结

本节课中我们一起学习了TinyML的核心概念。我们了解了什么是嵌入式系统和TinyML,探讨了其独特的传感器、微小的处理核心以及严苛的功耗和内存约束。我们介绍了用于实践TinyML的开发套件及其组件,深入研究了TinyML的软件栈,特别是TensorFlow Lite Micro框架的工作原理和内存管理策略。最后,我们概述了从模型训练到部署在MCU上的完整工作流程。TinyML使得在无处不在的微型设备上实现智能成为可能,开辟了机器学习应用的新前沿。
机器学习硬件和系统:008:量化技术详解

在本节课中,我们将要学习神经网络量化技术。量化是一种通过降低数值精度(例如,从32位浮点数到8位整数)来提升模型在硬件上运行效率的核心方法。我们将从基本概念入手,逐步探讨其原理、不同类型、实施细节及其对神经网络的影响。
课程概述与过渡
至此,我们已经完成了本课程硬件模块的学习,探讨了如何为神经网络设计硬件加速器、评估方法以及如稀疏性和低精度等效率技术。从本节开始,我们将转向一系列通用的效率提升技术,这些技术与硬件高度相关,但更侧重于优化神经网络本身的效率,而非硬件设计。首先,我们将深入探讨量化。
什么是量化?🤔
量化是将输入值从一个大的集合(通常是连续的,如实数)映射到一个小的、可数的集合的过程。在深度学习的语境下,这通常意味着从高精度数值格式(如FP32)转换到低精度格式(如INT8)。
核心公式:
对于一个实数 r,其量化值 q 的计算通常遵循以下公式(线性量化):
q = clip(round(r / s) + z, 0, 2^b - 1)
其中:
s是缩放因子(scale)。z是零点(zero point)。b是量化后的比特数。clip是截断函数,确保结果在量化范围内(例如,0到255)。round是取整函数。
反量化(从量化值恢复近似实数值)的公式为:
r' = s * (q - z)
量化并非新概念,在通信等领域已有长期应用。在深度学习中,它主要被重新定义为降低数值精度以提升计算和存储效率的技术。
为什么量化可行?🔍
从FP32(约40亿个可表示数)映射到INT8(仅256个可表示数),表示能力和数值范围都大幅缩减。量化之所以仍然有效,主要基于以下原因:
- 神经网络容忍性:神经网络本身对噪声和精度降低具有一定的鲁棒性。
- 参数分布集中:训练后的网络权重和激活值通常服从一个范围相对有限的分布(例如,类似高斯分布),而非布满整个FP32的理论范围。
- 输入数据范围有限:自然数据(如图像、语音)本身的数值范围就是有界的。
量化中的关键问题 ❓
将量化应用于神经网络时,我们需要考虑一系列设计选择:
- 量化对象:权重(参数)还是激活值(输入/中间结果)?还是两者都量化?
- 量化类型:采用线性量化还是非线性量化?
- 对称性:在线性量化中,使用对称量化(零点
z=0)还是不对称量化(z≠0)? - 训练阶段:是否使用量化感知训练来让模型在训练时就适应量化误差?
- 应用场景:量化主要用于推理阶段以提升效率,但也可用于训练阶段以加速训练过程。
- 误差来源:量化会引入舍入误差和截断误差,如何权衡?
- 量化粒度:是整个网络使用同一套量化参数(每网络),还是每个张量(每张量)或每个通道(每通道)使用不同的参数?

接下来,我们将逐一深入这些问题。

线性量化详解 📐
上一节我们介绍了量化的基本公式,本节我们来详细看看最常见的线性量化。
缩放因子与零点
缩放因子 s 和零点 z 是线性量化的关键。
- 缩放因子
s:决定了实数域中的“步长”。它通过选择的实数范围[r_min, r_max]计算得出:
s = (r_max - r_min) / (2^b - 1)
选择r_min和r_max的方法有多种,例如直接使用最小/最大值,或使用百分位数(如去除离群值后的最小/最大值)。 - 零点
z:表示实数0在量化域中对应的值。其计算公式为:
z = round(-r_min / s)
若z = 0,则为对称量化;否则为不对称量化。
量化误差
量化过程会引入两种误差:
- 舍入误差:由于
round()操作引起,误差范围在[-s/2, s/2]之间。 - 截断误差:由于
clip()操作引起,所有超出[r_min, r_max]范围的实数都会被映射到量化范围的边界值上。

误差权衡:减小量化范围 [r_min, r_max] 可以减小步长 s,从而降低舍入误差,但会增加被截断的数值数量,从而增大截断误差。设计时需要在这两者间取得平衡。

矩阵乘法的量化
了解了基础原理后,我们来看看量化如何应用于神经网络的核心运算——矩阵乘法。
假设我们有权重矩阵 W 和激活矩阵 X,进行浮点运算 Y = W * X。
对 W 和 X 分别进行量化后,我们有:
W_q = quantize(W, s_w, z_w)
X_q = quantize(X, s_x, z_x)
那么,量化后的矩阵乘法近似为:
Y ≈ s_w * s_x * (W_q * X_q) + s_w * z_w * (sum(X_q)) + s_x * z_x * (sum(W_q)) + s_w * s_x * z_w * z_x * n
情况分析:
- 对称量化(
z_w = 0, z_x = 0):公式简化为Y ≈ s_w * s_x * (W_q * X_q)。计算开销很小,只需在整数矩阵乘后乘上一个标量系数。 - 不对称量化:公式包含额外项。通常实践中,对权重使用对称量化,对激活使用不对称量化。这样,
z_w = 0,可以消除公式中与W_q相关的额外项,剩余与X_q相关的项可以合并到网络的偏置(bias)中,从而减少在线计算开销。
量化粒度
量化参数(s, z)的选取可以在不同粒度上进行:
- 每网络:整个网络使用同一套参数。简单但灵活性差。
- 每张量:为网络中每个权重或激活张量单独计算参数。这是常见做法。
- 每通道:为张量的每个通道(例如,卷积层的每个输出通道)计算参数。这能更好地适应数据分布,通常能获得更好的精度,但计算稍复杂。
量化实施策略 🛠️

训练后量化

训练后量化是最直接的方法:先正常训练一个FP32模型,训练完成后,再确定各层的量化参数并将权重转换为低精度格式。
- 权重:直接根据训练好的权重值计算
r_min,r_max。 - 激活:需要一个有代表性的数据集(如验证集的一个批次),通过网络前向传播,收集各层激活值的分布,据此计算量化参数。
这种方法实现简单,但对于某些模型可能造成精度下降。

量化感知训练
为了缓解训练后量化的精度损失,可以采用量化感知训练。其核心思想是在训练过程中模拟量化效应,使模型能够适应量化误差。

实现方式:在网络图中插入伪量化节点。在前向传播时,这些节点执行 量化->反量化 操作,将量化误差引入计算图;在反向传播时,使用直通估计器,假设该操作的梯度为1,让梯度正常回传。
代码示意(前向传播中的伪量化):
def fake_quantize(tensor, scale, zero_point):
# 量化
quantized = round(tensor / scale) + zero_point
quantized = clip(quantized, 0, 2**bits - 1)
# 反量化
dequantized = scale * (quantized - zero_point)
return dequantized
量化感知训练通常能显著提升量化模型后的精度,是生产中的常用技术。
非线性量化 🌀
之前我们讨论的都是线性量化,其量化步长是均匀的。但当数值分布极不均匀时(如双峰分布),线性量化效率不高。这时可以使用非线性量化。
核心思想:根据数值的分布密度来分配量化值,在数值密集的区域使用更精细的间隔,在稀疏区域使用更粗糙的间隔。
常见方法:K均值聚类量化。
- 将权重值通过聚类算法(如K-means)分成
k个簇。 - 每个簇用一个质心(通常是簇内点的平均值,高精度存储)表示。
- 原始的每个权重值不再存储其具体数值,而是存储其所属簇的索引(仅需
log2(k)比特)。
优势与局限:
- 优势:能实现极高的压缩率(例如,用2-4比特索引代替32位浮点数),大幅减少模型存储占用。
- 局限:计算时仍需将索引查表转换为高精度质心进行计算,因此不能加速计算,主要适用于存储受限、计算能力足够的场景。
前沿思路:乘积量化 🚀
本节最后,我们看一个有趣的量化变体——乘积量化。它展示了量化思想可以如何拓展。

乘积量化不再对单个数值进行量化,而是对向量块进行量化。
- 学习一组原型向量。
- 将数据向量分割成块,每块用最相似的原型向量来近似表示(存储原型索引)。
- 对于点积运算,可以预先计算所有原型向量之间的点积并存入查找表。
- 实际计算时,只需查找和累加这些预计算的结果,从而“不乘而乘”。

这是一种将计算开销转化为存储和查找开销的激进方法,在某些特定场景下非常高效。
课程总结 📚
本节课我们一起深入学习了神经网络量化技术。我们从量化的基本定义和动机出发,详细剖析了线性量化的原理,包括缩放因子、零点、量化误差以及其在矩阵乘法中的应用。我们比较了对称与非对称量化的优劣,并探讨了量化粒度的选择。
接着,我们学习了两种主要的量化实施策略:简单的训练后量化和更鲁棒的量化感知训练。此外,我们还了解了非线性量化(如K均值聚类)如何通过非均匀间隔实现更高的压缩比。最后,我们瞥见了乘积量化这一前沿思路,它展示了量化思想的更多可能性。

量化是连接高效算法与底层硬件的重要桥梁,是部署机器学习模型,特别是在边缘设备上不可或缺的技术。掌握量化,意味着你能让模型跑得更快、更省电,并能在资源有限的平台上解锁更强大的AI能力。
机器学习硬件和系统:009:剪枝

在本节课中,我们将学习另一种提高神经网络效率的技术——剪枝。我们将探讨其核心概念、不同类型、实施方法以及如何将其整合到训练流程中。
概述
剪枝是一种通过移除神经网络中不重要的参数(权重)来减少计算量和模型大小的通用技术。其核心思想是,许多参数对最终输出的贡献微乎其微,移除它们可以在保持模型精度的同时显著提升效率。
什么是剪枝?


上一节我们介绍了量化技术,它通过降低数值精度来提升效率。本节中,我们来看看另一种方法:剪枝。
剪枝的基本过程是:训练一个神经网络,分析其参数,然后移除其中一部分。最简单的标准是移除幅度最小的参数,因为它们在点积运算中的贡献最小。
在数学上,剪枝通过引入一个剪枝掩码来实现。假设我们有一个权重矩阵 W 和输入 x,正常的线性层计算是 y = Wx。剪枝后,计算变为:
y = (W ⊙ M) x
其中 M 是一个与 W 形状相同的二进制掩码(0 表示剪枝,1 表示保留),⊙ 表示逐元素乘法。
在 PyTorch 中,实现方式就是创建一个剪枝掩码,并将其与权重矩阵进行逐元素相乘。
剪枝的类型与策略
了解了基本概念后,我们来看看剪枝的不同维度。主要涉及剪什么、如何剪、何时剪以及剪枝频率。
以下是几种关键的剪枝策略分类:
-
按剪枝结构分类
- 非结构化剪枝:移除单个权重,不遵循特定模式。理论上压缩率高,但硬件加速困难。
- 结构化剪枝:移除整个结构单元,如权重矩阵中的整行、整列(通道)或整个滤波器。硬件友好,但可能对精度影响更大。
-
按剪枝范围分类
- 局部剪枝:独立地对每一层移除固定百分比(如 P%)的参数。
- 全局剪枝:将所有层的参数放在一起排序,全局移除幅度最小的 P% 的参数。通常效果更好,但可能导致“层坍塌”(某一层的参数被全部移除)。
-
按剪枝时机分类
- 训练后剪枝:模型训练完成后,一次性剪枝。
- 迭代剪枝:采用“剪枝-再训练”的循环,逐步移除参数并微调模型,通常能获得更好的精度-稀疏度权衡。
- 初始化剪枝:在训练开始前,根据权重初始化状态进行剪枝。
迭代幅度剪枝

目前最成功且普遍的剪枝方法是迭代幅度剪枝。

它不是一个一次性操作,而是将剪枝过程放入循环:先训练网络,移除一小部分(如10%)最小幅度的权重,然后对剪枝后的网络进行再训练(微调),重复此过程直到达到目标稀疏度。
这种方法之所以有效,是因为它给了优化算法机会,在每次剪枝后重新调整剩余权重的重要性,从而找到更优的稀疏子网络。
促进稀疏性:正则化
为了让剪枝更有效,我们可以在训练时鼓励权重趋向于零。这通常通过向损失函数添加正则化项来实现。
损失函数通常为 L_total = L_task + λ * R(W),其中 L_task 是原始任务损失(如交叉熵),R(W) 是正则化项。
常用的正则化项有:
- L1 正则化:
R(W) = ||W||_1 = Σ|w_i|。倾向于产生精确的零值。 - L2 正则化:
R(W) = ||W||_2^2 = Σw_i^2。使权重整体变小。
在训练中,优化器会尝试最小化总损失,从而同时推动权重幅度减小,为后续剪枝创造更有利的条件。
超越幅度:参数重要性准则
仅凭权重幅度来判断重要性是一个有效的代理,但并非终极标准。更根本的方法是衡量移除某个参数对损失函数的影响。
参数 w_j 的重要性(显著性)可以形式化定义为:
S_j = | ΔL(D; w_j) | = | L(D; W) - L(D; W | w_j=0) |
其中 L(D; W) 是使用所有权重时的损失,L(D; W | w_j=0) 是将 w_j 设为零后的损失。
然而,精确计算这个值需要为每个参数重新训练网络,计算成本无法承受。因此,研究提出了多种近似方法:
- 最优脑损伤:使用损失函数关于权重的二阶导数(海森矩阵的对角线)来近似重要性。
S_j ≈ w_j^2 / (2 * [H_{jj}]),其中H是海森矩阵。 - 基于梯度的准则:利用一阶或二阶梯度信息来估计参数对损失的影响。
- 基于信息的准则:如互信息或费雪信息,衡量激活通道(而非权重)的重要性。
这些方法旨在找到比简单幅度更准确的参数重要性排序。
彩票假设与初始化剪枝
一个有趣的方向是彩票假设。它指出,一个随机初始化的密集网络中,包含一些“中奖彩票”子网络(稀疏网络),如果使用与密集网络相同的初始化来训练这个子网络,它能达到与原始密集网络相当的性能。
这启发了初始化剪枝的研究,旨在训练开始前就找到有效的稀疏结构,从而避免先训练庞大密集网络的开销。相关算法如 SNIP、GraSP、SynFlow 等,试图在初始化阶段就估计参数重要性并进行剪枝。
其他高级剪枝概念
除了上述主流方法,还有一些前沿方向:
- 动态剪枝:允许在迭代过程中被剪枝的权重重新恢复,从而更灵活地探索稀疏结构。
- 运行时剪枝:根据不同的输入样本,动态激活网络的不同部分。
- 学习剪枝掩码:将剪枝掩码或稀疏模式作为可学习参数,与网络权重一同优化。
总结

本节课我们一起学习了神经网络剪枝技术。我们从基本概念出发,了解了如何通过移除不重要权重来压缩模型。我们探讨了非结构化与结构化剪枝、局部与全局剪枝的区别,并深入介绍了最有效的迭代幅度剪枝方法。此外,我们还学习了如何通过正则化促进稀疏性,以及更复杂的参数重要性准则。最后,我们展望了彩票假设和初始化剪枝等前沿方向。剪枝与量化一样,是构建高效、轻量级机器学习模型的关键技术之一。
机器学习硬件和系统:010:特邀讲座 - Cerebras Sean Lie
在本节课中,我们将学习Cerebras Systems联合创始人兼首席硬件架构师Sean Lie带来的特邀讲座。他将探讨如何通过颠覆性的协同设计方法,应对未来机器学习对算力的巨大需求挑战。
演讲者介绍
Sean Lie是Cerebras Systems的首席硬件架构师和联合创始人。在此之前,他曾任职于SeaMicro公司,并担任其I/O虚拟化架构的硬件架构负责人。在SeaMicro被AMD收购后,他成为AMD院士和首席数据中心架构师。其职业生涯早期,他曾在AMD的先进架构团队工作五年。Sean拥有麻省理工学院的电气与计算机工程及计算机科学学士和硕士学位,并在计算机架构领域拥有16项专利。
讲座概述
我们非常荣幸能邀请到Sean。他今天将与我们分享Cerebras公司为应对AI计算挑战所做的一些“跳出框架”的思考。这些思考对于满足未来的机器学习需求至关重要。
面临的挑战:前所未有的算力需求
上一节我们介绍了演讲者,本节中我们来看看当前机器学习领域面临的巨大算力挑战。
机器学习,特别是深度学习,正以前所未有的速度发展。2018年,最先进的神经网络拥有1亿个参数。到了2019年,GPT-2和Megatron等模型的参数量达到了10亿到1000亿级别。2020年,GPT-3的参数量达到了1750亿。就在几个月前,微软宣布了其Megatron-Turing NLG模型,参数量高达5300亿。
核心趋势:模型规模在短短两年内增长了1800倍。这给计算机架构师和整个行业带来了既令人兴奋又令人生畏的挑战。
行业的应对:创新与局限
面对这种需求,行业做出了哪些努力?以下是近年来的一些关键创新:
- 工艺技术:从16纳米、12纳米到7纳米芯片的持续演进。
- 先进封装:实现更高带宽的内存。
- 低精度格式:如FP16和BFloat16。
- 新数据通路设计:如脉动阵列和张量核心,显著提高了计算密度和能效。


让我们深入分析这些创新。首先,工艺技术(摩尔定律)持续进步,晶体管密度在过去十年中稳步提升,并且这一趋势预计将持续数年。其次,在架构和微架构层面,我们使用“每晶体管峰值FLOPS”作为衡量标准。数据显示,架构性能的提升速度与摩尔定律持平甚至略有超越,这证明了架构设计的重要性。
然而,令人担忧的部分是:过去两年,工艺带来了约2倍的提升,架构带来了约3倍的提升,但ML需求却增长了1800倍。这中间存在300倍的缺口。这个缺口是如何填补的呢?答案是:系统横向扩展。例如,OpenAI训练GPT-3时使用了1000个GPU。因此,近年来的性能提升完全由系统横向扩展主导。
横向扩展的瓶颈

那么,我们是否可以简单地继续横向扩展来满足未来需求?让我们设想一下:假设未来两年,工艺再带来2倍提升,架构再带来3倍提升,那么要满足可能再增长1800倍的需求,我们仍然需要300倍的横向扩展。这意味着需要数十万个芯片组成的集群。这在技术上是可能的,但在成本、功耗和物理空间上几乎不可行。
横向扩展存在根本性限制,因为它并不容易部署,且本质上不具备良好的可扩展性。根本原因在于:巨型神经网络需要海量的内存、计算和通信。试图用成千上万个小型设备来解决这个问题,会将内存、计算和通信的扩展都变成相互依赖的分布式难题,导致分布式复杂性爆炸式增长。

因此,我们认为,使用现有的横向扩展技术,可能还能获得10倍左右的提升(对应约1万个芯片的集群规模),但很难再多了。微软训练MT-NLG模型使用了4000个GPU,似乎也印证了这一点。
总结挑战
综上所述,采用当前方法,行业在未来两年可能还有60倍(2倍工艺 x 3倍架构 x 10倍扩展)的提升路径。但我们需要的是1800倍的提升。这就是摆在我们面前的“宏大ML需求挑战”。
我们必须找到方法,在工艺、架构和横向扩展三个方面都实现数量级的实质性改进。我们需要一个更均衡的扩展路径:在工艺、架构和真正可扩展的集群技术上,各自再获得10到50倍的提升。这有可能吗?我们相信答案是肯定的,但前提是必须跳出传统思维框架,进行真正的端到端协同设计。
解决方案一:超越单芯片的工艺协同设计
上一节我们明确了挑战的规模,本节中我们来看看如何通过协同设计在工艺层面实现突破。
摩尔定律依然有效,但我们能否进一步放大其效果?历史上,晶体管密度的提升也伴随着芯片尺寸的逐步增大。然而,我们现在遇到了瓶颈:大芯片良率低、光刻技术存在根本性挑战、大芯片供电和散热困难。
行业已经通过先进封装和多芯片模块(MCM)技术进行创新,实现了比单芯片多2到5倍的硅面积。最近,特斯拉等公司提出的使用整个晶圆作为中介层的概念,甚至有望实现20倍的硅面积增长。
在Cerebras,我们采取了更极端的协同设计方法。2019年,我们推出了晶圆级引擎。它是一个从300毫米晶圆上切割出的最大正方形单芯片,面积超过46,000平方毫米,拥有2.6万亿个晶体管和85万个计算核心。它的面积是最大GPU的56倍。
实现这一点需要深度协同设计,以解决三个主要问题:良率、光刻限制和功耗/散热。

1. 良率问题:我们通过冗余设计来解决。将芯片架构设计为一个由二维网格连接的均匀小核阵列,并内置了冗余核心和冗余链路。当某个核心存在缺陷时,可以用冗余核心替代,并通过冗余链路重新连接网格,从而在逻辑上恢复完整的二维网格。

2. 光刻限制:我们不再追求更大的光刻视野,而是在标准独立芯片(die)的基础上,通过晶圆上的“划片槽”进行连接。我们在划片槽上添加导线,使用工艺的高层金属,将这些独立的芯片连接起来,从而在整个晶圆上形成一个完全同质的核心阵列。这些看似很短的导线至关重要,因为它们提供了芯片内部级别的带宽,却跨越了整个晶圆,其能效比传统I/O高出数个数量级。
3. 功耗与散热:这块芯片功耗高达20千瓦,传统的电路板横向供电和直接风冷无法满足要求。我们通过3D封装协同设计解决了这个问题:电流通过电路板垂直注入晶圆,热量则通过水冷板中的水流垂直导出,从而实现了对整个晶圆均匀的供电和散热。
最终,我们构建了一个从晶圆、引擎块到完整系统的、为晶圆级芯片从头设计的系统架构。通过芯片、封装、代工厂和芯片架构之间的这种深度协同设计,我们可以将芯片尺寸的边界推远至远超传统扩展的程度。我们相信,晶圆级芯片等新的协同设计方法,是解决宏大ML挑战的关键部分,它能在单芯片上实现高达两个数量级的工艺增益和集群级性能。
解决方案二:面向稀疏性的架构协同设计
解决了工艺扩展问题后,本节我们探讨如何通过架构创新,尤其是利用神经网络的稀疏性,来大幅提升性能。
神经网络通常被视为一系列矩阵乘法运算。传统架构不断演进,以越来越高的密度运行密集矩阵乘法,这是过去几年架构性能提升的主要来源之一。但这种方法能否带来下一个数量级的提升?很可能不行,因为物理和功耗限制意味着芯片上只能容纳有限数量的计算单元,且越大的数据通路在计算不规则工作负载时利用率可能越低。
我们需要改变规则。我们能否用更少的浮点运算得到相同的结果?答案是肯定的,因为神经网络本质上是稀疏的。将神经网络仅仅视为密集矩阵乘法,忽略了其基本特性。
稀疏性出现在计算中存在零值时。由于乘以或加上零不会改变结果,这些运算是浪费的。稀疏性可能来源于ReLU、Dropout等技术,甚至在前向传播密集的网络中,反向传播的非线性函数也会引入稀疏性。此外,即使是全连接网络也可以被稀疏化,因为神经网络本质上是过参数化的,训练过程在某种程度上就是在发现哪些参数重要,哪些不重要。
ML社区已经发明了许多利用稀疏性的算法,如下表所示,有些可以实现高达10倍甚至更多的浮点运算减少。
| 稀疏性算法示例 | 潜在收益 |
|---|---|
| 权重剪枝 | 高 |
| 激活稀疏化 | 中到高 |
| 动态稀疏训练 | 高 |
想象一下,如果架构能够利用这种潜力,并促使ML社区发明更稀疏的新模型。这种ML与硬件的协同设计水平,是现有矩阵乘法方法无法实现的。因为传统矩阵乘法架构与细粒度、非结构化、动态的稀疏计算从根本上是不匹配的,原因有二:
- 内存限制:传统架构利用缓存和本地寄存器来利用数据复用,这对数据复用多的密集矩阵乘法很有效,但对数据复用少的稀疏操作则成为瓶颈。
- 结构限制:数据通路为执行结构化矩阵乘法而硬连线,这使其设计紧凑高效,但无法有效处理非结构化的稀疏操作。
那么,如果我们能将稀疏性作为一等公民进行架构协同设计,解决这两个根本限制呢?这将为ML协同设计和稀疏性加速打开广阔的机会。
Cerebras的解决方案:
- 解决内存限制:我们通过完全分布式内存,将内存紧邻计算单元放置。利用晶圆级集成,我们能够以高容量、高性能和低功耗实现与计算操作数带宽相等的内存带宽。这使得我们能够以全性能运行从矩阵乘到向量-标量乘的所有级别的运算。一个稀疏矩阵乘法本质上就是一系列向量-标量乘的集合,因此这种能力使得加速任意非结构化、细粒度的稀疏矩阵乘法成为可能。
- 解决动态非结构化问题:我们采用细粒度数据流调度。在Cerebras核心中,计算由数据触发。数据流机制使得整个计算结构成为一个数据流引擎。通过简单地在源头过滤掉所有零值,接收端就不会触发计算,从而自然地支持稀疏性。这不仅节省了功耗,还通过跳过无用工作实现了加速。
这种架构需要与机器学习和编译器软件深度协同设计。在ML侧,它原生加速自然稀疏性,并支持新稀疏ML技术的协同设计。在软件侧,我们从零开始协同设计了具有数据流感知能力的软件。
以稀疏矩阵乘法内核为例:我们将整个晶圆视为一个巨大的稀疏矩阵乘法阵列。权重流经晶圆,触发与本地激活值的乘法(一次一个权重),跳过所有零权重,结果部分和通过高带宽互连在整个晶圆上累加。由于晶圆的巨大尺寸,我们无需对矩阵进行分块或分区。
我们的实验室测量结果显示,对于GPT-3规模的层,在高达90%的权重稀疏性(即零值是非零值的10倍)下,仍能实现接近线性的加速。唯一的限制是Amdahl定律,因为需要分摊一些固定开销,但随着模型增大,这些开销会减小。
通过这种级别的ML协同设计,我们实际上可以突破传统的浮点运算扩展限制。我们相信,稀疏性操作的机会随着模型规模的增长而增加。结合传统的架构改进,通过启用与ML社区协同设计的新一类稀疏ML技术,我们有路径实现另一个数量级的架构性能提升。


解决方案三:集群级的可扩展协同设计
我们已经讨论了工艺和架构,本节我们来看最后一个关键组成部分:如何实现真正可扩展的集群计算。
现有的集群解决方案为何难以扩展?让我们看看现有的横向扩展技术:
- 数据并行:模型在每个设备上复制,训练数据被分割。这种方法简单,但对于大模型不适用,因为整个模型需要能放入每个设备。
- 模型并行(流水线并行):将模型的不同层放在不同设备上运行。这支持更大的模型,但通信开销大,且随着设备增多,需要保存的激活内存呈二次增长。
- 模型并行(张量并行):将层分割到不同设备上。这也有通信开销,且如何分割层非常复杂。
因此,训练这些巨型模型通常需要混合并行策略(数据并行+模型并行),例如OpenAI训练GPT-3的方式。这使得问题极其复杂,许多大公司需要专门的工程团队来管理。
根本原因在于:传统的横向扩展中,内存和计算是绑定在一起的。试图在数千个设备上运行单个模型,使得内存和计算的扩展变成了相互依赖的分布式约束问题。随着模型增大,需要更多的分区、更细粒度的协调和同步。
在Cerebras,我们认为正确的解决方案不是创建软件来隐藏复杂性,而是在集群级别进行真正的协同设计,跳出传统设备的思维框架。我们相信可以设计出本质上简单且可扩展的解决方案。
我们的方法是权重流执行模型。我们将整个集群视为ML加速器,从根本上将内存与计算分离(解耦)。这样,我们可以在集群级别为模型所需的不同类型的内存和计算设计专用解决方案,从而解开复杂性,完全简化扩展问题。
权重流架构包含三个核心组件:
- CS2系统:包含晶圆级引擎的主要计算单元。单个大芯片使得所有大模型层都无需分区即可运行。
- Memory-X:外部存储设备,专门设计用于存储所有模型参数(权重),可扩展到支持数万亿参数。
- Swarm-X:互连网络,专门设计用于扩展神经网络训练,可将集群规模扩展到192个CS2系统。
在这个执行模型中,所有权重都集中存储在Memory-X中,并按需流式传输到CS2系统,以逐层计算神经网络。权重甚至不临时存储在系统上。前向传播产生的激活值保留在系统上供下一层使用。反向传播时,梯度流回Memory-X进行权重更新。
为了容忍将数据移远带来的延迟,我们利用了神经网络内存访问模式的特性:激活内存需要被下一层立即访问,对延迟敏感,因此我们将其保留在芯片上。而权重内存的访问和更新相对不频繁,没有这种背靠背的依赖关系。我们通过两种流水线技术来隐藏外部权重访问的延迟:
- 粗粒度层间流水线:调度整个训练作为层的流水线,无需等待前一层完成即可开始流式传输下一层的权重。
- 细粒度权重更新流水线:在更新权重的同时,重叠执行下一轮训练的前向传播。
通过这种集群级的流水线技术,权重流执行模型可以达到与权重本地存储相同的性能。
- 存储容量:通过将所有模型参数移至单个外部设备,我们可以使用DRAM和闪存存储来支持极大的模型规模。该设备内部还包含执行权重更新(优化器函数)的计算单元。
- 计算扩展:通过Swarm-X互连,我们可以完全独立于内存来扩展计算。Swarm-X在Memory-X和所有CS2计算单元之间,以树状拓扑广播所有权重并归约所有梯度。它是一个为数据并行训练量身定制的主动组件。扩展计算就像向Swarm-X拓扑添加更多节点和CS2系统一样简单。
- 原生稀疏性支持:由于底层架构原生支持稀疏性,整个集群也原生支持。稀疏性在Memory-X单元内的权重矩阵中诱导产生,然后以稀疏形式广播到CS2进行计算。
我们预计,从单个CS2系统扩展到192个系统,性能提升接近线性。对于从100亿到100万亿参数的各种自然语言模型,这种扩展可以转化为显著的训练加速。对于当今最大的语言模型(如GPT-3),我们预计在扩展到192个系统时仍能保持接近线性的扩展。
通过改变规则,从整体上思考集群级别的问题,我们可以解决当今横向扩展的根本挑战,并实现从单个设备到数百个设备完全相同的执行模型。这就是我们如何应对宏大挑战的最后一个组成部分——实现本质上可扩展的横向扩展。
总结与展望
本节课中,我们一起学习了Sean Lie关于应对未来机器学习算力挑战的深刻见解。
回顾过去几年,我们看到ML工作负载的需求增长了超过一千倍,且没有放缓的迹象。初看之下,这似乎令人生畏且难以实现。但我们今天看到,这实际上是可能的——但并非通过传统技术。只有改变规则,跳出传统边界,通过深度协同设计,才能实现这个未来。
我们探讨了三种关键的协同设计路径:
- 工艺层面:通过晶圆级芯片等创新,超越单芯片限制,将工艺增益放大数个数量级。
- 架构层面:将稀疏性作为一等公民,设计超越浮点运算限制的架构,为ML协同设计打开新的大门。
- 集群层面:通过权重流等执行模型,在集群级别进行解耦和协同设计,实现本质上简单且可扩展的计算扩展。

这是一个令人兴奋的计算机架构时代。Sean分享的只是Cerebras为追求这一未来所采取的部分思路和方法,作为可能性的一个例证。我们期待看到社区接下来会提出什么创新的解决方案。
本节课中我们一起学习了:
- 机器学习模型规模爆炸式增长带来的算力挑战(1800倍/2年)。
- 传统工艺、架构和横向扩展方法的提升空间与局限。
- 通过“深度协同设计”应对挑战的必要性。
- Cerebras在工艺(晶圆级引擎)、架构(稀疏性优先、数据流)和集群(权重流执行模型)三个层面的具体协同设计创新与实践。
- 这些创新如何共同为满足未来万亿参数模型的训练需求提供了可行的技术路径。
机器学习硬件和系统:011:知识蒸馏 🧠
在本节课中,我们将要学习一种名为“知识蒸馏”的神经网络优化方法。与之前讨论的量化、剪枝不同,知识蒸馏旨在将大型、高精度网络(教师网络)的“知识”迁移到小型、高效的网络(学生网络)中,从而在不显著损失精度的情况下实现模型压缩和加速。
概述
上一节我们介绍了通过剪枝来移除神经网络中的冗余参数。本节中,我们来看看另一种缩小神经网络规模的方法——知识蒸馏。其核心思想是,让一个已经训练好的、性能强大的大型网络(教师)去指导一个更小、更易部署的网络(学生)进行训练。
什么是知识蒸馏?🤔
在标准的神经网络分类任务训练中,我们使用“硬目标”(Hard Targets),即独热编码的标签(例如,对于一张猫的图片,猫的类别为1,其他所有类别为0)。这种方法只提供了正确类别的信息。
然而,一个训练良好的大型网络输出的“软目标”(Soft Targets),即经过Softmax函数处理后的类别概率分布,包含了更丰富的信息。例如,它可能给“猫”很高的概率,给“狗”一定的概率,而给“船”几乎为零的概率。这种分布揭示了类别之间的相似性关系,即所谓的“暗知识”(Dark Knowledge)。
知识蒸馏就是利用教师网络产生的软目标,结合原始的硬目标,共同指导学生网络的训练过程。
知识蒸馏如何工作? ⚙️
以下是知识蒸馏的基本流程框架:
- 准备教师网络:首先,训练(或获取)一个大型、高精度的神经网络作为教师。该网络已训练完毕,参数固定。
- 定义学生网络:初始化一个结构更小、参数更少的学生网络。
- 前向传播:对于一批训练数据,同时输入教师网络和学生网络。
- 计算损失:损失函数由两部分组成:
- 学生损失(Student Loss):计算学生网络输出(使用温度T=1的Softmax)与真实硬标签之间的交叉熵损失。这确保了学生网络学习基本的正确分类。
- 蒸馏损失(Distillation Loss):计算学生网络输出(使用温度T>1的Softmax)与教师网络输出(使用相同温度T的Softmax)之间的差异。通常使用KL散度(Kullback-Leibler Divergence)来衡量两个概率分布的差异。这部分促使学生模仿教师的“思考方式”。
- 组合损失与反向传播:将两部分损失加权求和,得到总损失,然后仅对学生网络的参数进行反向传播和优化。
核心概念:Softmax温度
温度参数 T 是知识蒸馏中的一个关键超参数。标准的Softmax函数为:
公式:softmax(z_i) = exp(z_i) / Σ_j exp(z_j)
引入温度T后,变为:
公式:softmax(z_i, T) = exp(z_i / T) / Σ_j exp(z_j / T)
- 当
T = 1时,即为标准Softmax。 - 当
T > 1时,概率分布会变得更“平滑”,错误类别的相对概率会被放大,从而暴露出更多暗知识,有利于蒸馏。 - 当
T < 1时,分布会更“尖锐”,趋向于硬目标。
在训练时,我们使用较高的T(例如5或10)来计算蒸馏损失;在推理(部署)时,学生网络仍使用 T = 1 的标准Softmax来获得最终的分类结果。
总损失函数

总损失函数可表示为:
公式:Loss_total = α * Loss_hard + β * Loss_distill

其中:
Loss_hard是学生网络与硬标签的交叉熵损失。Loss_distill是学生与教师软目标之间的KL散度损失。α和β是平衡两项损失的权重超参数,通常β = 1 - α。
代码实践:实现知识蒸馏 💻
以下是如何在PyTorch训练循环中实现知识蒸馏的核心代码片段。假设我们已有一个预训练的教师模型 teacher_model 和待训练的学生模型 student_model。
# 定义超参数
temperature = 5.0
alpha = 0.5
beta = 1.0 - alpha
# 训练循环内部
for inputs, labels in dataloader:
# 前向传播:学生和教师网络
student_logits = student_model(inputs)
with torch.no_grad(): # 教师网络不更新梯度
teacher_logits = teacher_model(inputs)
# 计算硬目标损失(学生损失)
loss_hard = F.cross_entropy(student_logits, labels)
# 计算软目标损失(蒸馏损失)
# 使用带温度的softmax
soft_targets = F.softmax(teacher_logits / temperature, dim=1)
soft_prob = F.log_softmax(student_logits / temperature, dim=1)
# 使用KL散度,等价于交叉熵,因为targets是固定的
loss_distill = F.kl_div(soft_prob, soft_targets, reduction='batchmean') * (temperature ** 2)
# 组合总损失
loss = alpha * loss_hard + beta * loss_distill
# 反向传播与优化(仅更新学生网络)
optimizer.zero_grad()
loss.backward()
optimizer.step()
进阶技术与开放问题 🚀
知识蒸馏领域发展迅速,出现了许多变体和进阶技术:
-
教师网络的变体:
- 集成蒸馏:使用多个神经网络的输出平均值作为教师信号,可以提升知识质量。
- 专家网络:针对大规模数据集(如数万类别),训练多个“专家”网络,每个负责一个子类别的集合,然后将它们的知识蒸馏到一个学生网络中。
-
蒸馏模式:
- 离线蒸馏:教师网络预先训练好,固定不变。这是我们上面介绍的标准模式。
- 在线/协同蒸馏:教师网络和学生网络同时训练,互相学习。
- 自蒸馏:同一个网络内部,用深层特征或最终输出指导浅层或中间层的输出。这在具有“早期退出”机制的网络中特别有用。
-
知识类型:
- 基于响应:使用最终输出层的软目标(本节主要内容)。
- 基于特征:匹配教师和学生网络中间层特征图(如激活值)的分布。
- 基于关系:匹配教师网络中不同层或样本之间的关系(如Gram矩阵),并将这种关系迁移给学生网络。
-
特殊场景应用:
- 跨模态蒸馏:将从一个数据模态(如RGB图像)训练好的教师网络知识,迁移到另一个模态(如热力图)的学生网络。
- 无数据蒸馏:在没有原始训练数据的情况下,仅利用教师网络生成合成数据或噪声数据进行蒸馏。
- 量化辅助:使用知识蒸馏来提升量化后模型的精度。
总结

本节课中我们一起学习了知识蒸馏技术。我们从其核心动机讲起——如何将大型教师网络的丰富知识迁移到小型学生网络。我们详细剖析了其工作流程,包括软目标、Softmax温度、以及结合了学生损失和蒸馏损失的总损失函数。通过代码示例,我们看到了如何在实际训练中实现它。最后,我们概述了该领域的一些进阶技术与开放性问题,如集成蒸馏、特征蒸馏和跨模态蒸馏等。知识蒸馏是一种强大且灵活的模型压缩与性能提升工具,在资源受限的部署场景中具有重要价值。
机器学习硬件和系统:012:神经架构搜索 (Neural Architecture Search)
在本节课中,我们将要学习一个非常有趣且高级的主题——神经架构搜索。这是一种神经网络优化方法,旨在让网络在硬件上实现更高效的运行。我们将探讨其基本概念、主要算法、如何提升搜索效率,以及如何与硬件特性结合进行优化。
概述
神经架构搜索旨在自动化神经网络结构的设计过程。传统上,神经网络结构(如AlexNet、VGG)依赖于研究者的直觉和大量试错。NAS通过算法自动探索和评估大量可能的网络结构,以找到在特定目标(如准确率、延迟)上表现最佳的模型。
动机:从手动设计到自动设计
上一节我们介绍了神经网络优化的背景,本节中我们来看看为什么需要自动化设计。
人们设计神经网络来完成特定任务。例如,AlexNet有特定的拓扑结构:5个卷积层和3个全连接层,这很大程度上基于传统图像识别工作的直觉。同样,VGG网络也是手动设计的,它基于“卷积层比全连接层更重要且计算成本更低”的直觉,因此增加了更多卷积层。
然而,这些设计中的具体参数(如层数384)往往是任意选择的。神经网络的一个强大之处在于,许多不同的拓扑结构都能通过训练算法(如SGD)学习到相同的功能。因此,问题就变成了:我们如何设计出能获得最佳准确率的网络结构? 这就是神经架构搜索要解决的问题。
手动设计基于直觉和大量试错,耗费大量人力时间。自动设计则转向了智能化的、自动化的试错,它虽然需要GPU时间,但正在朝着更快的方向发展。
什么是神经架构搜索?
上一节我们了解了自动设计的必要性,本节中我们来看看NAS最基本的形式。
在其最简单的形式中,神经架构搜索相当直接:
- 一个算法提出一个深度神经网络(例如图中的绿色网络)。
- 我们训练这个网络并获得其准确率(例如79%)。
- 算法稍微修改网络结构(例如改变层数、滤波器大小),提出一个新的网络(例如黄色网络)。
- 训练新网络并获得不同的准确率。
- 重复此过程,最终在尝试过的众多网络中选择准确率最高的一个。
这种方法被称为随机搜索。它虽然简单,但效果不错,甚至可以超越人工设计的网络,因为它能自动化地尝试大量结构。
当然,除了随机搜索,还有许多更智能的算法。
基于样本的搜索算法
以下是几种主流的基于样本的NAS搜索算法,它们都需要实际训练候选网络来评估其性能。
1. 强化学习方法
NAS最初的研究始于强化学习。其核心思想是使用一个控制器(通常是一个循环神经网络)来生成网络结构。
- 控制器 (Controller):一个参数化的函数(如RNN),在每一步预测网络的一个超参数(如滤波器数量、尺寸)。
- 动作 (Action):选择一个具体的架构参数值。
- 状态空间 (State Space):即搜索空间,是所有可能网络结构的集合。
- 奖励 (Reward):训练生成的网络后得到的性能反馈(如准确率)。控制器根据奖励更新自身参数,以便下次提出更好的网络。
然而,早期的强化学习方法需要巨大的计算资源(例如,一篇开创性论文使用了800个GPU运行28天),这引发了人们对可扩展性的关注。
2. 遗传/进化算法
为了寻找更高效的搜索算法,人们转向了遗传或进化算法。这里介绍一个成功的变体:衰老进化。
以下是衰老进化算法的工作流程:
- 初始化进化池:随机生成一组(例如8个)神经网络,并评估其准确率。
- 选择与变异:从池中选择准确率最高的模型(“精英”),对其进行微小改动(“变异”)以产生一个子代模型。
- 淘汰与更新:从池中移除存在时间最长的模型(“衰老”),无论其性能如何。然后将新的子代模型加入进化池。
- 重复:不断重复步骤2和3。
移除最老的模型而非最差的模型,是为了在探索(尝试新区域)和利用(优化已知好区域)之间取得平衡。进化算法通常比强化学习更稳定、更高效,是目前最好的基于样本的搜索算法之一。

提升NAS的可扩展性

上一节我们介绍了搜索算法,但它们的计算成本可能很高。本节中我们来看看如何让NAS变得更高效、更易实施。
1. 缩小搜索空间:基于单元的NAS
搜索空间的大小随网络深度呈指数增长。为了应对这个问题,基于单元的NAS 成为一种主流方法。

其核心思想是:
- 固定一个网络的骨架(如整体的深度和阶段划分)。
- 不再搜索整个网络,而是搜索一个小的、可重复的单元的结构。
- 一旦找到最优单元,就将其重复堆叠到骨架的各个阶段中。
例如,假设一个单元内有5个操作,每个操作有8种选择。那么:
- 微搜索:所有单元相同,搜索空间大小为
8^5 = 32,768。 - 宏搜索:每个单元可以不同,如果有10个单元,搜索空间大小激增至
(8^5)^10,这是一个天文数字。


基于单元的方法大大缩小了搜索空间,同时借鉴了成功网络(如ResNet、MobileNet)由重复模块构成的经验,在实践中非常有效。

2. 参数共享


在传统NAS中,每个候选网络都从头开始训练,成本高昂。参数共享 技术允许不同的候选网络共享已经训练好的层参数。
例如,如果新提议的网络包含一个与之前训练过的网络相同的5x5卷积层,那么可以直接继承该层的参数,只需训练新增或不同的层。这可以显著减少训练时间,有论文报告其速度提升了1000倍。


3. 训练代理
完全训练每个候选网络直到收敛仍然很慢。我们可以使用训练代理来快速估计网络的潜力。
常见的代理方法包括:
- 训练更少的周期。
- 使用训练数据的子集。
- 使用更低分辨率的输入图像。
- 减少每层的通道数。
这些方法虽然不能给出精确的最终准确率,但能有效对网络性能进行排序,从而指导搜索方向。组合使用这些代理方法可以获得显著的加速(例如32倍)。

4. 高效的搜索算法:预测器
另一种思路是训练一个元模型来预测网络性能的相对排名,而不是每次都进行训练。

例如,可以训练一个二元关系预测器(一个神经网络),输入是两个网络的结构,输出是哪个网络更好的预测。首先用少量完全训练的网络数据对这个预测器进行监督学习,然后用它来快速筛选和排序搜索空间中的大量网络。这种方法能实现很高的样本效率,快速收敛到优秀模型。
可微架构搜索
上一节我们主要关注基于样本的方法,本节中我们来看一种不同的、基于梯度的范式:可微架构搜索。
其核心思想是构建一个包含所有可能操作的超网。在超网的每条边上,我们不是选择单一操作,而是将所有候选操作(如3x3卷积、5x5卷积、池化)的输出进行加权求和,权重为可学习的架构参数 α。
公式表示混合操作:
输出 = Σ_i ( softmax(α_i) * op_i(x) )
在训练过程中,我们同时优化:
- 网络权重
w:在训练集上,固定α,优化w以减少训练损失。 - 架构参数
α:在验证集上,固定w,优化α以减少验证损失。
这形成了一个双层优化问题。实践中常采用交替优化的近似方法。训练结束后,选择每条边上 α 值最大的操作,即可得到最终的网络结构。
DARTS等方法使得NAS可以在几个GPU小时内完成,但这种方法在理论和实践上也面临一些挑战,是当前的研究热点。
硬件感知的神经架构搜索
到目前为止,我们主要优化的是准确率。但实际部署时,我们同样关心效率。本节中我们来看看如何让NAS同时优化准确率和硬件性能(如延迟、功耗)。
1. 多目标优化
在硬件感知NAS中,搜索循环增加了一个步骤:
- 搜索算法提出一个网络。
- 训练网络,获得准确率
Acc。 - 将网络部署到目标设备(如手机)或模拟器中,测量其延迟
Latency。 - 根据
Acc和Latency计算一个多目标奖励,反馈给搜索算法。
奖励函数的设计通常有两种:
- 硬约束:延迟超过阈值的网络直接被丢弃。
- 软约束:使用加权和等形式,如
奖励 = Acc - λ * Latency。
2. 延迟预测
直接在设备上测量延迟虽然准确,但麻烦且难以扩展。因此,人们研究如何预测延迟。
- FLOPs/参数量:简单的代理,但相关性往往不佳,因为它忽略了内存访问、硬件并行度等实际因素。
- 逐层累加:预先测量每种操作在目标设备上的延迟,然后将新网络的各层延迟相加。这比FLOPs更好,但仍未考虑层间的融合、数据依赖等整体效应。
- 基于神经网络的预测器:将网络结构(如图神经网络)作为输入,直接预测其端到端延迟。这种方法准确性高,且只需少量样本进行训练,是当前的研究方向。
3. 硬件与网络的协同设计
一个更前沿的方向是协同设计,即同时搜索最优的神经网络架构和为其定制的硬件架构参数(如缓冲器大小、并行度)。
这通常使用强化学习,控制器同时输出网络操作和硬件配置。虽然搜索空间更大、更复杂,但有可能在特定硬件(如FPGA)上实现精度和效率的双重提升。
总结
本节课中我们一起学习了神经架构搜索的各个方面:
- 动机与定义:我们了解了自动化网络设计的需求,以及NAS通过算法自动搜索高效网络结构的基本流程。
- 核心算法:我们介绍了基于样本的搜索方法,包括早期的强化学习和目前更有效的遗传/进化算法(如衰老进化)。
- 提升效率:为了应对NAS的计算挑战,我们探讨了多种技术:基于单元的NAS缩小搜索空间;参数共享避免重复训练;训练代理加速评估;以及使用预测器等更智能的搜索算法。
- 可微搜索:我们学习了DARTS等可微架构搜索方法,它们通过梯度优化架构参数,速度更快。
- 硬件感知:我们深入探讨了如何将硬件指标(如延迟)纳入优化目标,比较了不同的延迟预测方法,并简要介绍了硬件-网络协同设计这一前沿方向。

神经架构搜索是自动化机器学习的关键组成部分,它正在改变我们设计神经网络的方式,使其不仅能达到更高的精度,也能满足实际部署中对速度、功耗和资源的严格约束。
机器学习硬件和系统:013:核计算

在本节课中,我们将要学习核计算。这是关于软件主题的第一讲。我们已经讨论了硬件架构效率,比较了不同芯片,并深入研究了如何在不深入了解硬件的情况下优化神经网络。现在,我们将转向运行这些深度神经网络或深度学习工作负载的另一个关键组成部分——软件。
软件常常被忽视,尤其是在使用PyTorch或考虑GPU时,人们通常不会关注中间层。然而,软件的实现实际上非常困难,并且对神经网络的性能至关重要。这也是像英伟达这样的公司目前领先的原因之一——他们拥有非常优秀的软件栈。
软件栈概览
上一节我们介绍了学习核计算的动机。本节中,我们来看看机器学习软件栈的一个简单视图。
对于机器学习用户、深度神经网络设计者或运行神经网络的人来说,最相关的视图通常是这样的:最上层是PyTorch或TensorFlow等框架,它们运行在Python之上。这些Python库会调用底层的硬件特定库。
- 如果运行在GPU上,通常会调用一个名为cuDNN的库,该库使用基于C的CUDA语言编写。
- 如果运行在CPU上(例如英特尔CPU),通常会调用名为MKL(数学核心库)的库及其扩展MKL-DNN,这些库使用C++编写。
cuDNN等库在非常高的粒度上实现操作,例如整个卷积运算。因此,PyTorch在GPU上运行时,很大程度上可以看作是cuDNN的一个封装器。
矩阵乘法的不同算法
我们将探讨实现矩阵乘法的不同算法。矩阵乘法可以用四层循环简单实现,但还有许多其他方法,通常称为变换或核实现,可以使运算在某些情况下更高效。
我们还将研究卷积的一些实现方法。我们将从图像到列(Im2col)变换开始,然后讨论Strassen变换、Winograd变换、快速傅里叶变换和对数域乘法。这些是矩阵乘法和卷积的核实现,它们不改变最终结果,只是使用不同的数学运算来执行。
我们还将简要了解矩阵乘法的近似方法,例如低秩近似,并概述张量分解。
在接下来的内容中,我们会提到“节省了一次乘法,但增加了十次加法”之类的比较。请记住,乘法运算比加法运算昂贵得多,其能耗比大约在4到8倍之间。
Im2col:图像到列变换
首先,我们介绍Im2col变换。这是一种在大多数通用硬件上实现卷积的方法。
Im2col的字面意思是将二维图像转换为矩阵中的列。例如,对于一个卷积运算,我们有一个滤波器和特征图。通常,我们需要将滤波器在特征图上滑动以获得输出。然而,大多数通用硬件并不原生支持卷积操作,需要将其转换为加法和乘法。矩阵乘法在大多数硬件上得到了非常好的支持和高效实现。

Im2col通过以下方式将卷积转换为矩阵乘法:
- 将滤波器展平为一维向量。
- 对于特征图中的每个滑动窗口,将该窗口内的数据转换为矩阵的一列。

通过执行矩阵(或向量)乘法,我们可以得到与原始卷积相同的结果。随着卷积窗口滑动,每个新窗口成为转换后图像矩阵的新的一列。
这种方法非常简单,也是GPU上实现卷积的主要方式,因为GPU同样不原生支持卷积,需要将其转换为优化良好的矩阵乘法。
有人可能会问,是否有硬件原生支持卷积?答案是肯定的。例如,TPU或手机中的NPU等专用芯片就原生支持卷积。它们通常采用权重固定的数据流,将滤波器存储在处理单元中,然后让不同的输入流过该滤波器。这与GPU或CPU等通用硬件不同。
关于Im2col的一个关键问题是数据复制。将图像转换为列本身没有计算成本,只是内存重组,但它带来了内存成本。数据被复制,这增加了对内存带宽或片上缓冲区的需求。访问模式也可能变得更复杂,但人们通常在卷积操作之前离线完成这种重组,以便数据更好地适配缓存。
Im2col也可以应用于滤波器,尽管这不太常见,因为它会引入许多零值。基本思想是将输入特征图展平为向量,然后以特定方式复制和填充滤波器,使得进行向量-矩阵乘法时能得到相同的输出结果。
Im2col的主要问题是数据复制,这在算法层面是昂贵的,可能增加对外部或内部内存带宽或存储的需求。
Strassen变换
接下来,我们看看Strassen变换。我们将开始计算乘法和加法的数量,看看每种方法节省了多少。
左侧展示的是普通的矩阵乘法。对于一个2x2矩阵乘以2x2矩阵,总共需要8次乘法和4次加法。
Strassen提出了一种更好的方法,只需要7次乘法和18次加法。他节省了1次乘法,但增加了14次加法。考虑到乘法比加法昂贵4到8倍,这在许多硬件上可能带来节省。
在深度神经网络中,我们还有一个额外的技巧。因为其中一些乘法、减法或加法可以离线完成,特别是当矩阵B代表我们的参数或权重时。在推理时,我们可以预先计算这些部分,从而在部署时只需13次加法,而不是18次。
Strassen变换本质上是通过重组操作来实现的,例如以特定方式分解运算,通过改变加法和减法的发生位置来转换。
Winograd变换
另一个非常有趣的变换是Winograd变换,我们在设计加速器时经常使用它。现在我们讨论的是卷积,而不是矩阵乘法。
让我们看一个一维卷积的例子。我们有一个滤波器(F0到F2)和一个输入块(I0到I3)。我们需要将滤波器在输入上滑动。
如果写成矩阵形式,这需要6次乘法和4次加法。
Winograd提出了一种更好的方法,其精神与Strassen变换类似,但它还利用了矩阵中的数据有公共部分这一事实(例如,在步长为1时,每一行是前一行移位后的版本)。他重组了计算,并证明这是对卷积窗口执行相同精确操作所需的最少乘法数。
同样,我们可以利用参数可离线计算的技巧,进一步减少加法次数。在这个例子中,我们从6次乘法、4次加法减少到4次乘法、8次加法。
关于Winograd变换的一些要点:
- 通常,卷积窗口越大,能获得的节省越多。例如,对于3x3卷积,乘法次数可以减少约2.25倍。
- 变换不仅特定于滤波器大小,还特定于操作的图块大小。用于转换到Winograd域的数值计算对特定尺寸是唯一的。
- 人们通过矩阵形式泛化了这种计算,使用G、B、A矩阵来转换输入和滤波器,并在输出端用A矩阵及其转置来还原变换。
- Winograd变换的真正节省来自于:一旦转换了输入和滤波器,卷积操作就变成了逐元素乘法。
- 滤波器可以离线转换,但输入转换(乘以B矩阵)和输出逆转换(乘以A矩阵)需要在推理时在线完成。
- 在使用低精度(如INT8)时,变换本身对低精度的鲁棒性通常较差。因此,人们通常在更高精度下执行变换,而在低精度下执行逐元素乘法。
快速傅里叶变换
现在,我们讨论FFT变换。傅里叶变换是将时域信号转换为其频率分量的重要变换。
离散傅里叶变换的方程涉及输入与一个指数项的乘积和求和。通常,我们将权重(滤波器)和输入通过傅里叶变换转换到频域。

卷积定理指出,在时域进行卷积等价于在频域进行乘法。这与Winograd变换类似,都是用计算较轻的逐元素乘法替代计算较重的卷积操作。
但我们需要付出什么代价?为了进行逐元素乘法,我们需要相同大小的张量或矩阵。因此,我们通常用零填充滤波器,使其与输出特征图大小相同。
如果正常进行卷积,操作次数约为 R*S*P*Q(滤波器尺寸R x S,输出尺寸P x Q)。进行傅里叶变换后,操作变为乘法,但滤波器尺寸变大了,操作次数约为 P*Q*log2(P*Q)。
如果所有尺寸相同(设为N),则复杂度从 N^2 变为 N log N,缩放性更好。但实际获得加速的条件是:R*S 必须大于 log2(P*Q)。如果滤波器尺寸远小于输出尺寸,并且仍然小于输出尺寸的对数,那么可能无法获得加速,并且还需要承担不平凡的变换开销。

对数域乘法
这是另一种变换,可能尚未在cuDNN中支持。对数域乘法的思想是:将两个数A和B相乘,可以写成 2^x * 2^y。如果我们能找到将A转换为 2^x、将B转换为 2^y 的方法,那么乘法就变成了指数相加:2^(x+y)。
为了转换到对数域,我们对输入取以2为底的对数,得到x和y。然后,我们不再需要乘法,只需进行加法得到z。最后,我们计算 2^z 得到最终结果。
这非常巧妙,因为乘法比加法昂贵得多,这提供了一种用单个操作转换输入输出,然后用加法替代所有乘法的方法。
然而,存在一些问题:
- 高精度计算对数和指数本身效率不高,甚至可能比乘法更昂贵。
- 如何处理负数?不能直接对负数取对数。通常的解决方案是单独处理符号位,仅对数值部分进行变换。
- 对数域变换本身可能容易导致溢出,因为它压缩了数值范围,转换回来时可能饱和。
- 精度可能是个问题,尤其是在低精度下,因为数字被重新映射到不同的域。
- 最主要的问题是:我们通常不只是做乘法,而是做乘加运算。如何在对数域中相加两个数?没有直接的方法。需要转换回线性域才能相加,而转换成本很高。尽管有许多近似方法,但它们通常会损失很多精度或需要专用硬件。
好消息是,英伟达似乎正在研究这个问题。有一项专利描述了一种通过将指数分解为商和余数分量、基于余数对商排序、然后对排序后的商求和来快速相加对数域数字的方法。这可能在未来的GPU中实现。
如何选择变换
那么,如何选择使用哪种变换呢?一个实用的方法是像英伟达那样:在cuDNN库中有一个函数 cudnnFindConvolutionForwardAlgorithm,它会尝试所有可用的卷积前向算法,并提供每个算法的运行时间。这就是为什么在GPU上对模型进行基准测试时,通常会丢弃前几次运行的结果——因为库正在尝试每种变换,找出最快的一种,然后继续使用它。
目前并没有完美的启发式方法,有时手动计算乘法和加法数量也太复杂。
低秩近似与张量分解

之前讨论的都是实现精确矩阵运算的新方法。现在,我们简要讨论矩阵的近似方法,特别是低秩近似。

奇异值分解是特征值分解对任意尺寸矩阵的推广。它将一个 M x N 的矩阵分解为三个矩阵:U、Σ(对角矩阵,包含奇异值)和 V^T。U 和 V 是正交基向量,奇异值表示每个基向量在重构原矩阵时的重要性。
SVD如何帮助我们?我们可以移除最小的奇异值,同时最小化矩阵重构误差。每次移除一个奇异值,就可以移除 U 和 V 中对应的行和列,从而得到一个更小的矩阵运算。这被称为低秩近似,因为我们减少了表示矩阵所需的基向量数量(即矩阵的秩)。
深度神经网络中的矩阵本质上是低秩的,网络本身已经过参数化,因此低秩近似对许多网络非常有效。通过低秩近似,原来的 M x N 矩阵乘法变成了两个更小的矩阵乘法:M x K 和 K x N。加速比取决于 K(保留的秩)。只有当 K 足够小,使得 M*K + K*N < M*N 时,才会获得加速。

更进一步,除了矩阵分解,还有张量分解。SVD作用于矩阵,而张量分解直接作用于更高维的张量(例如,卷积神经网络的滤波器是四维的:高度、宽度、输入通道、输出通道)。两种主要的张量分解方法是Tucker分解和CP分解。与将张量展平为矩阵再进行SVD相比,直接进行张量分解可以保留更多信息,有时能实现更好的压缩。

例如,有研究使用单个高维张量来参数化整个神经网络,然后通过张量分解对其进行整体压缩。这种方法不仅压缩效果好,还能作为正则化器,有时能获得更好的实证结果。这代表了从标量、向量、矩阵运算向张量-张量运算发展的趋势。
总结与延伸阅读

本节课中,我们一起学习了不同的核实现方法,主要是为了节省乘法运算。我们讨论了Im2col、Strassen、Winograd、FFT和对数域乘法。我们还讨论了奇异值分解和矩阵近似,并简要接触了Tucker和CP张量分解。

以下是一些延伸阅读资料,帮助你更深入地了解这些主题:
- Im2col: Chellapilla et al., “High Performance Convolutional Neural Networks for Document Processing”, 2006.
- Strassen变换: Strassen, “Gaussian Elimination is not Optimal”, 1969.
- Winograd变换: Lavin & Gray, “Fast Algorithms for Convolutional Neural Networks”, CVPR 2016.
- FFT变换: Mathieu et al., “Fast Training of Convolutional Networks through FFTs”, ICLR 2014.
- 对数域乘法: 英伟达相关专利。
- 低秩近似: Denton et al., “Exploiting Linear Structure Within Convolutional Networks for Efficient Evaluation”, NIPS 2014.
- 张量分解: Kossaifi et al., “Tensor Regression Networks”, JMLR 2020.
机器学习硬件和系统:014:映射

在本节课中,我们将要学习如何将高级代码映射到机器学习加速器或通用处理器上。我们将探讨为了在特定硬件上高效运行代码而进行的各种优化,这些优化对于提升性能至关重要。
编译器基础概述

上一节我们介绍了映射的概念,本节中我们来看看编译器是如何工作的。大多数编译器包含三个主要部分。
- 前端:将高级编程语言(如C++)转换为一种中间表示。这种中间表示比源代码更底层,但比汇编语言更抽象,便于进行优化。
- 中端/优化器:在中间表示上进行代码重构和优化。例如,可以重新排列循环、融合或拆分循环、改变数据索引方式以提高缓存命中率,所有这些操作都不改变程序的功能。
- 后端/代码生成器:将优化后的中间表示转换为针对特定目标硬件(如CPU、GPU或ARM处理器)的机器代码。LLVM项目就是为了创建统一的中间表示以支持多种后端而诞生的。

机器学习编译器
了解了传统编译器后,本节中我们来看看专注于机器学习的编译器有何不同。机器学习编译器通常处理领域特定语言,例如深度学习框架中的计算图。

以下是机器学习编译器的典型流程:

- 计算图层:接收由粗粒度操作(如卷积、矩阵乘法)构成的计算图,并在此层级进行优化。
- 中间表示层:将计算图转换为更细粒度的中间表示,并进行进一步的底层优化。
- 后端:最终生成能在GPU、CPU或专用加速器上运行的代码。此时,LLVM可能被视为一个后端选项。
映射的核心优化
现在,我们将深入探讨将深度神经网络映射到硬件时需要考虑的核心优化技术。
选择数据流
首先,我们需要决定计算的数据流模式。硬件可能支持不同的数据流,例如权重驻留、输入驻留或输出驻留。编译器可以通过重构代码循环来改变数据流,以适应硬件特性并提升性能。
以一个一维卷积的简单代码为例:
for (int s = 0; s < S; s++) { // 遍历滤波器
for (int q = 0; q < Q; q++) { // 遍历输入
output[q] += input[q + s] * filter[s];
}
}
在上述代码中,外层循环遍历滤波器权重,内层循环遍历输入。这意味着在每次内层循环迭代期间,filter[s]的值保持不变,因此这是一种权重驻留的数据流。
编译器可以将其转换为输出驻留的数据流,使输出地址在计算过程中保持稳定,这可能更适合某些硬件架构。
分块
分块是指选择每次计算所处理的数据块大小。这主要出于内存层次结构的考虑。
以下是将循环分块的示例:
int Q0 = TILE_SIZE; // 分块大小
for (int q_outer = 0; q_outer < Q; q_outer += Q0) {
for (int q_inner = 0; q_inner < Q0; q_inner++) {
// 计算逻辑,使用 (q_outer + q_inner) 作为索引
}
}
通过分块,我们可以控制数据在内存层次结构中的位置。通常,最内层循环处理的数据块(分块)会被放置在离处理单元最近的存储器中。
向量化/并行化
分块优化了数据局部性,而向量化则旨在利用所有可用的并行计算单元。
在分块的基础上,我们将最内层循环并行化:
for (int q_outer = 0; q_outer < Q; q_outer += Q0) {
#pragma parallel for
for (int q_inner = 0; q_inner < Q0; q_inner++) {
// 并行计算逻辑
}
}
这样,多个处理单元可以同时处理同一个分块内的不同数据元素。分块大小通常设置为与处理单元数量相匹配。
计算单元绑定
在拥有多个处理核心的硬件上,我们需要明确指定哪个计算操作由哪个处理单元执行。
最简单的绑定方式是将循环迭代变量直接映射到线程或核心索引上。现代编程模型(如CUDA)通过“线程”抽象来管理这一点,允许创建比物理核心更多的线程,由系统调度执行。
计算图级优化
除了上述循环级优化,在计算图层级也有重要的优化手段。
以下是常见的计算图优化策略:
- 算子融合:将多个连续的操作合并为一个更大的操作,减少数据搬运开销并增加并行度。
- 算子降级与强度削减:将软件中丰富的算子集合映射到硬件实际支持的有限算子集上。例如,将反卷积或平均池化转换为标准卷积操作。
- 内存分配与调度:管理片上内存的使用,采用双缓冲等技术减少内存碎片,并通过调整操作执行顺序来最小化所需的内存容量。
- 常量传播与形状推导:在编译时计算常量表达式,简化运行时操作。
映射空间与指令集
映射的选择空间非常庞大,但其中许多选项在功能或性能上是等价的,另一些则是无效的。编译器通常使用启发式方法和硬件模型来导航这个空间,以找到较优解。
对于深度学习加速器,其指令集架构通常非常专用。编译器的工作可能简化为参数化这些粗粒度指令(如“执行卷积”并指定其超参数),然后直接发送给硬件执行。
总结

本节课中我们一起学习了代码映射的核心概念。我们从编译器的基础结构讲起,对比了通用编译器与机器学习编译器的差异。然后,我们深入探讨了关键的映射优化技术:选择数据流以适应硬件、分块以优化内存访问、向量化以利用并行计算能力,以及计算单元绑定。此外,我们还了解了在计算图层级进行的优化,如算子融合和内存调度。理解这些优化原理对于在机器学习加速器上实现高效计算至关重要。
机器学习硬件和系统:015:TVM 框架概述与核心技术


在本节课中,我们将学习一个名为 TVM 的开源深度学习编译器框架。我们将了解它为何被创建,其核心工作原理,以及它如何解决机器学习模型在不同硬件平台上部署时面临的效率、可移植性和软件支持等关键挑战。
概述:机器学习部署的挑战
随着人工智能的普及,AI推理任务需要在各种设备上运行,从云端服务器到资源受限的边缘设备(如智能音箱、安防摄像头)。机器学习工程师面临一个复杂的部署矩阵:模型可能来自不同的训练框架(如 PyTorch、TensorFlow),而目标硬件平台(如 CPU、GPU、ARM 微控制器、专用加速器)也多种多样。传统上,依赖硬件厂商提供的手动优化库不仅难以扩展以适应新模型和新硬件,而且开发和维护成本极高。
TVM 应运而生,它是一个开源的机器学习优化框架,旨在自动生成针对特定硬件的最优代码,从而解决上述可移植性、效率和新硬件支持问题。
TVM 的核心优势
以下是 TVM 旨在解决的三个核心痛点:
- 可移植性:TVM 允许将模型部署到众多“异质”平台上。例如,研究人员曾成功将关键词识别模型部署到不支持标准机器学习框架的 Azure Sphere 物联网设备上。
- 效率:TVM 提供自动化优化,能从硬件中榨取最大性能。例如,Facebook 的工程师使用 TVM 对 WaveRNN 模型应用稀疏化、数据类型优化等,在一周内实现了 100 倍的加速,满足了实时音频处理的严苛要求。
- 对新硬件的软件支持:对于设计 AI 专用芯片(如 ASIC、FPGA)的硬件公司,TVM 提供了一个统一的软件栈入口,降低了让程序员使用其硬件的门槛,无需为每个框架单独适配。
TVM 已在工业界得到广泛应用,例如优化 Facebook 的模型、为亚马逊 Alexa 提供支持,并被高通、ARM 等芯片厂商用于其 SoC 上的异构计算。
深入 TVM 工作原理
上一节我们介绍了 TVM 解决的问题,本节中我们来看看 TVM 内部是如何工作的。我们将从算子优化、自动化优化、图级优化以及对微控制器的支持四个方面进行探讨。
算子级优化:从数学定义到高效实现
一个神经网络模型可以看作一个计算图,其中每个节点代表一个算子(如卷积、矩阵乘法)。让单个算子在特定硬件上高效运行是编译器的核心任务。
传统的高性能算子实现(如 Intel MKL、NVIDIA cuDNN 中的库)通常包含大量手写、难以维护的汇编或内联代码。TVM 借鉴了 Halide 语言的思想,引入了 算法定义 与 调度 的分离。
- 算法定义:描述算子要“计算什么”,即其数学功能。例如,矩阵乘法的算法定义是:
C[i, j] = sum(A[i, k] * B[k, j]) - 调度:描述算法“如何计算”,即数据如何在内存中存取、循环如何组织、如何利用并行等。
通过这种分离,TVM 允许用户用简洁的 张量表达式语言 定义算法,然后通过编写简短的调度代码来应用各种优化(如循环分块、向量化、并行化),从而自动生成复杂但高效的低级代码。这使得在获得媲美手写库性能的同时,保持了代码的简洁性和可维护性。
自动化优化:用机器学习优化机器学习
手动为每个算子和硬件组合寻找最优调度非常耗时。TVM 的 AutoTVM 组件将这个过程自动化。
它首先定义一个调度模板,其中预留了一些可调参数(如分块大小、循环顺序)。然后,AutoTVM 将这些参数视为一个巨大的搜索空间,使用基于机器学习的成本模型来指导搜索。该系统通过在目标硬件上实际运行和测量不同调度配置的性能,学习硬件特性,并自动找到接近最优的配置。这种方法甚至能在某些情况下超越硬件厂商提供的手动优化库。
图级优化:超越单个算子
在优化了单个算子之后,我们还可以在整個计算图层面进行优化。TVM 使用名为 Relay 的高级中间表示来承载整个模型的计算图。
一个关键的图级优化是 算子融合。在典型的逐层执行中,每一层的输出张量都需要写回内存,然后作为下一层的输入再读出来,这造成了大量的内存带宽开销。算子融合将多个连续的算子(如 Conv2D + BatchNorm + ReLU)合并成一个复合算子,从而减少中间张量的内存读写,显著提升性能。TVM 的代码生成能力使得这种灵活的融合成为可能,无需为所有可能的算子组合预写实现。
支持微控制器与硬件加速器
TVM 的可移植性优势在资源极端受限的微控制器领域尤为突出。MicroTVM 允许 TVM 为没有操作系统、内存极小的微控制器生成精简的部署代码。它利用灵活的代码生成器,可以适配 GCC、LLVM 或供应商特定的工具链,从而支持多种指令集架构和实时操作系统。
此外,TVM 也为新兴的硬件加速器提供了软件支持。例如,ARM 的 Ethos-U55 微 NPU 就可以通过 TVM 进行编程。模型经过 Relay 图优化和分区后,部分计算可以被卸载到加速器上执行,并由 TVM 完成底层代码生成,使得开发者能够便捷地利用专用硬件的性能优势。
总结与展望


本节课中我们一起学习了 TVM 深度学习编译器框架。我们了解到 TVM 通过分离算法与调度、利用 AutoTVM 进行自动化搜索、在 Relay 层进行图优化,以及支持微控制器和硬件加速器,有效地解决了机器学习模型跨平台部署的挑战。它平衡了代码的简洁性、可维护性与高性能,成为连接多样化的模型与爆炸式增长的硬件生态的关键桥梁。
TVM 不仅是一个强大的研究工具,也已在工业界落地,并催生了像 OctoML 这样的商业化平台,致力于进一步简化机器学习模型的优化与部署流程。对于学习者而言,TVM 为在各类设备上部署和优化模型提供了强大的可能性和实践项目基础。

资源链接:
- TVM 官方文档与教程: https://tvm.apache.org/
- AutoTVM 论文: 《Learning to Optimize Tensor Programs》
- MicroTVM 与 Azure Sphere 案例
- OctoML 平台: https://octoml.ai/
机器学习硬件和系统:016:ML系统中的预处理与后处理

在本节课中,我们将要学习在运行深度神经网络时,除了核心计算之外的其他系统开销。我们将探讨在部署机器学习模型时,预处理、后处理以及系统架构如何影响整体性能,并介绍一些应对这些挑战的新兴思路。

阿姆达尔定律与系统性能瓶颈
上一节我们介绍了课程的整体框架,本节中我们来看看一个决定系统整体性能的关键定律。
当我们优化一个系统时,通常只关注其最耗时的部分。然而,阿姆达尔定律指出,整体性能的提升受限于被优化部分在总运行时间中所占的比例。
假设一个工作负载中,深度神经网络部分占70%。如果我们将其优化了10倍(即速度提升10倍),那么整体系统的加速比是多少?
根据阿姆达尔定律,整体加速比的计算公式为:
整体加速比 = 1 / ((1 - P) + (P / S))
其中:
P是可优化部分(此处为DNN)所占的时间比例(0.7)。S是该部分的加速比(10)。
代入计算:
整体加速比 = 1 / ((1 - 0.7) + (0.7 / 10)) = 1 / (0.3 + 0.07) ≈ 2.7x
因此,即使核心的DNN部分获得了10倍的巨大提升,整体系统性能仅提升了约2.7倍。剩余的30%开销(如数据预处理、传输、系统调度等)成为了新的瓶颈。
阿姆达尔定律的核心思想是:通过优化系统某一部分所获得的整体性能提升,受限于该部分被实际使用的时间比例。 在机器学习系统部署中,这意味着我们不能只关注模型本身的效率,还必须考虑其运行环境中的所有其他环节。
系统栈中的开销层级
理解了性能瓶颈的基本原理后,我们来看看这些开销具体出现在系统栈的哪些层面。从高层的部署到底层的硬件,每一层都可能引入显著的开销。
以下是系统栈中可能产生开销的几个主要层级:
- 部署层:例如使用Docker容器和Kubernetes进行大规模部署时,容器间的通信和管理(如通过消息代理Apache Kafka)会引入延迟。在一个实际的人脸检测系统案例中,仅代理通信就占据了约36%的延迟。
- 应用层:在具体的机器学习应用流水线中,并非所有步骤都涉及深度神经网络。例如,从视频流中提取帧、调整图像大小、裁剪检测到的人脸区域、记录日志等操作,都可能占用大量时间。在某些系统中,这些非DNN操作的总开销甚至可能超过DNN计算本身。
- 硬件层:在典型的加速器架构(如CPU+GPU)中,数据需要在主机内存和加速器内存之间通过PCIe总线传输。这个传输过程会产生延迟,并且可能让加速器处于空闲等待状态,影响吞吐量。此外,主机CPU上的预处理任务也可能成为瓶颈,无法及时为多个GPU提供数据。
硬件层面的优化策略
认识到硬件层面的数据传输是主要开销后,本节我们来看看如何从系统架构设计上缓解或消除这些瓶颈。
针对硬件层面的开销,业界提出了多种优化策略:
- 计算与传输重叠:在将第N个任务的数据传输到GPU的同时,执行第N-1个任务的计算。这可以显著提高GPU的利用率和系统吞吐量,但无法减少单个任务的端到端延迟。
- 增加主机处理能力:当CPU预处理成为瓶颈时,可以增加CPU核心数量。例如,NVIDIA在其A100系统中为每个GPU配备了一个专用的ARM核心来处理数据调度,而不是依赖一个强大的x86核心。
- 加速器直连:在分布式训练等场景中,为了避免通过主机CPU进行梯度同步带来的延迟,可以使用高速互联技术(如NVIDIA的NVLink或Google TPU Pods内的环状连接)直接连接多个加速器。
- 前置处理单元:为了规避“数据先到CPU,再经PCIe到加速器”的路径延迟,可以将可编程硬件(如FPGA)放置在网络入口处,直接在数据到达CPU前进行处理。微软的“脑波项目”就采用了这种架构,将FPGA置于网卡和CPU之间,用于低延迟推理或预处理任务。
- 专用数据处理单元:像NVIDIA的BlueField DPU这类芯片,专门用于处理数据中心的网络、存储和安全任务,旨在减轻CPU和GPU的负担,让它们更专注于计算。
算法与系统的协同设计
除了优化硬件架构,我们还可以从算法和软件层面思考,如何减少或消除预处理步骤。本节介绍一种将传统处理步骤融入神经网络的有趣思路。
一个常见的预处理步骤是图像解压缩(如JPEG解码)。传统流程需要在CPU上完成解码,再将像素数据送入GPU进行DNN推理。
一项研究发现,可以跳过JPEG解码中的“逆离散余弦变换”步骤,直接将DCT系数输入到一个经过适当重新训练的神经网络中。这样做不仅减少了CPU的预处理时间,在某些情况下甚至还能略微提升模型精度。原因是,神经网络的前几层本身就在学习类似于频域变换的特征,因此直接输入频域系数是可行的。
这个例子展示了算法与系统协同设计的潜力:通过重新设计算法流程,可以将部分系统开销吸收到高度优化的DNN计算中,从而简化系统架构并提升整体效率。
移动设备上的系统考量
将计算从云端转移到移动设备是另一个重要趋势,这能降低服务提供商的成本、减少延迟并增强隐私保护。本节我们探讨在手机等设备上运行ML系统时的独特挑战和机遇。

在移动设备上,系统架构与数据中心有很大不同:
- 片上系统:CPU、GPU、NPU等组件通常集成在同一芯片上,共享内存。这消除了PCIe数据拷贝的开销,是一个显著优势。
- 资源受限:移动设备的计算能力和功耗预算远低于服务器。
- 端云协同:由于设备能力有限,复杂的模型仍可能需要将部分计算卸载到云端。这引入了网络传输延迟和能耗的新问题。

研究重点包括:如何划分模型(哪些层在端侧运行,哪些在云侧运行)、如何压缩需要传输的中间数据(激活值),以及如何根据网络条件(4G/5G)动态调整卸载策略。

传感器端的智能处理
最后,我们来看一个更前沿的想法:将处理能力尽可能靠近数据产生的源头——传感器本身。
以手机拍照为例,传统成像流水线非常冗长:传感器 -> 图像信号处理器(ISP,用于调色、HDR等) -> 压缩存储 -> 读取解压 -> DNN处理。如果我们最终只想得到图片的元信息(如“图中有一只猫”),那么中间生成高质量图像的过程就浪费了大量能量和时间。
一种新兴的思路是近传感器处理。例如,索尼提出的“智能视觉传感器”,将图像传感器与一个简单的DNN加速器通过3D堆叠技术集成在一起。这样,传感器在捕获图像后,可以直接在片上完成初步分析,并只输出元数据(如“猫”)或经过裁剪处理的感兴趣区域,而不是完整的图像数据。这能极大减少后续流水线的数据量,节省存储、传输和处理的能量。
总结
本节课中我们一起学习了机器学习系统部署中预处理和后处理的重要性。我们了解到,由于阿姆达尔定律的存在,仅优化深度神经网络本身往往无法获得线性的端到端系统性能提升。系统栈的各个层级,包括部署、应用流水线和硬件架构,都会引入显著开销。

我们探讨了多种应对策略,从硬件层面的计算-传输重叠、加速器直连,到算法层面的协同设计以减少预处理,再到移动设备上的端云协同和传感器端的智能处理。这些思路表明,构建高效的机器学习系统需要跨领域的协同优化,综合考虑算法、软件、硬件和系统架构。
机器学习硬件和系统:017:分布式训练


在本节课中,我们将要学习分布式训练的核心概念。当模型过大无法放入单个GPU内存,或训练速度过慢时,我们需要使用多个设备协同工作。我们将探讨两种主要的并行化策略:模型并行与数据并行,并了解如何通过梯度压缩和先进的网络拓扑来优化设备间的通信。


硬件发展背景与动机

上一节我们介绍了大规模模型对硬件的需求。本节中我们来看看最新的硬件如何推动分布式训练的发展。

NVIDIA近期发布了基于Hopper架构的H100 GPU。与上一代A100相比,H100在训练如GPT-3这样的大模型时,声称能带来近7倍的性能提升和高达30倍的吞吐量提升。
性能飞跃的背后存在一些关键变化。H100的功耗达到了700瓦,远高于A100的400瓦,同时制程工艺从7纳米升级到了4纳米。这表明,部分性能提升是通过增加功耗和提升制程密度实现的。

另一个重要转变是对数值格式的侧重。H100架构加强了对FP8(8位浮点数)格式的支持,这与传统的INT8(8位整数)量化不同。FP8格式包含指数和尾数,能提供更大的动态范围,但其在数轴上的表示点并非均匀分布,可以看作一种非线性量化。这种格式的引入是为了更好地适应现代大模型的训练需求。

此外,如何将多个GPU高效连接成集群或超级计算机,也是当前硬件发展的重点,这与我们今天要讨论的分布式训练中的通信问题直接相关。
为什么需要分布式训练?
使用单个GPU进行训练主要面临两个限制:
- 计算速度限制:单个GPU每秒能执行的乘加运算次数是有限的。
- 内存容量限制:GPU的显存必须能容纳模型参数、前向激活值、反向梯度、优化器状态以及小批量数据。当模型过大或批量设置导致所需内存超过显存时,单卡训练就无法进行。
以GPT-3(1750亿参数)为例,其规模已远超早期的AlexNet(百万级参数)。为了训练此类大模型,或处理图像、视频等多模态数据,我们必须采用多设备并行训练。分布式训练已成为必需而非可选的技术。
分布式训练的三种核心方法


以下是实现分布式训练的三种核心思路。
1. 模型并行
当模型过大,无法放入单个GPU内存时,我们需要使用模型并行。其核心思想是将模型的不同部分放置在不同的GPU上。
具体流程如下:
- 将输入数据移至GPU0。
- 在GPU0上计算模型第一部分的前向传播。
- 将GPU0输出的激活值(一个大张量)移至GPU1。
- 在GPU1上计算模型第二部分的前向传播,并计算损失。
- 在GPU1上开始反向传播,计算梯度。
- 将GPU1上的梯度移回GPU0。
- 在GPU0上完成剩余部分的反向传播。
- 更新所有参数。

在代码中,使用PyTorch时,通过 tensor.to(device) 命令(如 tensor.to(‘cuda:1’))可以方便地在设备间移动数据。一个简单的模型并行代码示例如下:
# 将网络的第一部分放在GPU0上
net1.to(‘cuda:0’)
# 将网络的第二部分放在GPU1上
net2.to(‘cuda:1’)

# 前向传播
input = input.to(‘cuda:0’)
intermediate = net1(input)
intermediate = intermediate.to(‘cuda:1’) # 移动激活值
output = net2(intermediate)
模型并行的主要挑战在于:
- 通信开销:设备间移动激活值和梯度需要时间。
- 设备闲置:由于计算依赖,GPU1必须等待GPU0完成计算后才能开始工作,容易造成设备利用率不足。
- 负载均衡:需要手动划分模型,尽量使不同GPU上的计算负载均衡。
因此,模型并行通常只在模型无法放入单卡内存时使用。
2. 数据并行
当模型可以放入单个GPU内存,但希望通过增加批量大小来加速训练时,我们使用数据并行。其核心思想是将一个小批量数据拆分到多个GPU上并行处理。
具体流程如下:
- 将同一模型副本复制到每个GPU上。
- 将小批量数据平均分给每个GPU。
- 每个GPU独立进行前向传播和反向传播,计算本地梯度。
- 聚合所有GPU的梯度并计算平均梯度。
- 每个GPU使用平均梯度更新其模型参数。
关键问题在于如何高效地聚合梯度。最初的方法是All-Reduce(全规约),即每个GPU需要将自己的梯度广播给所有其他GPU。如果有 N 个GPU,每个梯度大小为 K,那么每个GPU需要发送 K*(N-1) 的数据量。通信成本随GPU数量线性增长,扩展性差。
为了改进,人们引入了参数服务器架构。指定一个或一组GPU作为服务器,工作GPU将梯度发送给服务器,服务器聚合梯度后再将结果广播回所有工作GPU。这减少了工作GPU的通信量,但服务器的通信负载变为 K*N,仍存在瓶颈。通过使用多个参数服务器(S个)可以分摊负载,使每个服务器的通信量降至约 K*N/S。
目前最流行且扩展性更好的方法是环全规约。它将All-Reduce操作分解为两个阶段:Reduce-Scatter(规约散播)和All-Gather(全收集)。
- Reduce-Scatter:每个GPU将自身的梯度数组分成
N块。通过环状连接,GPU依次传递并累加这些块。经过N-1步后,每个GPU拥有完整梯度总和的一部分。 - All-Gather:每个GPU将其拥有的那块总和部分,再次通过环状连接广播给所有其他GPU。经过
N-1步后,所有GPU都拥有了完整的梯度总和。
环全规约的优点是每个GPU的通信量约为 2K(发送和接收各约 K 数据),且与GPU数量 N 无关,具有极佳的扩展性。主流框架如Horovod即采用此方法。
数据并行还有同步与异步之分:
- 同步训练:等待所有GPU计算完毕,聚合梯度后再更新参数。这是最常用的方式,收敛行为可预测。
- 异步训练:任一GPU计算完梯度后立即更新中心参数服务器,其他GPU使用可能过时的参数进行计算。虽然延迟更低,但可能影响收敛速度和最终精度,目前较少使用。

3. 梯度压缩

即使采用环全规约,通信量仍与梯度大小 K 成正比。梯度压缩技术旨在减少 K 的有效大小,从而降低通信开销。主要方法有:
- 量化:例如,将32位浮点梯度量化为8位或4位进行传输,训练完成后再恢复。这通常能带来约2倍的加速,有时还能起到正则化效果。
- 剪枝:只传输绝对值较大的梯度,将小梯度置零。由于零值可以高效压缩(如游程编码),能大幅减少通信量。研究表明,即使剪枝90%的梯度,模型精度也可能基本不受影响。

前沿架构与总结

传统的加速器(GPU)通过CPU和PCIe总线连接与通信。新兴的架构试图改变这一点,例如微软在数据中心部署的FPGA方案,将FPGA直接置于网络交换机上。数据在到达CPU之前即可被FPGA处理,计算结果也可直接通过网络发送给其他FPGA,避免了CPU和PCIe的延迟与不确定性开销。
NVIDIA的新方案也体现了类似思路,推出了将GPU直接与网络接口卡相连的产品,旨在优化分布式训练中的通信路径。



本节课中我们一起学习了分布式训练的核心方法。我们了解到,模型并行用于解决内存不足问题,数据并行用于加速训练,而环全规约是高效实现数据并行的关键算法。此外,通过梯度压缩可以进一步减少通信开销。最后,硬件架构的演进(如直接网络连接)正在为超大规模分布式训练提供新的可能性。掌握这些知识,是理解和设计现代机器学习系统的重要基础。
机器学习硬件和系统:018:联邦学习
在本节课中,我们将要学习一个非常有趣的主题——联邦学习。我们将探讨它如何将分布式训练的思想扩展到更多设备和用户,并了解其独特的要求和挑战。
上一节我们介绍了分布式训练及其通信成本问题。本节中,我们来看看联邦学习,它本质上是分布式训练的一种形式,但具有非常不同的要求和应用场景。
联邦学习概述
联邦学习是一种分布式训练方法,其核心思想是利用大量用户设备上持续生成的数据来训练一个中央模型,而无需将原始数据上传到中央服务器。
联邦学习与分布式训练的区别
以下是联邦学习与分布式训练的主要区别:
- 设备异构性:联邦学习中的设备类型差异巨大,从旧款手机到最新智能手机,甚至智能手表和增强现实眼镜。
- 通信链路:设备可能通过Wi-Fi、3G、4G或5G等不同网络连接,且连接不稳定、不可靠。
- 设备数量:联邦学习面向数百万甚至数十亿台设备,规模远超分布式训练中通常的数十或数百个GPU。
- 数据分布:每个设备上的数据分布通常不同且不具代表性,这被称为非独立同分布数据。
- 设计目标:联邦学习强调数据隐私和系统可扩展性,而分布式训练更侧重于训练速度。
总而言之,联邦学习的目标是在无法直接访问数据、且能扩展到海量设备的情况下,利用持续生成的数据训练模型。
设备端训练的挑战
在深入算法之前,需要认识到设备端训练面临硬件限制。目前,手机等设备可以进行推理,但进行复杂模型训练的能力仍然有限。训练通常在设备充电且连接Wi-Fi时进行,以节省电量并降低通信成本。
联邦平均算法

联邦平均是联邦学习的基础算法,其核心步骤是减少通信频率。以下是该算法的步骤:

- 初始化:中央服务器初始化一个全局模型。
- 选择设备:在每一轮训练中,服务器从数百万设备中随机选择一部分(例如几千台)。
- 分发模型:将当前全局模型发送给选中的设备。
- 本地训练:每台设备使用本地数据对模型进行多轮训练,更新本地模型参数。
- 上传更新:设备将更新后的模型参数上传至服务器。
- 聚合更新:服务器收集所有更新,并根据各设备的数据量进行加权平均,更新全局模型。
该算法的关键优势在于,通过让设备在本地进行多轮训练后再通信,将通信成本降低了10到100倍。

联邦平均的改进:FedProx
联邦平均算法存在一些缺点,FedProx算法对其进行了两项主要改进以提升效果:
- 处理掉队者:不直接丢弃未及时完成训练的设备,而是接受其部分训练结果。
- 限制参数变化:在本地训练的损失函数中增加一个正则化项,限制本地模型参数与全局模型的差异,防止某些设备的更新过度影响全局模型。
这些改进使训练过程更稳定,在存在设备掉队或数据不平衡时表现更好。
隐私、安全与通信优化
尽管联邦学习将数据保留在设备上,但隐私和安全仍是重要考量:
- 隐私风险:研究表明,从共享的梯度甚至模型参数更新中,也有可能反推出原始数据信息。
- 安全增强:采用安全聚合等技术,例如在加密状态下对模型更新进行聚合,以进一步增强隐私保护。
- 通信优化:应用模型压缩、量化和剪枝等标准方法,减少传输数据量,节省带宽和设备电量。
数据标注的挑战
监督学习需要标注数据。在联邦学习场景中,获取标签主要通过以下方式:
- 利用用户反馈:例如,用户纠正语音识别的转录文本或图像分类标签。
- 激励用户标注:引导用户参与标注,如相册应用询问照片中的人物或地点。
- 探索无监督学习:采用不需要显式标签的学习方法,这被认为是未来的发展方向。
其他替代方案
除了联邦学习,还有其他利用用户设备数据训练模型的方法:
- 数据卸载:直接将数据发送到云端服务器进行训练。优点是避免设备端训练的限制,但牺牲了数据隐私,并需要强大的云端基础设施。
- 协作式机器学习:一种新兴范式,旨在在没有中央服务器的情况下,通过设备间直接交换更新来协同训练模型。这更具挑战性,目前尚未成熟。
总结

本节课中我们一起学习了联邦学习。它是一种利用海量设备数据训练中央模型的方法,核心步骤包括分发模型、本地训练、聚合更新。我们探讨了联邦平均及其改进算法FedProx,并了解了联邦学习在隐私、安全、通信优化和数据标注方面面临的挑战及其解决方案。最后,我们还简要了解了数据卸载和协作式机器学习这两种替代方案。
机器学习硬件和系统:019:环境与伦理系统问题

在本节课中,我们将讨论与机器学习硬件和系统相关的各种环境与伦理问题。我们将聚焦于那些直接与系统和硬件设计相关的议题,并探讨为什么作为工程师或计算机科学家的我们需要关注这些问题。
环境问题
上一节我们介绍了课程的整体框架,本节中我们来看看机器学习对环境的具体影响。一个核心问题是训练大型模型(如GPT-3)所产生的巨大能源消耗和碳排放。

碳排放的量化


一篇早期论文量化了自然语言处理模型的碳排放。训练一个大型模型所产生的二氧化碳排放量,相当于一辆汽车整个生命周期排放量的两倍。而随着模型规模扩大,最新模型的碳排放量已增长到约10辆汽车的排放量。
这引发了一个重要问题:我们是否应该继续这种做法?在进一步推进之前,我们现有的效率技术是否足以减轻这些影响?
能源来源与缓解措施
碳排放的严重程度很大程度上取决于能源的来源。数据中心的能源可能来自可再生能源、核能、煤炭或天然气。因此,将数据中心设在可再生能源丰富的地区,或购买碳信用额度(如植树或投资清洁能源项目),是抵消碳排放的有效方法。
以下是几种主要的缓解策略:

- 使用更高效的模型:通过神经架构搜索、剪枝、量化等技术设计更高效的神经网络。
- 开发专用芯片:与通用GPU相比,专用加速器(如TPU)能显著提高能效。
- 提升数据中心效率:优化数据中心的能源使用效率。
- 创新数据中心设计:例如,微软曾实验将数据中心沉入海底,利用海水冷却,并发现其可靠性更高。

能效指标:PUE


在评估数据中心效率时,一个关键指标是PUE。
PUE = 数据中心总能耗 / IT设备能耗



PUE值越接近1,表示数据中心的能效越高。例如,谷歌曾报告其数据中心的PUE低至1.16,而行业平均水平通常在1.4到1.6之间。
分布式学习的能效:联邦学习
联邦学习将训练任务分散到用户的移动设备上。直观上看,这似乎更节能,但研究发现了相反的结果。


与在高效的数据中心进行集中式训练相比,联邦学习由于通信开销和设备端芯片效率较低,总能耗通常更高。不过,通过改进训练算法,有可能降低其能耗。


全球能源消耗背景
信息与通信技术(ICT)部门目前消耗全球约3%的能源。虽然这个数字目前低于航空业,但预计在未来十年内可能增长到20%。考虑到AI技术的快速普及,确保其可持续发展至关重要。
隐含碳与运营碳


我们必须关注的不仅是设备运行时的能耗(运营碳),还包括制造设备本身所消耗的能源(隐含碳)。

对于许多ICT公司,制造过程(如芯片、显示器)产生的碳排放占其总碳足迹的约70%,远高于产品使用阶段的排放。这凸显了延长设备寿命、减少“计划性报废”的重要性。

效率悖论
在追求效率时,需要警惕“杰文斯悖论”:提高某项技术的效率,可能会因为其使用成本降低而导致总使用量增加,最终反而加剧了对环境的总影响。例如,更高效的汽车可能促使更多人购买和使用汽车。
伦理问题

上一节我们探讨了环境影响,本节我们将转向伦理层面。虽然系统设计中的选择可能不直接决定最终用途,但工程师需要意识到其工作可能被滥用的风险。
技术应用的道德考量

“Maven计划”是一个典型案例。谷歌员工在得知他们参与的项目被用于分析军用无人机图像(可能用于攻击行动)后,超过3000名员工联名抗议,最终促使谷歌制定了不将AI用于武器的原则。这体现了工程师道德意识的重要性。
数据所有权与偏见
数据的使用引发了一系列伦理问题:
- 数据所有权与许可:例如,GitHub Copilot等代码生成模型在未经明确许可的情况下,使用了受版权保护的开源代码进行训练,引发了关于数据所有权和商业使用的争议。
- 算法偏见:模型会反映其训练数据中的偏见。例如,GPT-3在涉及特定宗教或种族的文本补全中,可能生成带有严重偏见的内容。在医疗诊断等关键领域,这种偏见可能导致对少数群体的误诊或不公对待。




研究不平等

最后,我们讨论一个影响AI生态的问题:研究资源的不平等。
训练最先进的模型需要巨大的计算资源,而这些资源(如大型GPU集群)主要集中在少数大型科技公司手中。许多学术界的研究人员或小型机构无法获得这些资源,这限制了创新的多样性和公平性,使得研究进展过度依赖商业公司的利益导向。

总结

本节课中,我们一起学习了机器学习硬件和系统领域面临的环境与伦理挑战。

在环境方面,我们探讨了训练大型模型的碳足迹、能效指标PUE、隐含碳的重要性以及效率提升可能带来的“杰文斯悖论”。


在伦理方面,我们讨论了技术应用的道德责任、数据偏见的所有权问题以及算法公平性的重要性。


最后,我们指出了当前AI研究领域存在的资源不平等问题。

作为未来的工程师和研究者,在设计系统和硬件时,我们不仅要考虑性能和效率,还必须将这些环境和伦理因素纳入考量,以推动技术向更可持续、更公平的方向发展。

浙公网安备 33010602011771号