UCB-EE290-机器学习硬件笔记-全-

UCB EE290 机器学习硬件笔记(全)

001:课程介绍

在本节课中,我们将要学习这门课程的整体概览、核心动机以及课程结构。我们将探讨机器学习硬件领域面临的挑战与机遇,并了解如何通过本课程的学习,成为一名能够构建高效硬件系统的实践者。

课程概述与动机

大家好,欢迎来到EE2902机器学习硬件课程。我是加州大学伯克利分校的Sophia Shao,将担任本课程的讲师。课程将在每周一和周三的太平洋时间下午2点到3点半进行线上授课。

本课程旨在搭建硬件设计与机器学习思维之间的桥梁。我们将以机器学习作为驱动范例,探讨如何设计未来的硬件系统,特别是如何应对新兴应用带来的独特需求。

本课程的具体目标是,在学期结束时,使你们能够构建高效的硬件系统。我们将使用机器学习作为驱动应用,探讨在为其设计硬件时需要考虑的硬件与软件优化,以及通用的硬件设计原则。

为了实现这一目标,我们将采取三种核心方法:

  1. 理解机器学习应用的核心特征。
  2. 学习实现高性能与高能效的核心硬件设计原则。
  3. 通过来自业界的嘉宾讲座,了解实际部署中的挑战与行业实践。

机器学习的兴起与计算需求

上一节我们介绍了课程的整体目标,本节中我们来看看推动硬件发展的机器学习领域本身。

当我们谈论机器学习,尤其是深度学习时,有三个至关重要的组成部分:

  1. 更大的数据:数据是深度学习发展的基石。例如,ImageNet数据集的构建及其上的成功,是深度学习早期突破的关键。
  2. 更优的算法:这是机器学习研究的活跃领域,涉及新的网络架构和算子,以更好地从数据中学习。
  3. 更强的算力:计算能力是当今深度学习得以广泛应用的重要支撑。早期的成功(如AlexNet)便得益于GPU的并行计算能力。

深度学习的影响力正以两种维度扩展:

  • 应用广度:它已渗透到医疗、娱乐、安全、自动驾驶等众多领域。
  • 人才与研究的增长:相关职位需求、论文发表数量均呈指数级增长。

这种广泛的采用和深入的研究,最终转化为对计算能力的巨大需求。根据OpenAI的数据,从AlexNet到近年最先进的模型,训练所需的计算量增长了超过30万倍。这对硬件设计师而言既是挑战,也是机遇。

硬件设计的挑战与机遇

面对指数级增长的计算需求,硬件行业传统的“法宝”——摩尔定律——正面临瓶颈。晶体管尺寸的微缩带来的性能和能效提升正在放缓,同时研发成本急剧上升。

这是一个“最好的时代,也是最坏的时代”。我们面临着巨大的算力需求,但依赖已久的技术红利正在减弱,这迫使我们寻找新的解决方案。

其中最有前景的方案之一是领域专用加速器。与CPU、GPU等通用处理器不同,DSAs是为特定应用领域(如深度学习)定制设计的硬件,旨在消除通用处理的低效,实现更高的性能和能效。

例如,苹果的SoC中除了CPU和GPU,还集成了专用的“神经引擎”。这种趋势表明,为了满足不同应用的计算需求,片上集成的专用加速器正变得越来越多。

机器学习硬件生态概览

机器学习硬件的繁荣吸引了众多参与者,形成了一个充满活力的竞争生态:

  • 传统半导体巨头:如英伟达,其GPU因并行计算特性成为早期深度学习的理想平台,并持续通过Tensor Core等定制单元进行优化。
  • 初创公司:如Cerebras,其创新的晶圆级芯片突破了传统芯片尺寸的限制,展示了硬件设计的激进创新。
  • 跨界软件/系统公司:如谷歌的TPU、特斯拉的FSD芯片,这些拥有算法和数据优势的公司也纷纷进入硬件领域,以优化其整体系统。

为了公平比较不同硬件,行业建立了MLPerf等基准测试套件,这对硬件设计和选型至关重要。

课程目标:成为构建者

面对如此多的机遇与参与者,本课程的核心是让你们成为构建者。我们不仅希望你们成为机器学习的使用者或开发者,更希望你们能够构建自己的优化方案、管理系统,尤其是硬件优化方案,以实现具有竞争力的性能、能效和精度。

通过利用现代工具链的支持,即使是小团队也能取得显著成果。本课程旨在帮助你们掌握这些工具和能力。

课程具体信息与结构

现在,让我们了解本课程如何运作以实现上述目标。

我是讲师Sophia Shao,助教是Abraham。所有课程信息、Zoom链接和办公时间都会发布在课程网站和Piazza上。

课程组织如下:

  • 讲座:每周两次,包含常规讲座和8场业界嘉宾讲座。
  • 论文研读:每周一篇精选论文,帮助理解研究前沿。
  • 实验:共三个,循序渐进。
    • 实验1:聚焦机器学习框架(PyTorch)和量化实验。
    • 实验2:使用Verilog设计机器学习加速器的处理单元。
    • 实验3:基于FPGA的大规模仿真与映射优化实验。
  • 项目:学期后半段的重点,鼓励2人组队,利用提供的硬件平台进行开放式研究。
  • 考核:无考试。评分由论文研读(10%)、实验(40%)和项目(50%)构成。

先修要求:需要具备计算机体系结构和数字逻辑设计的基础知识(如EE151/CS152),并需要Verilog经验。

如何开始

  1. 注册Piazza以获取课程通知。
  2. 完成课前调查,让我们更好地了解你的背景和期望。
  3. 关注下周发布的实验1和第一篇阅读材料。

总结

本节课我们一起学习了EE2902课程的概览。我们探讨了机器学习硬件领域的核心动机:由数据和算法驱动产生的巨大算力需求,以及硬件设计在“后摩尔定律”时代面临的挑战与机遇。我们看到了一个由传统厂商、初创公司和软件巨头共同构成的活跃硬件生态。本课程的目标是让你们掌握必要的知识和技术,成为能够构建高效机器学习硬件系统的实践者。课程将通过讲座、论文阅读、动手实验和开放项目相结合的方式,引导你们深入这一领域。期待与大家共同度过这个学期。

002:深度神经网络入门

在本节课中,我们将学习深度神经网络的基础知识。我们将从机器学习的核心概念开始,逐步深入到深度学习的具体架构和原理。课程将涵盖机器学习的基本组成部分,包括任务、经验和性能度量,并特别关注深度学习如何通过分层结构自动提取特征。最后,我们将简要介绍AlexNet作为深度学习成功的一个早期关键案例。


机器学习概述

上一节我们介绍了课程背景和硬件与机器学习的关系。本节中,我们来看看什么是机器学习。

机器学习是人工智能的一个子领域,其目标是让计算机能够从经验中学习,而无需进行明确的编程。一个机器学习算法通常包含三个核心组成部分:

  1. 任务:算法需要完成的具体目标或功能,例如根据输入预测输出。
  2. 经验:算法学习所依据的数据或观察结果,即数据集。
  3. 性能度量:用于量化算法执行任务好坏的指标,例如准确率或误差。

以下是理解机器学习算法的三种范式:

  • 基于规则的系统:由人类设计者明确指定所有规则,计算机仅负责执行和评估这些规则。例如早期的国际象棋程序。
  • 经典机器学习:人类设计者手动选取或设计一些特征,然后由机器学习算法根据这些特征来学习决策规则。例如,在房价预测中,手动选取房屋面积和地理位置作为特征。
  • 深度学习:算法通过多层的分层网络结构,自动从原始数据中学习并提取特征,从简单特征逐步构建复杂特征,最终用于决策。

深度学习的关键在于其“深度”的分层结构,这使得它能够自动处理特征工程,从而在处理大规模、高维度数据时更具可扩展性。


深度学习核心概念

上一节我们了解了机器学习的整体框架。本节中,我们聚焦于深度学习的具体机制。

深度学习是机器学习的一种,其核心是使用包含多个隐藏层的神经网络。这种分层结构使得网络能够自动学习数据的层次化特征表示。

一个简单的图像识别网络可能包含以下层次:

  1. 第一层检测图像中的边缘
  2. 第二层基于边缘组合检测角点和简单形状。
  3. 第三层基于更复杂的形状组合识别完整的物体(如汽车、人脸)。

这种从简单到复杂的特征自动提取和组合,是深度学习强大能力的基础。其成功也依赖于三个关键要素:算法(模型)大规模数据集强大的计算硬件


机器学习算法组件详解

上一节我们介绍了深度学习的特点。本节中,我们回到更基础的层面,详细拆解一个机器学习算法的各个组件。

我们以垃圾邮件分类任务为例,说明三个核心组件:

  1. 任务:预测一封电子邮件是否是垃圾邮件。这是一个二分类任务,输入是邮件内容,输出是“是”或“否”。
  2. 经验:用于学习的数据集,即大量已被用户标记为“垃圾邮件”或“非垃圾邮件”的历史邮件。
  3. 性能度量:分类的准确率,即被正确分类的邮件比例。在训练过程中,我们追求此度量值的提升。

进一步地,执行一个“任务”可以分解为两个部分:

  • 模型:用于进行预测的数学结构。例如线性回归模型 y = w0 + w1*x,或复杂的深度神经网络。
  • 优化方法:用于调整模型参数以提升性能度量的算法。最常见的方法是梯度下降,它通过计算损失函数相对于模型参数的梯度,并沿梯度反方向更新参数,以最小化损失。

实例:线性回归

上一节我们以分类任务为例。本节中,我们来看一个回归任务的经典例子——线性回归,以具体化上述概念。

假设我们想根据房屋面积预测其价格。

  • 经验/数据集:已知的房屋面积和对应价格的数据点集合 (x_i, y_i)
  • 任务:给定新的房屋面积 x,预测其价格 y
  • 模型:采用线性模型 h(x) = w0 + w1*x。其中 w0 是截距,w1 是斜率。
  • 性能度量/损失函数:使用均方误差来衡量预测值与真实值的差距。公式为:
    J(w0, w1) = (1/2m) * Σ (h(x_i) - y_i)^2
    其中 m 是训练样本数量。目标是最小化 J(w0, w1)
  • 优化方法:使用梯度下降来找到使损失函数 J 最小化的参数 w0w1

数据与泛化

上一节我们讨论了算法的内部机制。本节中,我们关注算法外部的关键因素——数据。

数据集通常被划分为两部分:

  • 训练集:用于训练模型、调整参数的数据。
  • 测试集:用于评估训练好的模型在未见过的数据上表现的数据。

这种划分是为了评估模型的泛化能力,即模型对新数据的适应能力。在训练过程中,需要警惕过拟合现象:模型在训练集上表现极好(训练误差低),但在测试集上表现很差(测试误差高)。这意味着模型过度“记忆”了训练数据的细节,而非学习其普遍规律。

优化方法和损失函数的设计(如加入正则化项)有助于减少过拟合,提升模型的泛化能力。


总结

本节课中,我们一起学习了深度神经网络的基础知识。我们从区分人工智能、机器学习和深度学习等术语开始,建立了对机器学习算法核心组件(任务、经验、性能度量)的理解。我们探讨了深度学习通过分层网络自动提取特征的核心思想,并通过线性回归实例具体分析了模型、损失函数和优化方法的作用。最后,我们强调了数据集划分和模型泛化能力的重要性。这些概念为后续深入学习机器学习硬件加速技术奠定了坚实的基础。

003:深度神经网络与量化入门

在本节课中,我们将完成对机器学习流程的讨论,深入探讨深度学习,并开始介绍量化技术。这是一个充满活力的研究领域,有许多初创公司提出新想法,例如苹果公司去年收购的AI初创公司Xnor.ai,其核心技术就是低精度机器学习。

机器学习流程回顾

上一讲我们讨论了人工智能、机器学习和深度学习等术语。机器学习流程通常包含三个核心组件:经验(数据集)、性能度量(成本函数)和任务(模型与优化方法)。深度学习是机器学习的一个子集,擅长处理高维数据,并能自动从简单特征中提取复杂特征,构建层次化网络。

成本函数详解

成本函数用于量化模型预测值与期望值之间的误差,是训练过程中的性能度量指标。在线性回归中,我们常用均方误差

防止过拟合

在训练中,我们不仅要最小化训练误差,还要防止模型对训练数据过拟合,以确保其能泛化到新数据。以下是两种常用技术:

1. 正则化
正则化通过在成本函数中添加一项,来表达对更简单模型的偏好,通常意味着更小的权重。这有助于减少过拟合风险。

  • L2正则化(权重衰减):在成本函数中添加所有权重平方和的一项,公式为:Cost = Original_Cost + λ * Σ(wi²)
  • L1正则化:在成本函数中添加所有权重绝对值之和的一项,公式为:Cost = Original_Cost + λ * Σ|wi|

2. Dropout
Dropout在训练过程中,随机将网络中的一部分神经元输出置零(即“丢弃”)。这相当于同时训练了多个不同的子网络(集成学习),有助于防止模型对特定神经元的依赖,增强泛化能力。在推理时,会使用完整的网络。

优化方法详解

优化方法的目的是通过调整模型权重,最小化成本函数。最常用的方法是梯度下降

随机梯度下降

在实际训练中,我们很少使用全部数据计算梯度,而是采用随机梯度下降。它将数据集分成多个批次,每次迭代仅用一个批次的数据计算梯度并更新权重。批次大小是一个重要的超参数,会影响收敛速度和硬件利用率。

动量

为了帮助优化过程跳出局部最小值,找到全局最小值,我们引入动量的概念。动量不仅考虑当前梯度,还考虑之前权重更新的方向,形成一种“惯性”。
权重更新公式变为:v = ρ * v - η * ∇J(w)w = w + v。其中,v是动量,ρ是动量因子,η是学习率,∇J(w)是梯度。

从机器学习到深度学习

深度学习,特别是深度神经网络,因其在处理图像、语音等高维数据上的成功而成为主导模型。其核心特点是深度(多层网络)以及线性变换非线性变换的结合。

深度神经网络术语

  • :网络由输入层、输出层和多个隐藏层组成。
  • 激活:指各层节点的输出值,与输入数据相关。
  • 权重:指连接节点的边上的参数,在训练后固定,是模型固有的部分。

非线性激活函数

非线性激活函数对于网络学习复杂模式至关重要。目前最常用的是修正线性单元

  • ReLU:函数为 f(x) = max(0, x)。它计算简单,能缓解梯度消失问题,并产生大量零激活,有助于模型稀疏化,提高硬件效率。
  • ReLU变体:如Leaky ReLU,在输入为负时给予一个小的斜率,以避免神经元“死亡”。

训练与推理

  • 训练:包含前向传播(计算预测)和反向传播(根据误差计算梯度并更新权重)。涉及全部四个组件:数据、成本函数、模型和优化。
  • 推理:仅包含前向传播。使用训练好的模型和固定的权重,根据新输入数据产生预测。只涉及数据和模型。

案例:AlexNet

AlexNet是深度学习早期成功的典范。它使用了交叉熵损失函数(适用于多分类问题),并在优化中采用了我们讨论过的带动量的随机梯度下降权重衰减。其结构包含了卷积层、池化层和全连接层。

总结

本节课我们一起学习了机器学习流程的核心组件,深入探讨了成本函数中的正则化与Dropout技术,以及优化方法中的随机梯度下降与动量。随后,我们过渡到深度学习,了解了深度神经网络的基本术语、ReLU激活函数,并区分了训练与推理过程。最后,我们以AlexNet为例回顾了这些概念的应用。下节课我们将开始深入讨论量化技术。

004:量化

在本节课中,我们将深入学习量化技术,特别是其对硬件设计的影响。量化是一种通过降低数据表示精度来减少计算和存储需求的关键技术,在边缘设备的高效机器学习模型部署中尤为重要。

概述

上一节我们介绍了机器学习的基本概念和深度学习模型。本节中,我们将深入探讨数据表示,特别是量化技术。量化通过使用更低精度的数据(如8位整数代替32位浮点数)来执行计算,从而显著减少硬件资源消耗,包括计算单元的面积、能耗以及内存带宽需求。我们将从浮点数和定点数表示的基础知识开始,逐步深入到深度学习中的量化实践。

浮点数表示回顾

在计算机系统中,我们通常使用科学计数法来表示数字。对于十进制数,其形式为:
值 = 有效数字 × 10^指数
例如,6.02 × 10^23

在二进制系统中,我们使用类似的浮点数表示法:
值 = (-1)^符号位 × 有效数字 × 2^指数

一个标准的浮点数由三部分组成:

  1. 符号位:表示数值的正负。
  2. 指数位:决定数值的范围。
  3. 有效数字位(尾数):决定数值的精度。

常见的标准是IEEE 754浮点数格式,例如:

  • FP32(单精度):1位符号位 + 8位指数位 + 23位有效数字位。
  • FP16(半精度):1位符号位 + 5位指数位 + 10位有效数字位。

降低精度(如从FP32到FP16)可以减少数据存储和传输的开销,但会引入精度损失。幸运的是,深度学习模型对这类误差通常具有较好的容忍度。

定点数表示

与浮点数不同,定点数的小数点位置是固定的。这本质上是在进行整数运算,但我们需要跟踪一个“缩放因子”来理解整数所代表的实际值。

定点数的值可以通过以下公式从存储的整数值 x 重建:
真实值 y = S * x + Z
其中:

  • S 是缩放因子(斜率),决定了整数单位对应的实际值大小。
  • Z 是零点(偏置),用于调整数值范围的偏移。

例如,用3位存储整数 x

  • S=1, Z=0,则 x=7 表示 y=7
  • S=0.25, Z=0,则 x=7 表示 y=7*0.25=1.75(相当于小数点左移)。
  • S=4, Z=0,则 x=7 表示 y=28(相当于小数点右移,用3位表示了5位的范围)。

定点数运算的硬件实现(加法和乘法)比浮点数运算简单得多,因此在面积和功耗上具有显著优势。

硬件影响与动机

量化之所以重要,是因为它在硬件层面带来了巨大的效率提升。

以下是不同数据表示在硬件开销上的对比(基于较旧的45纳米工艺数据,但趋势依然成立):

  • 能耗:16位定点加法比16位浮点加法节能约8倍。
  • 面积:16位定点乘法器比16位浮点乘法器面积小10倍以上。
  • 精度间对比:16位浮点运算比32位浮点运算在面积和能耗上也有数倍的优势。

此外,降低数据位宽直接减少了模型参数的存储空间,降低了内存带宽需求。

需要指出的是,即使在“8位量化”的系统中,内部的乘累加单元可能使用更高位宽(如24位或32位)的寄存器来累积中间结果,以防止溢出,最终再将结果量化回8位输出。

深度学习中的量化

现在,我们将定点数表示应用到深度学习计算的核心——矩阵乘累加运算中。

对于一个输出激活值,其原始浮点计算为:
输出 = Σ (权重 * 输入)

当我们用量化后的值(Q表示整数值,S表示缩放因子,Z表示零点)代替原始值时,公式变为:
S_output * (Q_output - Z_output) = Σ [ S_weight * (Q_weight - Z_weight) * S_input * (Q_input - Z_input) ]

为了简化,通常假设零点 Z 为0。经过整理,我们可以得到计算量化输出的公式:
Q_output = (S_weight * S_input / S_output) * Σ (Q_weight * Q_input)

这个公式揭示了量化的核心:

  1. 核心计算Σ (Q_weight * Q_input) 是完全在整数域进行的乘累加操作,硬件效率极高。
  2. 缩放因子:比例 (S_weight * S_input / S_output) 是一个浮点常数,可以在计算前后通过简单的浮点乘法或移位操作完成。

因此,大部分繁重的矩阵运算可以用高效的整数硬件完成。

如何确定缩放因子S

缩放因子 S 的选择是量化好坏的关键。一个常见的方法是:
S = (数值范围) / (量化后范围)
例如,对于8位量化(范围0-255),如果某层激活值的实际范围是[-1.5, 2.0],则范围宽度为3.5,那么缩放因子 S = 3.5 / 255

确定“数值范围”有多种策略:

  • 最大最小值:直接使用观测到的最大、最小值。
  • 基于均值和标准差:使用 均值 ± N * 标准差 来确定范围,以排除 outliers。

在实验中将探索不同的方法对模型精度的影响。

总结

本节课我们一起深入学习了量化技术。我们从浮点数和定点数的基础表示法开始,理解了降低数据精度如何带来显著的硬件效益,包括更小的面积、更低的功耗和内存占用。接着,我们探讨了如何将定点数运算应用到深度学习的矩阵计算中,推导出了量化计算的关键公式,即将浮点计算转化为高效的整数乘累加运算加上后续的缩放调整。最后,我们讨论了确定缩放因子的策略。量化是连接高效算法与高效硬件设计的桥梁,对于在资源受限的设备上部署机器学习模型至关重要。

005:核心计算(Kernel Computation)

在本节课中,我们将要学习深度学习的核心底层操作,即计算原语(Kernel)。我们将重点探讨卷积(Convolution)和全连接层(Fully Connected Layer)的计算模式、参数及其硬件映射的含义。理解这些基础操作是设计高效机器学习硬件和软件生态系统的关键。

量化研究的延伸讨论

在上一节中,我们讨论了数据表示,特别是浮点数和定点数。本节中,我们来看看量化领域的一些最新研究方向。

除了我们讨论过的训练后量化(Post-Training Quantization),该领域还存在大量活跃研究。一个重要的方向是量化感知训练(Quantization-Aware Training)。其核心思想是在模型训练过程中就引入对权重和激活值的量化,使得最终部署的模型直接就是低精度版本。这样可以在训练时就将量化误差考虑进损失函数中,有望训练出对低精度更友好的模型。

另一个相关方向是将稀疏性(Sparsity)也引入训练过程。深度学习算子中天然存在稀疏性,如果在训练时就鼓励零值和低精度值,可能得到更易于量化的推理模型。

在浮点数格式方面,除了标准的IEEE FP16和FP32,业界也在探索更适合深度学习的格式。例如,Google的TPU和NVIDIA最新的Tensor Core GPU都支持BFloat16格式。其公式表示为:

BFloat16: 1位符号位 + 8位指数位 + 7位尾数位

与FP16(5位指数,10位尾数)相比,BFloat16牺牲了部分精度以换取更大的数值表示范围,这对于覆盖深度学习中常见的激活值范围特别有益。

微软也提出了自定义的浮点格式家族(MS-FP),旨在用最少的位数满足深度学习的精度和范围需求,并已部署在其基于FPGA的BrainWave加速器上。这些探索表明,低精度优化不仅是硬件决策,更取决于应用对精度的容忍度,需要软硬件协同设计。

卷积计算详解

现在,让我们进入今天的核心内容:卷积计算。卷积神经网络(CNN)是深度学习在计算机视觉领域取得早期突破的关键,理解其计算模式至关重要。

我们将使用以下颜色和术语约定:

  • 蓝色:输入激活(Input Activation),即上一层的输出或原始输入数据。
  • 绿色:权重(Weights),即模型训练学习到的参数。
  • 红色:输出激活(Output Activation),即本层的计算结果,将作为下一层的输入。

基础二维卷积与参数

我们从基础的二维卷积开始。假设输入是一张图像。

  • 输入激活维度:高度 H 和宽度 W
  • 权重/滤波器维度:我们用 RS 表示滤波器的高度和宽度。例如,一个3x3的卷积核,R=3, S=3
  • 输出激活维度:高度 P 和宽度 Q

卷积操作的本质是乘累加(Multiply-Accumulate)。对于输出特征图上的每一个元素,我们都需要将滤波器与输入图像上对应的局部区域进行元素级乘法,然后将所有乘积结果相加。

例如,要计算输出元素 a,需要进行 R * S 次乘法和 (R * S - 1) 次加法。这构成了最底层的计算原语。

步长(Stride)

步长 stride 定义了滤波器在输入图像上每次移动的步幅。当 stride=1 时,滤波器每次移动一个像素;当 stride=2 时,则每次移动两个像素。步长会影响输出特征图的尺寸,步长越大,输出尺寸越小。

填充(Padding)与卷积类型

  • 有效卷积(Valid Convolution):也称为无填充(No Padding)卷积。它只使用输入图像中“完全有效”的区域进行卷积,因此输出尺寸会小于输入尺寸。输出尺寸由输入尺寸 (H, W)、滤波器尺寸 (R, S) 和步长 stride 共同决定。
  • 相同卷积(Same Convolution):通过填充(Padding)零值像素,使得输出特征图的高度和宽度与输入保持一致。填充的圈数是一个可调参数。虽然在数据层面增加了零,但硬件可以通过巧妙的寻址或仅在计算单元附近填充来高效实现,开销并不大。

三维卷积:引入通道

在实际的深度学习模型中,数据通常是三维的。

  • 输入通道 C:例如RGB图像有 C=3 个通道。在深层网络中,C 可能达到数十甚至数百。
  • 此时,输入激活和权重都变为三维张量(高度 H, 宽度 W, 通道 C)。
  • 计算一个输出元素时,需要在所有 C 个通道上分别进行二维卷积,然后将 C 个结果累加。因此,计算量变为 R * S * C 次乘加操作。

四维卷积:引入输出通道与批处理

为了提取更丰富的特征,我们使用多个滤波器。

  • 输出通道 K:每个滤波器产生一个输出通道。K 定义了输出激活的深度。
  • 权重张量升级:权重变为四维张量,维度为 (K, C, R, S)。可以理解为有 K 个不同的三维滤波器(每个尺寸为 C x R x S)。
  • 计算时,使用第 k 个滤波器与输入激活进行三维卷积,得到输出激活的第 k 个通道。

最后,在训练时,我们通常以批(Batch)为单位处理数据以提高并行度和训练稳定性。

  • 批大小 N:同时处理 N 个独立输入样本。
  • 张量最终形态
    • 输入激活:(N, H, W, C)
    • 权重:(K, C, R, S)
    • 输出激活:(N, P, Q, K)

这种四维张量的布局(如NHWC或NCHW)是硬件和框架优化内存访问模式的重要考量。

循环嵌套表示

上述复杂的卷积操作可以用一个七层嵌套循环来抽象表示,这有助于我们理解计算顺序和设计硬件数据流:

for n in range(N): // 批
  for k in range(K): // 输出通道
    for p in range(P): // 输出高度
      for q in range(Q): // 输出宽度
        for c in range(C): // 输入通道
          for r in range(R): // 滤波器高度
            for s in range(S): // 滤波器宽度
              // 乘累加操作
              output[n, k, p, q] += input[n, c, p*stride + r, q*stride + s] * weight[k, c, r, s]

全连接层作为卷积的特例

全连接层(或矩阵乘法)可以看作是卷积操作的一个特例。当我们将卷积的以下参数设为1时:

  • 空间尺寸:H=1, W=1, R=1, S=1
  • 步长 stride=1
  • 填充 padding=0

此时,四维卷积操作就退化成了二维矩阵乘法:

  • 输入激活从 (N, 1, 1, C) 变为矩阵 (N, C)
  • 权重从 (K, C, 1, 1) 变为矩阵 (K, C)
  • 输出激活从 (N, 1, 1, K) 变为矩阵 (N, K)

计算简化为:

输出 = 输入 · 权重^T

因此,从硬件视角看,一个支持通用卷积的引擎,通过配置参数,也能直接执行全连接层计算。反之,也可以通过im2col等方法将卷积转换为矩阵乘法来执行。

总结

本节课中,我们一起深入学习了深度学习的核心计算原语。我们从量化的前沿研究讨论开始,然后重点剖析了卷积操作的各个维度参数(空间尺寸、步长、填充、输入/输出通道、批大小)及其对计算和存储的影响。我们看到了卷积如何通过嵌套循环抽象表示,以及全连接层如何作为卷积的一个特例。理解这些基础概念是后续学习如何将这些计算高效映射到硬件(如GPU、TPU等专用加速器)上的关键基石。下一讲,我们将进一步探讨这些计算模式在硬件上的具体映射和优化策略。

006:数据流

概述

在本节课中,我们将学习卷积运算在硬件上的执行方式,并引入“数据流”这一核心概念。我们将探讨不同的硬件执行策略,特别是数据流如何影响硬件设计的效率。课程将从回顾卷积运算的基本参数开始,然后介绍几种不同的卷积执行方法,最后深入讲解数据流的概念及其在硬件设计中的重要性。


卷积运算回顾与硬件映射

上一节我们介绍了卷积层的执行和不同的卷积参数。本节中,我们来看看这些执行如何实际映射到硬件上。

卷积运算可以用一个七层嵌套循环来描述,其核心是乘累加操作。我们用以下颜色和字母表示:

  • 蓝色:输入激活,尺寸为 H x W x C
  • 绿色:权重,尺寸为 R x S x C x K
  • 红色:输出激活,尺寸为 P x Q x K

其中,N 是批次大小。执行卷积的总乘累加操作数为 R x S x C x P x Q x K

这个循环嵌套定义了需要完成的计算,但并未指定如何执行。硬件设计的核心在于如何高效地组织这些计算和数据移动。


卷积执行的不同方法

以下是几种执行卷积运算的优化方法。

1. 直接卷积

直接卷积是最直观的方法,即严格按照循环嵌套的顺序执行乘累加操作。

  • 公式for n, p, q, k, r, s, c: output[n, p, q, k] += weight[r, s, c, k] * input[n, p+r, q+s, c]
  • 现状:早期被认为效率不高,但随着专用硬件(如GPU的张量核心)的发展,直接卷积因其简单性和硬件优化支持,已成为当前最高效、最常用的方法之一。

2. 基于矩阵乘法的卷积

此方法通过 im2col 操作将卷积转换为通用矩阵乘法。

  • 核心思想:将每个卷积窗口的输入数据展开成矩阵的一列,从而将卷积运算转化为 GEMM
  • 优势:可以利用高度优化的 GEMM 库(如 cuBLAS)。
  • 劣势im2col 操作会导致输入数据被复制多份,显著增加内存开销和带宽压力。

3. 基于快速傅里叶变换的卷积

此方法利用卷积定理,在频域进行更高效的计算。

  • 核心公式Conv(time) = IFFT( FFT(input) ⊙ FFT(weight) ),其中 表示逐元素相乘。
  • 优势:对于大尺寸卷积核(如 11x11, 13x13),能显著减少计算量。
  • 劣势FFT 变换本身有开销。现代卷积神经网络普遍使用小卷积核(如 3x3, 1x1),使得 FFT 的收益不再明显,因此当前使用较少。

4. Winograd 变换卷积

此方法通过数学变换重组计算,减少乘法次数。

  • 核心思想:将卷积计算重新关联,用更多的加法来换取更少的乘法。
  • 示例:一个 2x2 输出、3x3 权重的卷积,Winograd 算法可以将乘法次数从 6 次减少到 4 次。
  • 现状:有一定应用,但收益受限于数据移动开销,且需要硬件支持特定的数据访问模式,其普及程度不如直接卷积。

硬件设计核心原则:局部性与并行性

在深入数据流之前,我们需要理解硬件优化的两个基本原则:局部性并行性

局部性

数据移动是主要开销。局部性旨在将频繁访问的数据保存在靠近计算单元的地方。

  • 时间局部性:同一数据项在短时间内被多次使用。可通过设计缓存层次结构来优化。
  • 空间局部性:同一数据项被多个并行计算单元同时需要。可通过广播网络或片上互联来优化,以减轻内存带宽压力。

并行性

通过部署大量并行计算单元来提升吞吐量。

  • 挑战:确保所有计算单元都被充分利用(高利用率)。
  • 关键:结合空间局部性,使单一数据读取能服务多个计算单元,是保持高利用率的关键。

深度学习的卷积运算天然具有大量的数据重用机会和并行性,为应用这些硬件优化原则提供了理想条件。


数据流:定义与示例

数据流在深度学习硬件上下文中,特指执行计算和数据移动的具体顺序。它定义了硬件如何调度卷积的嵌套循环。

我们使用循环嵌套的顺序来精确描述一种数据流。不同的循环顺序意味着不同的数据重用模式和硬件结构。

输出固定数据流

在这种数据流中,最内层循环遍历权重维度,外层循环遍历输出位置。

  • 循环表示for q in Q: for s in S: # 计算
  • 特点:在连续的计算周期内,输出激活的地址保持不变(被累加),而权重和输入激活在变化。这有利于将部分和存储在靠近计算单元的寄存器中。

权重固定数据流

在这种数据流中,最内层循环遍历输出位置,外层循环遍历权重维度。

  • 循环表示for s in S: for q in Q: # 计算
  • 特点:在连续的计算周期内,权重的地址保持不变,而输入和输出激活在变化。这有利于将权重缓存起来重复使用。

“固定”一词指的是在连续计算周期内保持不变的操作数。选择哪种数据流决定了硬件需要为哪种数据(输出、权重或输入)设计更复杂的本地存储层次。


总结

本节课中我们一起学习了:

  1. 卷积的多种执行方式:包括直接卷积、im2col+GEMMFFT卷积和Winograd卷积,并了解了它们各自的优缺点及适用场景。
  2. 硬件设计核心原则局部性(时间与空间)和并行性是优化深度学习硬件性能的基石。
  3. 数据流的概念:数据流是描述计算执行顺序的框架,它通过循环嵌套的顺序来定义,并决定了哪种数据(输出、权重、输入)在计算中被“固定”重用,从而指导硬件存储层次的设计。

理解数据流是分析现代深度学习加速器(如TPU、NVDLA)设计的关键。下一节课,我们将以具体的硬件为例,深入探讨这些数据流是如何在实际芯片中实现的。

007:加速器设计原理

在本节课中,我们将学习在硬件上执行深度学习算子的硬件含义、通用硬件设计原则,以及这些原则如何在当今的深度学习硬件中体现。我们将从加速器的历史背景谈起,深入探讨其核心设计优化策略。

概述

近年来,从大型公司到初创企业,都在为机器学习等新兴应用构建专门的硬件引擎。构建加速器或进行所谓的领域特定架构加速并非全新的概念。在计算机硬件设计史上,许多成功的想法会反复出现。例如,早期的领域特定加速器就是协处理器,特别是浮点协处理器。在个人计算机早期,英特尔386处理器没有浮点流水线,而387则作为独立的浮点加速器提供给需要高效执行浮点运算的客户。这说明了领域特定加速或硬件加速的理念早已存在,并在计算需求量大、要求高吞吐量的应用推动下,得到了新的发展。

上一节我们介绍了数据流的概念,它用于描述计算的执行顺序。本节中,我们将探讨如何在硬件上实现不同的执行顺序,特别是数据流中最内层循环的执行顺序,并分析其对性能和可扩展性的影响。

数据流在硬件中的体现

我们使用数据流来描述执行顺序,并通过循环嵌套表示法来具体说明。通过结合时间循环空间循环,我们可以利用数据局部性和并行性。以下是两种在当今深度学习硬件设计中常用的数据流。

输出驻留数据流

顾名思义,输出驻留数据流意味着在(最内层循环)执行期间,输出数据保持不变。

在循环嵌套表示中,输出索引 Q 在最内层循环中不发生变化,因此输出保持“驻留”。而输入和权重的索引则在最内层循环中变化。

硬件含义:由于同一输出数据被重复访问,存在时间局部性。为了利用这一点,硬件设计中通常会添加一个专用的输出激活寄存器来缓存该数据,从而减少对更大容量SRAM的访问。

权重驻留数据流

权重驻留数据流意味着在(最内层循环)执行期间,权重数据保持不变。

在相应的循环嵌套中,权重索引与最内层循环无关,因此权重被重用。

硬件含义:由于同一权重数据被重复使用,硬件设计中会添加一个专用的权重寄存器来缓存该权重值,以减少对权重缓冲区的访问。

设计权衡:在实际高效的硬件设计中,通常会结合使用这两种策略,并可能使用多入口寄存器。需要仔细权衡寄存器大小和复杂度,因为输出激活通常是32位宽,而权重可能是8位,减少输出激活的SRAM访问通常能带来更大的能效收益。

为何需要加速器:通用计算的效率瓶颈

为了理解加速器的优势,让我们先看看通用处理器在执行深度学习核心运算(如矩阵乘法)时的效率瓶颈。一个简单的三层矩阵乘循环,在通用RISC-V核上直接编译后,会发现大量指令周期花费在数据索引、地址计算和循环控制等“管理开销”上,而非核心的乘加计算。

一项关于视频解码应用的能量分析研究揭示了通用计算中的主要效率瓶颈:

  • 指令获取与解码:获取和解码大量细粒度指令的开销非常显著。
  • 数据缓存访问:频繁的数据移动也消耗大量能量。
  • 核心计算:实际在功能单元(如乘法器、加法器)中执行计算所消耗的能量占比反而较小。

这些“管理开销”对于维持处理器的通用性和灵活性是必要的,但对于执行固定的、计算密集型的深度学习算子而言,则成为了主要的效率瓶颈。这促使我们转向更专用的加速器设计。

加速器核心优化策略

基于上述效率分析,加速器设计主要围绕降低“管理开销”和提升“计算吞吐”展开。

策略一:粗粒度指令集

为了降低指令处理(取指、译码)的开销,深度学习加速器通常采用粗粒度指令集

  • 指令数量少:指令集非常精简,只包含数据搬运和核心计算等少数几种指令。
  • 指令粒度粗:每条指令对应一个高级操作(如执行一个完整的256x256矩阵乘法),可以持续成百上千个周期,完成海量底层操作。硬件内部通过状态机或专用控制器来处理细粒度的循环和索引,而无需反复取指译码。

示例:谷歌TPU的指令集主要包含:从主机内存加载数据到缓冲区、将权重加载到权重缓冲区、执行矩阵乘法/卷积、执行非线性激活函数、将结果写回主机内存。

这种设计将能量和周期更多地集中在实际计算上,而非指令管理上。在软件层面,类似的优化思想体现为算子融合,即将卷积、激活、池化等连续操作合并执行,减少中间数据的搬运。

策略二:并行数据通路设计

粗粒度指令意味着单条指令蕴含巨大的并行计算潜力。如何设计数据通路来高效支持这种并行性?我们通过将循环嵌套中的某些维度映射为空间循环来实现。

考虑矩阵乘法 C[M][N] = A[M][K] * B[K][N]。我们主要关注两个维度的并行化:

1. 空间K映射(累加维度并行)

将缩减维度 K 映射为空间循环,意味着同时进行 K 个乘加操作,然后对部分和进行累加。

实现方式A:加法树

  • 描述:使用一个组合逻辑加法树,在同一周期内完成多个部分和的累加。
  • 优点:在并行度(K值)不大时非常高效,无需在树中添加流水线寄存器。
  • 缺点:当并行度很大时,加法树深度增加,关键路径变长,可能不得不插入流水线寄存器,影响扩展性。output = sum( A[i] * B[i] for i in range(K) ) (通过加法树硬件实现)

实现方式B:脉动累加

  • 描述:在累加路径的每一步都插入寄存器,使部分和像流水一样在寄存器链中传递并逐步累加。
  • 优点:关键路径短(仅为一次乘加),高度规则,扩展性极佳,非常适合大规模并行设计(如TPU的256x256阵列)。
  • 缺点:每一步都需要进行寄存器读写,在并行度较小时可能不如加法树紧凑。P_sum[0] = 0; for i in range(K): P_sum[i+1] = P_sum[i] + (A[i] * B[i])

2. 空间N映射(输出维度并行)

将输出维度 N 映射为空间循环,意味着同时计算输出矩阵的一整行(或一整列)。

核心挑战与实现:此并行模式的关键在于单播输入数据的多播。同一个输入元素需要被分发到所有并行计算单元中。

实现方式A:直接连线

  • 描述:通过物理连线将输入寄存器直接扇出到所有计算单元。
  • 优点:简单直接,延迟低。
  • 缺点:当并行单元数量很多时,长连线的物理设计(时序、功耗)变得复杂。

实现方式B:脉动多播

  • 描述:在输入分发的路径上也插入寄存器链,让输入数据通过寄存器逐级传播到各个计算单元。
  • 优点:信号规整,易于物理实现和扩展。
  • 缺点:引入了额外的寄存器开销和初始延迟。

组合案例

  • NVDLA风格:可能采用 空间N(直接连线多播) + 空间K(加法树累加)
  • TPU风格:采用 空间N(脉动多播) + 空间K(脉动累加),构成了其著名的二维脉动阵列。

关于存储层次:在高效加速器设计中,计算单元通常不直接访问大型SRAM。为了最大化数据复用和最小化能耗,会在SRAM和计算单元之间加入多级寄存器或寄存器文件,用于缓存输入激活、权重和部分和(输出激活)。

总结

本节课我们一起学习了深度学习硬件加速器的核心设计原理。我们从历史背景了解到,领域特定加速并非新概念。我们深入探讨了输出驻留权重驻留数据流及其硬件实现含义。通过分析通用处理的效率瓶颈,我们引出了加速器两大核心优化策略:1)采用粗粒度指令集以降低指令管理开销2)设计并行数据通路以挖掘计算并行性。在并行数据通路设计中,我们重点分析了空间K映射(累加并行)的加法树与脉动累加实现,以及空间N映射(输出并行)的直接多播与脉动多播实现,并了解了这些基础模式如何组合成现代加速器(如NVDLA、TPU)的架构。下一节课,我们将继续探讨加速器设计中的内存优化策略。

008:高效神经网络的量化方法

概述

在本节课中,我们将学习神经网络量化的基本概念、方法及其在高效部署中的关键作用。量化通过将高精度数值(如FP32)映射到低精度表示(如INT8),可以显著减少模型的内存占用、计算能耗并提升推理速度。我们将从量化基础开始,逐步深入到高级主题和前沿研究方向。

基本概念

上一节我们概述了量化的重要性,本节中我们来看看量化的一些核心概念和不同方法。

均匀量化与非均匀量化

量化是将一个实数域中的值映射到低精度整数值的过程。例如,将范围在[-2.5, 5.0]的FP32值映射到8位整数(0-255)。

均匀量化将实数范围均匀地划分为多个区间(桶),每个区间映射到一个整数。其数学公式可表示为:
r = S * (q - z)
其中,r是实数值,S是缩放因子(scale),q是量化后的整数值,z是零点(zero-point),用于精确表示实数0。

然而,神经网络权重和激活值的分布通常不是均匀的(例如,呈高斯分布)。非均匀量化试图在值密集的区域分配更多的量化级别,理论上能获得更好的精度。但非均匀量化在硬件上部署效率低下,通常需要查找表,因此当前主流研究集中在均匀量化上。

对称量化与非对称量化

在确定量化范围时,我们使用裁剪范围[α, β]。如果选择α = -β,则称为对称量化,此时零点z自动为0,计算得以简化。如果α ≠ β,则称为非对称量化

对称量化虽然简单,但在某些场景下并不高效。例如,在ReLU激活函数之后,所有值都是非负的,使用对称量化会浪费一部分比特去表示永远不会出现的负值区间。此时,非对称量化是更优的选择。

逐层量化与逐通道量化

对于一个神经网络层,我们可以为整个层的所有权重选择一个统一的量化参数(α, β),这称为逐层量化。然而,同一层中不同的卷积核或通道可能具有不同的值分布范围。

因此,更优的做法是逐通道量化,即为每个通道或卷积核单独计算量化参数。这样做几乎没有额外开销,并能更准确地捕捉数据分布,从而获得更高的量化精度。

动态量化与静态量化

对于权重,由于其值在训练后是固定的,我们可以预先(静态地)计算其量化参数。但对于激活值,其范围可能因输入数据而变化。

  • 静态量化:在部署前,使用一个校准数据集来预先确定激活值的量化范围。这种方法速度快,但可能因输入分布变化而精度下降。
  • 动态量化:在运行时实时计算每个输入激活的张量范围,并据此进行量化。这种方法通常更准确,但由于计算范围需要额外开销,在硬件上执行速度较慢。

训练后量化与量化感知训练

这是决定量化工作流程的另一个关键区别。

  • 训练后量化:在模型训练完成后,直接对权重和激活进行量化,不进行任何重新训练。这种方法非常快速,甚至是“即插即用”的,但在低精度(如INT4)下可能导致显著的精度损失。
  • 量化感知训练:在模型训练(或微调)过程中,模拟量化的效果,让模型权重能够适应量化带来的误差。这种方法能显著提升低精度量化的模型精度,但需要额外的训练时间和计算资源。

高级概念与核心方法

上一节我们介绍了量化的基本分类,本节中我们来看看实现量化时更深入的技术细节和挑战。

伪量化与纯整数量化

在研究和部署中,量化算法的实现方式至关重要,主要分为两类:

  • 伪量化(或模拟量化):在训练或评估时,权重和激活以量化形式存储,但实际的前向计算(如矩阵乘法)仍在浮点数(如FP32)上进行。这种方法便于研究和快速验证,但无法获得硬件加速带来的实际速度提升,且在某些操作(如残差连接、批归一化)上可能与真实硬件行为存在差异。
  • 纯整数(或定点)量化:所有计算,包括乘加累加,都在整数域进行。累加通常在更高位宽的整数(如INT32)中进行,然后通过缩放舍入操作将结果映射回低精度(如INT8)。这是能在实际硬件上获得加速的正确方式。

实现纯整数量化的一个巧妙方法是二值量化,即将缩放因子S约束为2的幂次方的倒数。这样,在从高精度累加结果向低精度量化值转换时,复杂的浮点除法可以简化为高效的整数乘法和位移操作。

以下是纯整数量化中卷积运算的简化表示:

# 假设对称量化,忽略零点z
# W_q: 量化后的权重 (INT8)
# X_q: 量化后的输入 (INT8)
# S_w, S_x: 权重和输入的缩放因子
# S_y: 输出的缩放因子

# 在整数域进行乘加累加,结果用更高精度(如INT32)存储
accumulator_int32 = int32_matmul(W_q, X_q)
# 缩放并量化回INT8
Y_q = round(accumulator_int32 * (S_w * S_x / S_y))

混合精度量化

将整个网络的所有层统一量化到极低精度(如INT4)通常会导致严重的精度损失。混合精度量化的核心思想是:并非所有层对量化误差的敏感度相同。我们可以为网络中的不同层分配合适的比特宽度。

如何自动确定每层的最佳精度呢?一个关键洞察是利用损失函数景观。对于一个训练好的模型,如果我们轻微扰动某一层的参数,并观察损失函数的变化:

  • 如果损失变化剧烈(景观“陡峭”),说明该层对参数变化敏感,应分配较高精度(如INT8)。
  • 如果损失变化平缓(景观“平坦”),说明该层对参数变化不敏感,可以分配较低精度(如INT4)。

通过将每层的精度选择建模为一个优化问题(例如,在满足整体模型大小和延迟约束下,最小化精度损失),我们可以系统地搜索出最优的混合精度配置。


硬件协同设计与未来方向

上一节我们探讨了通过算法优化来提升量化效果,本节中我们来看看如何将算法与硬件特性协同设计,以达到极致的效率。

硬件感知的神经网络设计

传统的网络设计(如ResNet、MobileNet)主要追求更高的准确率。但在资源受限的边缘设备上,我们需要硬件感知的神经网络设计。这意味着在设计网络时,就将目标硬件的特性(如计算峰值、内存带宽、缓存大小)考虑在内。

例如,深度可分离卷积虽然参数少,但其算术强度低,意味着它受限于内存带宽而非计算能力。在某些硬件上,即使将其计算精度从FP32降到INT8,也可能无法获得显著的加速,因为瓶颈在于数据搬运。因此,针对特定硬件,可能需要减少这类层的使用,或调整网络结构。

神经架构搜索与硬件协同设计

自动化这一过程的方法是硬件感知的神经架构搜索。其基本流程如下:

  1. 定义一个包含多种基础操作(如3x3卷积、1x1卷积、深度可分离卷积)的搜索空间。
  2. 在目标硬件上精确测量每种操作的性能(延迟、能耗)。
  3. 训练一个随机超网络,该网络以概率形式包含所有可能的操作路径。
  4. 通过优化,使超网络学习到的路径采样概率分布能够满足目标硬件上的性能约束(如最大延迟),同时保持高准确率。
  5. 从训练好的超网络中采样,即可得到为特定硬件量身定制的高效网络架构。

更前沿的方向是硬件与算法的协同设计:不仅根据现有硬件设计网络,也根据目标工作负载(如一组特定的神经网络模型)来共同设计硬件架构本身(如处理单元阵列的大小、内存层次结构等)。这是一个充满挑战但潜力巨大的开放研究领域。


总结

本节课中我们一起学习了神经网络量化的核心知识。我们从基本概念入手,区分了均匀/非均匀、对称/非对称、动态/静态、训练后/量化感知训练等不同量化方法。接着,我们深入探讨了高级概念,明确了伪量化与纯整数量化的区别,并介绍了通过混合精度量化来突破低精度瓶颈的策略。最后,我们展望了硬件协同设计的未来,包括硬件感知的NAS以及算法-硬件联合优化这一激动人心的方向。

量化是使深度学习模型得以在资源受限环境中高效部署的关键技术,它连接了算法创新与硬件加速,是机器学习硬件领域不可或缺的一部分。

009:Chipyard & FireSim 教程 🚀

在本节课中,我们将学习伯克利研究基础设施的核心:Chipyard 和 FireSim。我们将了解它们如何协同工作,为机器学习硬件设计提供从RTL生成到性能评估的完整流程。课程的后半部分将指导你完成FireSim在AWS上的设置,为实验三做好准备。


概述 📋

Chipyard是一个集成了多种开源硬件IP(如处理器核心、加速器、缓存)和工具链的框架,用于快速构建和配置片上系统(SoC)。FireSim则是一个基于FPGA加速的仿真平台,能够对Chipyard生成的SoC设计进行快速、准确的性能仿真。本节课将介绍这两个工具的基本概念、工作流程,并手把手指导你完成FireSim在AWS云平台上的初始设置。


Chipyard 基础 🏗️

上一节我们概述了课程内容,本节中我们来看看Chipyard的具体构成。

Chipyard旨在解决开源硬件IP集成和性能评估的挑战。它不是一个单一的IP,而是一个组织和集成各种生成器(Generators)与工具的环境。

核心组件与流程

Chipyard包含多个流程,允许你针对不同的目标(如软件仿真、FPGA仿真、流片)进行设计。

  • 软件仿真流程:这是你在实验二中使用的流程。你修改RTL(如Gemini加速器),通过Firrtl编译器生成Verilog,最后使用VCS或Verilator等工具进行仿真。
  • FireSim流程:这是实验三将使用的流程。设计通过特定的构建过程转换,然后交由FireSim进行基于FPGA的加速仿真。
  • VLSI流片流程:设计经过面向流片的转换后,可接入名为“Hammer”的VLSI流程,最终生成可用于制造的版图。

核心语言:Chisel 🔨

Chipyard的基础设施主要基于Chisel构建。Chisel是一种嵌入在Scala中的硬件构造语言,其核心优势在于创建参数化生成器,而非单一的硬件实例。

以下是一个用Chisel编写的简单移动平均滤波电路示例:

class MovingAverage extends Module {
  val io = IO(new Bundle {
    val in = Input(UInt(32.W))
    val out = Output(UInt(32.W))
  })
  val reg = RegNext(io.in)
  io.out := (io.in + reg) >> 1.U
}

通过Scala的高级特性,我们可以轻松地将其参数化为一个通用的FIR滤波器:

class FirFilter(consts: Seq[SInt]) extends Module {
  val io = IO(new Bundle {
    val in = Input(SInt(32.W))
    val out = Output(SInt(32.W))
  })
  val taps = Seq(io.in) ++ consts.map { c =>
    val reg = RegNext(io.in)
    reg * c
  }
  io.out := taps.reduce(_ + _)
}

Chisel代码通过Firrtl编译器处理,Firrtl可以类比为LLVM。它接收Chisel代码,进行一系列优化和转换,最终输出针对不同后端(如仿真、FPGA、ASIC)的Verilog代码。

关键IP:Rocket Chip 与 BOOM 🚀

Chipyard的核心SoC生成器是Rocket Chip。它提供了一个可重用的SoC组件库和创建自定义SoC的API。

  • Rocket Core:默认的按序执行RISC-V CPU核心,支持RV64GC扩展,可启动Linux并支持加速器。
  • BOOM (Berkeley Out-of-Order Machine):高性能超标量乱序执行核心,可作为Rocket Core的直接替代品,支持相同的软件栈。

加速器(如Gemini)通过Rocket协处理器接口(RoCC) 连接到核心,允许执行自定义指令并与内存子系统交互。

系统集成与配置

如何将所有IP集成并配置成一个完整的SoC是一大挑战。Chipyard通过以下方式解决:

  1. Diplomatic参数协商:用于解决不同IP模块间参数(如总线位宽、地址空间)的自动协商问题,确保系统正确连接。
  2. 基于Scala的配置系统:允许用户通过简洁的Scala代码从底层向上构建系统。例如,你可以从一个基础配置开始,逐步添加特定核心、缓存和加速器。

以下是一个配置示例的简化概念:

// 这是一个概念示例,非实际代码
class MySoCConfig extends Config(
  // 添加基础Rocket配置
  new BaseRocketConfig ++
  // 使用BOOM核心
  new WithBoomCore ++
  // 添加Gemini加速器
  new WithGeminiAccel ++
  // 配置L2缓存
  new WithL2Cache(size="512KB")
)

FireSim:FPGA加速仿真 ⚡

上一节我们介绍了用于构建SoC的Chipyard,本节中我们来看看如何用FireSim对SoC进行高性能仿真。

FireSim的目标是为流片前的设计提供全系统、周期精确的仿真,以加速验证、确认和软件开发流程。

核心理念

FireSim不是简单的FPGA原型设计,而是FPGA加速的仿真器。关键区别在于时序解耦

  • 问题:如果直接将SoC RTL部署到FPGA上(原型),由于FPGA通常运行频率(如100 MHz)低于目标硅频率(如1 GHz),会导致内存访问延迟等时序特征失真,无法获得准确的性能数据。
  • FireSim解决方案:在FPGA上实现目标设计(Target)时,加入一个解耦层。每个FPGA时钟周期模拟一个目标时钟周期,而像DRAM访问这样的延迟则被建模为精确的周期数。这样就能在较慢的FPGA上获得与目标硅频率一致的性能仿真结果。

架构与工作流程

FireSim主要包含两部分:

  1. 编译器:接收Chipyard设计,生成用于FPGA仿真的网表和相关文件。
  2. 管理器:在AWS上编排和管理仿真任务。你可以通过一个“管理实例”(头节点)来启动“构建农场”(编译设计)和“运行农场”(在多个FPGA实例上执行仿真)。

优势与应用

FireSim能实现快速、大规模且功能丰富的仿真:

  • 性能评估:获得真实的硬件性能数据,用于设计空间探索。
  • 大规模仿真:可扩展至模拟数据中心级别的千节点系统,成本远低于实际搭建。
  • 强大调试:支持波形输出、printf合成、断言检查等,调试能力接近软件仿真器。
  • 开源:整个平台完全开源。

AWS 与 FireSim 实践设置 🛠️

前面我们学习了Chipyard和FireSim的理论知识,本节我们将进行FireSim在AWS云平台上的实践设置。请跟随以下步骤操作。

重要提示:在收到课程提供的AWS促销码之前,请勿在账户中添加信用卡信息或进行任何会产生费用的操作。你可以先熟悉流程,收到促销码后再完成设置。

第一步:创建AWS账户并设置区域

  1. 访问 AWS官网 并创建新账户。账户类型选择“个人账户”。
  2. 使用你的伯克利邮箱等信息完成注册。
  3. 登录AWS控制台,在页面右上角将区域(Region)设置为“美国东部(弗吉尼亚北部)us-east-1”。这是唯一支持F1 FPGA实例的区域。

第二步:申请提升F1实例限额

新AWS账户默认无权启动F1实例。

  1. 在控制台找到“EC2”服务并进入。
  2. 在左侧导航栏找到“限额(Limits)”。
  3. 点击“请求增加限额(Request limit increase)”。
  4. 在搜索框中输入“EC2”,选择“所有F实例”。
  5. 区域选择“US East (N. Virginia)”,将新限额值设置为64(最终可能批准为16)。
  6. 在用例描述中填写:“用于EE290课程,使用FireSim进行硬件仿真,需要F1实例。”
  7. 提交请求。通常会在几小时到一天内通过。

第三步:填写表单获取促销码

填写课程提供的Google表单,提交你的姓名、学号、邮箱和AWS账户ID。课程助教将通过邮件向你发送价值200美元的AWS促销码和预构建的AMI镜像访问权限。

第四步:设置密钥对

  1. 在EC2控制台左侧导航栏,找到“密钥对(Key Pairs)”。
  2. 点击“创建密钥对”。
  3. 名称输入 firesim,密钥对类型选择“RSA”,私钥文件格式选择“.pem”。
  4. 创建并妥善保存下载的.pem文件。这是后续登录实例的凭证。

第五步:(收到促销码后)兑换并启动临时实例

  1. 在AWS控制台,进入“账单仪表板(Billing Dashboard)”,选择“积分(Credits)”,兑换收到的促销码。
  2. 返回EC2控制台,点击“启动实例(Launch Instance)”。
  3. 选择“Amazon Linux 2 AMI”。
  4. 实例类型选择“t2.nano”(这是免费套餐可选的低成本实例)。
  5. 在“配置安全组”等步骤使用默认设置,直到“审核和启动”。
  6. 在最后一步,系统会提示选择密钥对。在下拉菜单中选择之前创建的 firesim 密钥对,然后启动实例。

第六步:在临时实例上配置AWS CLI

  1. 实例启动后,在EC2控制台获取其“公有IPv4地址”。
  2. 在本地终端,使用以下命令SSH连接到实例(将<path-to-key><public-ip>替换为实际值):
    chmod 600 <path-to-key>/firesim.pem
    ssh -i <path-to-key>/firesim.pem ec2-user@<public-ip>
    
  3. 在实例中,运行 aws configure 命令。你需要提供AWS访问密钥。
    • 获取密钥:在AWS控制台右上角点击你的用户名 -> “安全凭证(Security Credentials)” -> “访问密钥(Access Keys)” -> “创建新的访问密钥”。下载CSV文件。
    • aws configure 提示符下,依次输入CSV文件中的访问密钥ID、秘密访问密钥、区域(us-east-1)和输出格式(json)。

第七步:运行FireSim首次设置脚本并订阅AMI

  1. 在临时实例的SSH会话中,根据FireSim文档或助教在聊天中提供的命令,运行一系列以 sudo yum install python3 ... 开头的安装命令。
  2. 看到“Success”提示后,在EC2控制台终止(Terminate) 这个t2.nano实例,避免产生不必要的费用。
  3. 最后,通过FireSim文档提供的链接,订阅“FPGA Developer AMI”。点击“接受条款(Accept Terms)”。此过程可能需要30分钟到1小时完成。

第八步:启动FireSim管理实例(开始实验三时进行)

当你准备开始实验三时,需要启动一个长期运行的管理实例。

  1. 启动实例时,在AMI选择页面,搜索并选择课程提供的特定AMI(例如 Berkeley Firesim Manager AMI - Spring 2021)。你可能需要在“共享给我(Shared with Me)”选项卡中查找。
  2. 实例类型建议选择 r5.large(性能与成本平衡)。
  3. 关键配置
    • 在网络设置中,选择“firesim”网络。
    • 在安全组设置中,选择现有的“firesim”安全组。
    • 启用“终止保护”。
  4. 启动时,同样选择 firesim 密钥对。
  5. 启动后,使用SSH登录该管理实例,将本地的 firesim.pem 文件复制到实例上的 ~/.ssh/ 目录。
  6. 按照实验三文档说明,在实例中设置环境变量(通常通过 source 命令),然后即可开始使用 firesim 命令来管理你的仿真任务。

费用监控提醒 💸

务必定期通过AWS的“账单仪表板”监控你的积分使用情况。当积分消耗接近150美元时,应格外小心,如需更多资源请及时联系助教。200美元的积分应足够完成实验三。


总结 🎯

本节课我们一起学习了伯克利机器学习硬件研究的两大核心基础设施。

  • Chipyard 是一个强大的SoC设计框架,它集成了丰富的开源硬件IP(如Rocket Chip, BOOM),并通过Chisel语言和灵活的配置系统,让快速构建和定制复杂SoC成为可能。
  • FireSim 是一个基于FPGA加速的仿真平台,它通过时序解耦技术,在云上实现了对Chipyard生成设计的快速、精确的性能仿真,支持大规模系统模拟和深度调试。
  • 最后,我们逐步完成了在AWS上设置FireSim运行环境的实践指南,为接下来的实验三做好了准备。

掌握这些工具将极大地助力你的硬件设计、仿真和评估工作。

010:映射

在本节课中,我们将要学习如何将机器学习计算任务映射到专用的硬件加速器上。我们将探讨映射问题的核心概念、需要考虑的硬件约束、以及不同的映射策略如何影响性能和效率。

概述

映射,有时也称为分块、调度或编译,是指将特定维度的计算问题(如一个神经网络层)映射到特定硬件架构上的过程。这个过程需要考虑问题本身的维度(如矩阵大小)和硬件的具体规格(如计算单元阵列大小、片上缓存容量)。目标是找到一个正确的执行顺序,使其能在目标硬件上高效运行。

上一节我们介绍了硬件加速器的核心计算原语和架构设计。本节中,我们来看看如何将计算任务有效地映射到这些硬件上。

映射问题与硬件约束

映射问题有两个关键输入:一是问题特定的配置(如神经网络层的类型和维度),二是硬件特定的规格。我们需要结合这两者来找到一个高效的执行顺序。

以下是映射过程中需要考虑的主要硬件约束。

1. 脉动阵列尺寸

硬件加速器(如Google TPU或AWS Inferentia)通常采用脉动阵列设计,其尺寸(如128x128)是固定的。然而,实际的计算问题(如矩阵乘法)维度(M, K, N)可能远大于这个硬件尺寸。

解决方案:通过添加时间循环来进行分块。硬件尺寸由空间循环表示,而超出硬件尺寸的部分则通过额外的时间循环来处理。

例如,对于一个2x2的脉动阵列(空间循环N0和K0的循环边界为2),要计算更大的矩阵,我们添加时间循环N1和K1:

for m in range(M):
    for n1 in range(N1):
        for k1 in range(K1):
            # 硬件并行执行 (n0:2, k0:2) 部分
            for n0 in range(2):
                for k0 in range(2):
                    # 计算核心

这样,大问题被分解成多个小块,由硬件分多次执行。

2. 片上缓存容量

在专用加速器中,数据移动通常需要由程序员显式管理,通过特定的指令将数据加载到片上缓存(如权重缓存、输入激活缓存)。这与CPU中由缓存层次结构隐式管理数据不同。

核心约束:映射方案必须确保每次加载到片上缓存的数据量不超过该缓存的容量,否则会导致无效的执行或错误结果。

解决方案:通过添加更多层的时间循环,将数据块进一步切分得更小,以适应有限的缓存大小。

例如,如果权重矩阵(大小 N x K)超过了权重缓存的容量,我们不能一次性全部加载。我们需要添加一个外层时间循环,每次只加载权重矩阵的一个子集:

for n2 in range(N2):
    # 将部分权重(大小 N1 x K)移动到权重缓存
    move_in(weights[n2*N1:(n2+1)*N1, :])
    for m in range(M):
        for n1 in range(N1):
            for k1 in range(K1):
                # ... 计算部分

反之,如果片上缓存容量大于当前分块所需,我们可以考虑加载更大的数据块,以更好地利用缓存并可能重叠计算与通信。

3. 内存层次结构

现代加速器可能具有更复杂的内存层次,例如共享缓存或邻近缓存(如AWS架构中所述)。这引入了数据共享的机会,但也会影响访问延迟和带宽。映射策略需要考虑这些层次,通过添加更多循环层级来利用数据局部性。

映射空间的维度

为了更结构化地理解映射选择,我们可以将其分解为几个关键维度。

以下是映射决策的三个主要维度。

循环顺序

循环嵌套中各个循环的排列顺序会影响数据移动量,从而影响性能。

示例:考虑一个包含循环 M2(输入激活相关)和 N2(权重相关)的内核。不同的循环顺序会导致输入激活被重复加载的次数不同。

  • M2 为外层循环,N2 为内层循环,则对于每个 M2 块,权重需要被整体加载一次,但输入激活块可能被重复使用。
  • 若顺序交换,则对于每个 N2 块,输入激活需要被整体加载一次,而权重块可能被重复使用。
    最优顺序取决于 MN 的相对大小以及片上缓存容量。

循环边界

即每个循环的迭代次数(分块大小)。这直接由硬件约束决定:

  • 下限:必须满足片上缓存容量限制,确保数据块能放入缓存。
  • 优化目标:在满足容量限制的前提下,最大化缓存利用率,平衡计算与数据移动,以实现高性能和高能效。

空间化选择

此维度涉及将某些循环从“时间循环”转换为“空间循环”,以利用多个并行硬件单元(如多个加速器核或芯片)。

模型并行:将权重维度(如 N)的空间化。即将权重的不同部分分布到不同的加速器上。每个加速器持有模型的一部分。
spatial for n in range(2): # 在两个加速器间分配权重

数据并行:将输入激活维度(如 M)的空间化。即将输入数据批次的不同部分分布到不同的加速器上。每个加速器处理不同的输入数据。
spatial for m in range(2): # 在两个加速器间分配输入数据

映射调优的挑战

映射空间非常庞大,针对不同硬件和不同网络,最优映射可能截然不同。手动寻找最优解无法扩展。因此,该问题自然演变成一个自动调优优化问题

目标有两个:

  1. 找到高性能的映射:最小化内核执行时间或能耗。
  2. 快速找到解决方案:编译/调优时间本身也需要很短。

目前的研究方向包括使用启发式搜索、遗传算法、强化学习等机器学习方法来自动探索巨大的映射空间,以期快速找到接近最优的配置。

总结

本节课中我们一起学习了机器学习计算任务的映射问题。

  • 我们了解到映射需要同时考虑问题维度硬件约束,后者主要包括计算并行度(脉动阵列大小)和内存容量(片上缓存大小)。
  • 我们探讨了通过操作循环嵌套(添加时间循环、调整循环顺序和边界)来满足约束并优化性能。
  • 我们介绍了映射空间的三个关键维度:循环顺序循环边界空间化选择(对应模型并行与数据并行)。
  • 最后,我们认识到由于映射空间的复杂性和问题依赖性,自动调优已成为该领域的重要研究方向,旨在高效地寻找兼具高性能和短编译时间的映射方案。

理解这些映射概念对于设计高效的硬件加速器及其配套软件栈至关重要。

011:数据编排

在本节课中,我们将深入学习数据编排。数据移动在硬件设计中至关重要,尤其是在深度学习加速器的背景下。我们将探讨数据编排的核心概念、设计原则,并通过一个分类法来系统化地理解不同的数据移动策略。

上一节我们讨论了计算映射的挑战,本节中我们来看看数据移动的具体机制。

数据移动的重要性

数据移动在硬件设计中扮演着关键角色。在深度学习加速器中,数据移动消耗的能量通常比计算单元(ALU)本身还要多。下图展示了典型深度学习加速器中不同内存层级访问的能量消耗对比。

此外,片上存储(如缓冲器)不仅消耗大量能量,也占据了芯片面积的很大一部分。因此,高效的数据编排对于优化性能和能效至关重要。

什么是数据编排?

数据编排不仅仅是数据的被动移动,它更强调有目的地优化和管理数据传输,以满足特定的性能目标。任何数据编排方案都需要考虑两个核心方面:

  1. 数据供给:确保数据在功能单元需要时,能够及时地出现在正确的位置。
  2. 数据释放:当数据不再被需要时,应尽快将其从缓冲区中释放,以腾出空间供其他数据使用。

以下是设计数据编排方案时需要考虑的一些具体问题:

  • 何时发起传输? 太早会浪费缓冲区空间,太晚则会导致计算单元空闲等待。
  • 数据应放置在何处? 需要将数据放置在靠近消费者的位置,以获得良好的数据局部性。
  • 谁是消费者? 需要明确数据的最终使用者,这关系到数据的目的地。
  • 如何同步? 当有多个消费者时,需要同步机制来确保数据访问的正确性。
  • 数据的访问模式是什么? 是顺序流式访问,还是带步长的访问?了解模式有助于优化。
  • 何时可以释放数据? 消费者使用完毕后,应尽快释放数据以重用缓冲区空间。

数据编排的设计原则

以下是指导高效数据编排的几个核心原则:

  • 局部重用:利用数据局部性,通过内存层次结构(如缓存)将频繁使用的数据保存在靠近计算单元的地方。
  • 空间重用:支持多播,让多个消费者高效地共享同一份数据,减少内存访问开销。
  • 高效利用带宽:充分利用片上和外部的内存带宽。
  • 传输与计算重叠:在计算单元执行任务的同时,让内存系统忙于获取后续所需的数据,以隐藏内存延迟。例如,双缓冲就是一种实现此目标的简单技术。
  • 精确同步:只在必要时进行同步,避免代价高昂的全局同步,确保正确性的同时最小化开销。
  • 控制成本:在实现复杂编排方案时,需权衡其带来的面积和功耗成本,优先采用简单的结构。

数据编排的分类法

为了系统化地理解不同的数据移动策略,我们引入一个基于两个维度的分类法。首先,我们需要明确数据移动交易中的四个关键角色:

  1. 生产者:当前持有数据的代理。
  2. 消费者:将消费数据的代理。
  3. 请求者:发起数据请求的代理。它可能与消费者是同一个实体,也可能是独立的。
  4. 分发者:负责定位数据所在(例如在内存层次结构中的位置),并将数据从生产者路由到消费者的代理(例如缓存系统)。

维度一:耦合 vs. 解耦

这个维度关注请求者消费者是否是同一个代理。

  • 耦合架构:请求者和消费者是同一个代理(例如,CPU流水线既发出加载指令,也消费返回的数据)。这是当今通用CPU的主流设计。
    • 优点:设计简单直观。
    • 缺点:在数据返回前,需要预留存储空间(如寄存器),可能导致资源利用率不高。
  • 解耦架构:请求者和消费者是分离的代理(例如,独立的“访问切片”和“执行切片”)。
    • 目标:让请求者提前运行,预取数据,从而在消费者需要时数据已准备就绪,以隐藏内存延迟。
    • 挑战:需要复杂的同步机制来确保请求和消费的顺序正确匹配。

维度二:隐式 vs. 显式

这个维度关注请求者是否明确知道生产者的位置,是否需要分发者

  • 隐式数据移动:请求者不知道数据的具体位置,依赖分发者(如缓存层次结构)来定位和获取数据。
    • 示例:CPU的load指令。
    • 优点:对程序员透明,易于编程。
    • 缺点:需要复杂的硬件结构(如缓存标签、MSHR等),带来较高的面积和功耗开销。
  • 显式数据移动:请求者明确知道数据的源地址和目的地址,直接发起传输。
    • 示例:GPU中将数据从全局内存复制到共享内存的操作,或加速器中的DMA传输。
    • 优点:硬件开销低,效率高。
    • 缺点:需要程序员或编译器显式管理数据移动,编程更复杂。

这两个维度是正交的,可以组合成四种类型的数据编排策略。

案例研究

以下是四种组合的具体案例:

  1. 隐式+耦合

    • 描述:请求者/消费者统一,且依赖隐式分发(缓存)。
    • 典型示例:现代通用CPU的缓存层次结构。
    • 特点:易于编程,通用性强,但硬件开销大。
  2. 隐式+解耦

    • 描述:请求者(访问切片)和消费者(执行切片)分离,但仍使用隐式缓存进行数据分发。
    • 典型示例:“解耦访问/执行”架构的研究论文。
    • 特点:旨在隐藏延迟,但同步复杂,在通用计算中较难广泛应用。
  3. 显式+耦合

    • 描述:请求者/消费者统一,但数据移动是显式管理的。
    • 典型示例:GPU的共享内存编程模型。程序员需要显式地将数据从全局内存cudaMemcpy到共享内存,然后在同一个SM(流多处理器)内进行计算。
    • 特点:比完全隐式控制更精细,但编程负担仍在单个执行单元内。
  4. 显式+解耦

    • 描述:具有独立的请求者(如DMA引擎)和消费者(计算单元),并进行显式的数据搬运。
    • 典型示例:绝大多数现代领域专用加速器(如Google TPU、许多AI芯片)采用的方式。它们使用DMA引擎提前将数据从主存搬运到片上的暂存器(Scratchpad)。
    • 特点:硬件效率高,允许计算与数据传输充分重叠。这是加速器设计的首选方案,但需要专门的编程模型或编译器支持来管理显式数据移动。

总结

本节课中我们一起学习了数据编排的核心概念。我们了解到数据移动是硬件,特别是深度学习加速器设计中的关键瓶颈。高效的数据编排需要平衡及时供给及时释放。我们介绍了一个有用的分类法,通过耦合/解耦隐式/显式两个维度,将各种数据移动策略系统化地组织起来。通用CPU通常采用隐式+耦合的缓存系统以追求易编程性,而追求极致效率的领域专用加速器则普遍采用显式+解耦的DMA方式。理解这些策略的优缺点,有助于我们在设计或选择硬件时做出更好的权衡。

012:稀疏性

在本节课中,我们将探讨机器学习算法与硬件协同设计中的一个重要交叉领域:稀疏性。我们将了解为什么神经网络中存在大量零值,以及如何利用这些零值来设计更高效的硬件。课程将涵盖稀疏性的来源、在存储和计算中利用稀疏性的方法,并分析当前硬件广泛采用稀疏性支持所面临的挑战。

稀疏性的来源与重要性

上一节我们介绍了算法与硬件协同设计的背景,本节中我们来看看为什么稀疏性是一个重要的优化机会。

神经网络中的核心计算操作(如卷积和矩阵乘法)本质上是乘积累加运算。当输入激活或权重中的任何一个操作数为零时,乘法结果为零,该计算是无效的。研究表明,在许多神经网络中,权重和激活值中有高达50%至90%是零值。这为减少存储开销和计算量提供了巨大潜力。

以下是稀疏性的主要来源:

  • 激活值中的稀疏性:ReLU等非线性激活函数会将所有负值置零,这是激活值中零值的主要来源。即使在训练过程中,某些层的激活值密度也可能很低。
  • 权重中的稀疏性
    • 剪枝:将模型中不重要的、值很小的权重直接置零。
    • 正则化:在训练过程中,通过L1正则化等方法倾向于产生更小、更稀疏的权重,这也能间接引入零值。

权重稀疏性在模型部署中尤其有价值,因为权重在训练后是静态的,便于进行静态优化。

结构化稀疏与非结构化稀疏

在利用稀疏性之前,需要理解一个关键区别:结构化稀疏与非结构化稀疏。

  • 非结构化稀疏:零值随机分布在数据中,没有固定模式。虽然能带来理论上的存储和计算节省,但由于需要复杂的索引和间接寻址来跳过零值,在硬件上实现高效支持非常困难,甚至可能导致性能下降。
  • 结构化稀疏:零值以某种可预测的模式出现(例如,固定比例、整行/整列为零)。硬件可以针对这些模式进行高效优化。例如,英伟达的Tensor Core支持特定压缩比(如2:1)的结构化稀疏权重。

目前,商业硬件对非结构化稀疏的支持有限,部分原因在于其硬件实现开销较大。而结构化稀疏由于更容易实现,正开始被采纳。

存储中的稀疏性:压缩格式

既然数据中存在大量零值,一个自然的想法是通过压缩来减少存储和传输的数据量。支持压缩格式更多是软件和库层面的优化,已被广泛采用。

以下是几种常见的压缩格式:

  • 位掩码:为原始数据中的每个元素使用一个比特来标记其是否为零(1为非零,0为零)。同时,只存储非零值数组。其优点是简单规整,但元数据开销固定。当数据精度较低(如4位或8位整型)时,该开销会变得显著。
  • 游程编码:不单独记录每个零,而是记录连续零值的“游程”长度。它用一个计数器来记录两个非零值之间连续零的个数。这种格式在存在长串连续零时效率很高,但其效果和开销高度依赖于数据模式。
  • 压缩稀疏行/列:这是科学计算和高性能计算中处理稀疏矩阵的标准格式,在机器学习框架中也得到广泛支持。
    • CSR 使用三个数组:values(存储非零值)、column_indices(存储每个非零值所在的列索引)、row_ptr(存储每行非零值在values数组中的起始和结束位置)。它便于进行行访问。
    • CSC 格式与CSR类似,但按列优先顺序存储,便于列访问。

随着机器学习中多维张量的普及,出现了将CSR/CSC思想推广到多维空间的尝试(例如TACO编译器项目),旨在允许每个维度独立选择稠密或稀疏的存储格式。这种通用化的表示方法可能为未来硬件设计提供有潜力的通用原语。

计算中的稀疏性:硬件机制

在计算中跳过零值操作是硬件加速器研究的重点。根据稀疏性出现在一个还是两个操作数,以及数据对齐的方式,可以将硬件机制分为三类。

1. 间接机制

当只有一个操作数(如权重)稀疏,另一个操作数稠密时,硬件需要根据稀疏操作数的非零元素索引,去间接访问稠密操作数中对应的元素进行计算。

核心思想:使用稀疏张量的非零元素索引作为指针,来获取稠密张量中对应的数据。

例如,在稀疏矩阵与稠密向量乘法中,硬件需要一个间接单元,根据稀疏矩阵非零元素的位置(列索引j),去读取稠密向量x中对应的元素x[j]

2. 交集机制

当两个操作数(权重和激活)都稀疏时,目标是只对两个操作数都非零的元素对执行计算。这需要找到两个稀疏索引集的交集。

核心思想:并行比较两个稀疏操作数的索引,仅当在两个操作数中同一位置都找到非零值时,才触发乘法运算。

硬件上通常表现为一个并行比较器阵列,用于快速匹配两个稀疏输入的非零索引。

3. 仲裁机制

这是一种不同的思路,以SEN加速器为代表。它放弃在输入端对齐稀疏的权重和激活,而是允许所有非零权重和激活自由进入计算单元相乘。由于不知道乘积结果应该累加到哪个输出位置,因此在后端需要一个复杂的仲裁逻辑,将产生的部分和路由到正确的输出累加器中。

核心思想:计算总是会发生,难点在于将结果归位。通过输出端的仲裁来替代输入端的对齐。

这种方法避免了前端复杂的索引匹配逻辑,但将开销转移到了后端的仲裁网络上。

总结与挑战

本节课我们一起学习了机器学习中的稀疏性。我们探讨了稀疏性的来源(ReLU、剪枝、正则化),区分了结构化与非结构化稀疏的差异。接着,我们了解了在存储中利用稀疏性的常见压缩格式(位掩码、游程编码、CSR/CSC)。最后,我们深入分析了在计算中跳过零值的三种主要硬件机制:间接、交集和仲裁。

尽管稀疏性研究在过去几年非常热门,但在商业硬件中的广泛采用仍然有限,尤其是对于非结构化稀疏。主要挑战在于:

  1. 支持非结构化稀疏所需的索引和间接访问开销可能抵消其带来的收益。
  2. 稀疏模式高度依赖于数据和模型,通用的高效硬件支持设计困难。
  3. 需要整个软件栈(框架、编译器、库)的协同支持。

未来,结构化稀疏和更通用的稀疏张量表示(如TACO)可能为硬件设计提供更可行的路径。理解这些基本原则,有助于我们评估层出不穷的稀疏加速器提案。

013:软硬件协同设计

在本节课中,我们将要学习软硬件协同设计的概念、重要性及其在机器学习硬件领域的应用。我们将探讨硬件优化与软件优化如何相互影响,并了解当前研究中的一些关键趋势。


概述

软硬件协同设计是指在设计过程中,同时考虑并优化硬件和软件,以实现特定的性能、吞吐量、延迟、功耗或尺寸等目标。在机器学习领域,这通常涉及到一个多目标优化问题,需要权衡多种因素。

上一节我们讨论了稀疏性及其在硬件中的挑战,本节中我们来看看更广泛的协同设计概念。


为何协同设计至关重要

在讨论特定领域的硬件时,设计过程通常需要考虑该领域应用的需求,并思考如何提高效率。我们之前讨论过专业化或定制化,包括控制粒度、并行计算以及数据编排。

然而,即使在一个特定领域内,也存在不同的权衡。例如,我们可能希望进行高度专业化,但也需要支持该领域内不同应用或原语的差异。这引出了一个微妙的问题:在专业化策略上,我们应该走多远?


数据流设计的权衡

数据流设计是硬件优化的一个关键方面。我们讨论过两种常见的数据流:权重驻留和输出驻留。权重驻留数据流在寄存器级别重用权重,而输出驻留数据流则重用输出。

以下是两种数据流在能量消耗上的典型分解对比:

  • 权重驻留数据流:权重缓冲区访问能耗较低(例如占总能耗的35%),但累加缓冲区访问能耗成为主导(超过50%),因为每个周期都需要访问部分和。
  • 输出驻留数据流:累加缓冲区访问能耗显著降低(例如降至10%),但权重缓冲区访问能耗增加,因为每个周期都需要访问权重。

这个分析表明,很难断言哪种数据流总是更优。其效率取决于多种因素,包括应用特性、缓冲区大小、内存层次结构以及精度。因此,设计过程需要考虑这些依赖关系,而不是寻找一个“放之四海而皆准”的解决方案。


支持灵活性的硬件优化

认识到数据流选择的复杂性后,一个自然的思路是让硬件更具灵活性,以支持多种数据流模式。

一种方法是在权重缓冲区和累加缓冲区前都设置小型寄存器集合(称为收集器)。这样,硬件可以根据具体场景灵活地分配寄存器,支持多级数据流,从而可能比固定单一数据流的架构更高效。

这种微架构层面的优化,即使在张量核心或处理单元内部,也能通过增加灵活性来适应不同的设计场景,提升效率。


应用多样性对硬件设计的影响

硬件设计的权衡不仅存在于微架构层面,也受到应用多样性的影响。即使是同一个神经网络,不同层也可能偏好不同的数据流。

研究表明,对于某些网络层,权重驻留数据流更优;而对于其他层,输出驻留数据流更优。这进一步说明了硬件设计不应过于特化,而应增加一定的灵活性,允许用户根据需求进行配置,以更高效地处理多样性。

除了数据流,其他硬件参数如向量大小(脉动阵列中的网格维度)和量化精度,也会与软件算法产生交互影响,共同决定最终的准确性和硬件成本。理解这些交互是进行协同设计空间探索的关键。


软件端的协同设计趋势

接下来,我们简要讨论软件端考虑硬件成本进行优化的趋势。在协同设计讨论中,通常从以下三个角度展开:

  1. 剪枝:减少网络中的参数或计算量。
  2. 紧凑网络设计:手动设计更高效的网络结构。
  3. 神经架构搜索:自动搜索高效的网络架构。

剪枝与硬件感知

剪枝是一种通过将权重或激活值置零来引入稀疏性,从而减少内存占用和计算量的技术。早期的剪枝工作主要关注间接指标,如参数数量或FLOPs的减少。

然而,这些间接指标并不总能转化为实际的性能或能效提升,因为其收益高度依赖于硬件对稀疏性的支持效率。因此,出现了硬件感知剪枝的研究。

硬件感知剪枝在优化过程中,会通过硬件估计工具来评估剪枝操作是否能带来真实的能耗或延迟收益,而不仅仅是参数数量的减少。这使得优化目标更直接地关联到硬件性能。


紧凑网络设计

除了在现有网络结构上剪枝,另一种思路是直接设计更高效、更紧凑的网络结构。例如,MobileNet系列网络中引入了深度可分离卷积

标准卷积的计算量可以表示为:
计算量 ≈ K * C * R * S * 输出高度 * 输出宽度

深度可分离卷积将其分解为两步:

  1. 深度卷积:对每个输入通道独立进行空间卷积(R * S),没有跨通道计算。计算量约为 C * R * S * 输出高度 * 输出宽度
  2. 逐点卷积:使用1x1卷积进行跨通道信息融合。计算量约为 K * C * 1 * 1 * 输出高度 * 输出宽度

这种设计显著降低了理论计算量和参数量。然而,它也改变了数据复用模式,对硬件实现提出了新的挑战,例如可能导致硬件利用率下降。因此,在评估这类“高效”算子时,需要结合具体的硬件特性进行分析。


神经架构搜索

神经架构搜索旨在自动化地寻找高性能的网络架构。早期的NAS工作也主要优化间接指标(如FLOPs)。近期的趋势是引入硬件感知的NAS,在搜索过程中直接优化延迟、能耗等硬件相关指标,从而找到在目标硬件上真正高效的网络结构。


总结

本节课中我们一起学习了软硬件协同设计在机器学习硬件中的核心思想。我们了解到:

  • 协同设计是一个并发的硬件与软件优化过程,旨在达成多项目标。
  • 硬件设计(如数据流选择)存在复杂的权衡,没有单一的“最优解”,需要结合应用特性和硬件参数进行探索。
  • 软件端的优化(如剪枝、网络设计)越来越需要硬件感知,直接优化性能/能效指标,而非间接的理论指标。
  • 当前的研究趋势是增加硬件的灵活性以应对多样性,并在软件算法设计中更深入地考虑硬件行为,从而实现更有效的协同优化。

通过理解这些协同设计的原理和趋势,我们可以更好地评估机器学习硬件或系统的提案,并洞察其创新性与重要性。

014:其他算子与近数据处理

在本节课中,我们将完成关于软硬件协同设计(特别是神经架构搜索)的讨论,并探讨一些尚未深入讨论的其他重要算子。这些算子通常具有较低的计算-内存比,这引出了“近数据处理”的话题。我们还将回顾一个重要的早期项目——智能内存(IRAM),并探讨其与现代架构研究的联系。

神经架构搜索(NAS)回顾

上一节我们介绍了软硬件协同设计的理念,本节我们将深入了解神经架构搜索(NAS)的具体细节。NAS旨在自动寻找高效的神经网络架构,而非依赖人工设计。

以下是NAS流程的三个核心组成部分:

  1. 搜索空间:定义了所有可能网络架构的集合,包括层类型、连接方式、通道数、深度等超参数。
  2. 搜索策略:用于在庞大的搜索空间中高效导航的算法,例如强化学习、进化算法或可微分搜索。
  3. 性能评估:评估候选架构性能的方法,传统上侧重于准确率,现在也越来越多地考虑目标硬件上的延迟、能耗等指标。

一个关键趋势是将硬件性能反馈整合到NAS流程中。例如,针对iPhone和三星手机分别搜索出的网络,在各自目标硬件上的延迟性能显著优于在对方硬件上运行的性能,尽管它们的准确率和计算量(FLOPs)相近。这凸显了为特定硬件定制网络架构的价值。

其他重要算子分析

到目前为止,我们的讨论主要集中在卷积和全连接(矩阵乘)算子上。然而,在实际部署(如数据中心)中,其他类型的算子也占据了重要地位。

逐元素运算

逐元素运算对两个相同尺寸的张量进行按位操作,如加法、乘法。其计算模式可表示为:
C[i,j] = A[i,j] op B[i,j]
其中 op 代表加法或乘法等操作。

这类运算在LSTM、残差网络等模型中非常常见。尽管从算法角度看它们似乎“免费”(不增加参数量,计算简单),但从硬件角度看,它们具有极低的数据复用率,属于内存带宽密集型操作。

以ResNet-50中的残差加法层为例:当我们在系统级(SoC)设计上面临选择——是将更多芯片面积分配给加速器的本地暂存器(Scratchpad)还是共享的二级缓存(L2)时,不同算子的偏好不同:

  • 卷积层受益于更大的本地暂存器,因为其数据复用率高。
  • 残差加法层则几乎无法从更大的本地暂存器中获益,因为它本质上是流式操作。但在多核共享L2的场景下,更大的L2缓存有助于减少片外内存访问。

因此,即使是不起眼的逐元素运算,也可能对系统级内存架构决策产生重大影响。

嵌入查找层

嵌入查找层在推荐系统中至关重要,用于将稀疏的高维特征(如用户ID、商品ID)转换为稠密的低维向量。其核心操作可视为一个稀疏矩阵-向量乘法。

在具体实现中(如Caffe2的SparseLengthsSum算子),由于批处理的存在,它通常转化为稀疏矩阵-矩阵运算。其挑战在于如何处理间接内存访问和非规则的数据模式。优化手段包括利用稀疏性、缓存热点嵌入表项等。这本质上将问题引向了我们之前讨论过的稀疏线性代数领域。

从Facebook数据中心的经验来看,推荐模型大量使用了嵌入查找和全连接层,这解释了为什么在全数据中心范围内,全连接层比卷积层消耗了更多的计算时间。

近数据处理与智能内存(IRAM)项目

当我们讨论计算-内存比较低的算子时,自然会想到如何通过减少数据移动来提升性能,即“近数据处理”的理念。这让我们回想起约20年前在伯克利启动的智能内存(IRAM)项目。

IRAM项目的核心假设是:将处理器逻辑和DRAM内存集成在同一块芯片上,从而极大提升内存带宽,缓解“内存墙”问题。在此基础上,研究者探索了向量处理器等架构,以充分利用高带宽。

尽管将逻辑和DRAM的制造工艺集成在同一芯片上面临巨大技术挑战,至今仍未完全实现,但IRAM的研究催生了向量处理器架构等宝贵成果。其思想在现代以芯粒(Chiplet)为基础的异构集成技术中得以延续,即通过先进封装将不同工艺制造的处理器芯片和内存芯片集成在一起,提供高带宽互连。

这个案例说明了架构研究与底层技术的紧密互动:一个愿景可能因技术路径的变化而未能直接实现,但其探索过程往往能催生其他重要的创新。

课程总结与后续安排

本节课我们一起学习了神经架构搜索(NAS)的完整流程及其与硬件协同设计的关联,分析了几种关键但常被忽视的算子(逐元素运算、嵌入查找)的特性及其对硬件设计的影响,并回顾了近数据处理思想的早期实践——IRAM项目。

总结要点如下:

  1. NAS是实现软硬件协同自动优化的重要工具,其搜索结果可针对特定硬件进行定制以获得最佳性能。
  2. 逐元素运算等低计算-内存比算子对系统内存层次结构的设计有独特影响,不能因其计算简单而忽视。
  3. 嵌入查找等算子的核心挑战可归结为稀疏计算和间接访问问题。
  4. 近数据处理是一个长期的研究愿景,其实现形式随着半导体技术的发展而演变。

后续课程安排:
春假后,我们将迎来一系列嘉宾讲座,来自业界和学术界的专家将分享在机器学习硬件领域的实践经验,包括MLPerf基准测试、谷歌TPU的设计洞见以及存内计算的前沿挑战。请大家利用春假时间充分休息,并为期末项目做好准备。项目提案请于本周五前提交。

015:训练流程与核心算子

在本节课中,我们将深入探讨机器学习训练流程中的核心计算算子。我们将回顾训练的基本流程,并将其与我们已经熟悉的推理过程进行对比。通过分析前向传播、反向传播和权重更新这三个核心计算,我们将理解它们在硬件实现上的异同,以及从推理硬件扩展到训练硬件所需考虑的关键因素。


训练流程回顾

在之前的课程中,我们主要聚焦于推理过程,即模型的前向传播。然而,完整的机器学习训练流程包含更多组件。

一个典型的机器学习算法包含三个核心部分:

  1. 数据集:用于学习的经验数据。
  2. 性能度量(损失函数):用于评估模型预测好坏的反馈机制。
  3. 任务(模型):我们试图学习并优化的函数。

训练过程不仅包括前向传播以进行预测,还包括根据损失函数的反馈来更新模型的反向传播。因此,训练流程可以概括为:

  • 前向传播:输入数据通过模型,得到预测输出。
  • 损失计算:比较预测输出与真实标签,计算误差(损失)。
  • 反向传播:将误差从输出层向输入层反向传播,计算模型参数的梯度。
  • 权重更新:根据计算出的梯度,更新模型的权重参数。

本节中,我们将重点关注反向传播阶段涉及的两个核心计算:梯度反向传播和权重更新。


核心计算算子分析

在硬件层面,我们关心的是这些流程对应的基础计算原语。我们将使用统一的颜色和维度表示法进行分析:

  • 绿色:权重(Weights),维度为 [R, S, C, K](卷积核高、宽、输入通道、输出通道)。
  • 蓝色:输入激活(Input Activations),维度为 [N, P, Q, C](批次、图像高、宽、输入通道)。
  • 红色:输出激活(Output Activations),维度为 [N, P, Q, K](批次、图像高、宽、输出通道)。
  • 带虚线的张量:表示对应张量的梯度。

理解这些计算的一个有效方法是关注归约维度,即在计算过程中被累加求和并最终在输出中消失的维度。

1. 前向传播(推理)

这是我们已深入讨论过的部分。其计算本质是卷积或矩阵乘法。

公式/代码描述(以类GEMM形式表示):
输出[N, P, Q, K] = 输入[N, P, Q, C] * 权重[R, S, C, K]
其中,需要在维度 R, S, C 上进行归约(累加)。

关键点:

  • 归约维度R, S, C。这些维度在输出中不存在。
  • 硬件映射:在脉动阵列等硬件中,通常沿归约维度进行数据流编排,以实现乘积累加。

2. 反向传播(计算输入梯度)

此步骤的目标是将输出层的梯度传播到输入层,计算输入激活的梯度(dInput)。

核心变化:

  • 输入与输出互换:将前向传播的输出梯度作为输入,目标是计算输入梯度。
  • 归约维度改变:归约维度从 (R, S, C) 变为 K(输出通道数)。

公式/代码描述:
输入梯度[N, P, Q, C] = 输出梯度[N, P, Q, K] * 权重转置[K, R, S, C]
其中,需要在维度 K 上进行归约。

涉及的额外操作:

  • 权重转置:为了将 K 维度变为可归约的维度,需要对权重张量进行转置操作。
  • 列到图像转换:如果计算是以类GEMM形式完成的,可能还需要一个后处理步骤将结果转换回标准的图像(激活)格式。

3. 权重更新(计算权重梯度)

此步骤的目标是计算权重的梯度(dWeight),以便后续更新权重。

核心变化:

  • 输出变为权重梯度
  • 归约维度改变:归约维度变为 N, P, Q(批次和图像空间维度)。

公式/代码描述:
权重梯度[R, S, C, K] = 输入[N, P, Q, C] * 输出梯度转置[N, P, Q, K]
其中,需要在维度 N, P, Q 上进行归约。

涉及的额外操作:

  • 输出梯度转置:为了将 (N, P, Q) 维度对齐为归约维度,需要对输出梯度张量进行转置操作。

从推理硬件到训练硬件

基于以上分析,我们可以得出以下结论:

  1. 核心计算不变:训练中的三个核心算子(前向、反向传播、权重更新)本质上仍然是矩阵乘法或类矩阵乘法操作。这是许多硬件公司能够相对快速地从支持推理扩展到支持训练的根本原因。
  2. 数据变换增多:训练流程引入了额外的数据预处理和后处理操作,主要是转置数据格式重组(如im2col和col2im),以确保数据以正确的维度布局送入计算单元。
  3. 性能调优更复杂:由于归约维度在不同算子间发生变化((R,S,C), K, (N,P,Q)),硬件(尤其是编译器)需要处理更多样化的矩阵形状和尺寸组合。性能高度依赖于具体问题的维度,这对性能调优和分块策略提出了更高要求。
  4. 精度要求:虽然本节课未深入讨论,但训练通常需要更高的数值精度(如混合精度训练中的BF16)或特殊的硬件支持来管理梯度,这也是设计训练硬件时需要考虑的重要因素。

总结

本节课中,我们一起学习了机器学习训练流程的完整计算图景。我们回顾了训练与推理的区别,并深入剖析了训练中三个核心计算算子:前向传播、梯度反向传播和权重更新。通过关注“归约维度”这一关键概念,我们清晰地看到了这些算子在计算模式上的相似性与差异性。主要的差异体现在归约维度的变化以及由此带来的数据变换操作上。理解这些底层原语,有助于我们把握从推理硬件扩展到训练硬件时所面临的核心挑战与机遇,即:在保持高效矩阵乘法核心的同时,增强对数据布局变换的支持和更灵活的维度适应性。

016:加速器级并行性

概述

在本节课中,我们将学习加速器级并行性。我们将从单个加速器设计的视角中跳出来,从系统层面审视多个专用IP核如何协同工作,以及这种集成带来的机遇与挑战。我们将回顾计算机架构中利用并行性的历史,并重点探讨在移动SoC和数据中心场景下,如何通过硬件与软件的协同设计来管理异构加速器资源,以实现更高的性能和效率。


从历史视角看并行性

上一节我们介绍了课程的整体方向,本节中我们来看看计算机架构如何通过不同层级的并行性来提升性能。这是一个贯穿硬件设计历史的核心思想。

比特级并行性

比特级并行性是最基础的层级,它通过增加数据通路的宽度(例如从32位到64位)来并行处理更多信息。在指令集架构和底层电路设计中都有体现。

  • 核心思想:使用更宽的位宽(如64位ALU)一次处理更多数据。
  • 现代趋势:在机器学习等领域,出现了反向趋势,即采用低精度计算(如INT8、FP16)。公式表示为:低精度 = 减少位宽 -> 更高能效 -> 释放资源用于其他并行性。这并非放弃并行,而是通过优化每个操作的成本来换取系统层面更大的并行潜力。

指令级并行性

指令级并行性是通用处理器设计的基石,旨在通过硬件机制(如流水线、乱序执行、推测执行)挖掘单个线程内的并行性,并对软件完全透明。

  • 核心思想:硬件自动识别并并行执行无依赖关系的指令,无需程序员干预。
  • 设计哲学:在硬件内部创建一个“魔法区”,所有复杂性由硬件管理,软件接口保持简洁。这体现了硬件设计师对抽象层的忠诚维护。

线程级并行性与数据级并行性

当指令级并行性的提升遇到瓶颈时,架构开始向软件暴露更多复杂性,以利用更粗粒度的并行性。

  1. 线程级并行性:通过多核/多处理器系统并行执行多个线程。软件(程序员或运行时系统)需要负责线程创建、同步和通信。这标志着硬件“魔法区”的边界开始扩展,将部分责任移交给了软件层。
  2. 数据级并行性:通过向量单元或GPU对大量数据执行相同的操作。编程模型(如CUDA、OpenCL)需要显式地管理数据并行任务。硬件与软件之间的协作区域变得更大、更复杂。

过渡:从指令级到线程/数据级并行性的演变,是一个硬件控制权逐渐下放、软硬件协同设计区域不断扩大的过程。这为理解当前的加速器级并行性奠定了基础。


加速器级并行性

上一节我们回顾了并行性利用的历史演进,本节中我们来看看其最新的前沿——加速器级并行性。

什么是加速器级并行性?

随着摩尔定律放缓,仅靠通用核心的提升已不足够。领域专用架构兴起,导致现代SoC集成了众多异构计算单元:CPU集群(大小核)、GPU、NPU、DSP、ISP等。ALP关注的是如何协调这些异构的、可能同时工作的加速器,让它们高效协作以完成共同任务(如处理一帧图像),而非独立运行。

移动SoC中的现状与挑战

现代移动SoC是ALP的典型代表。其特点包括:

  • 高度异构:集成多种为不同任务优化的IP核。
  • 高度并发:单个用户任务(如视频录制)可能涉及CPU、GPU、ISP、编码器等多个加速器。
  • 市场碎片化:存在数百种不同的SoC设计,各有其专属的加速器和驱动库。

以下是当前面临的主要挑战:

1. 可编程性与抽象
如何为众多异构加速器设计统一的编程模型和软件栈?现状是各厂商提供私有库,导致应用优化困难且碎片化。例如,Facebook研究发现,为覆盖大部分设备需要适配海量SoC,最终他们往往选择仅优化通用的CPU/GPU路径。

2. 并发管理与调度
当多个加速器需要协同工作时,由谁(硬件、操作系统、运行时库)来负责调度、资源共享和依赖管理?硬件需要提供足够的可配置性和状态可见性,以支持高效的软件调度。

3. 通信与资源共享
加速器间通信常通过低效的DMA拷贝进行。如何设计高效的片上互连和缓存一致性协议,以实现加速器间的低延迟数据共享?代码示例的挑战在于缺乏标准:

// 理想情况:高效的数据共享
data = accelerator_a.process(input);
accelerator_b.consume(data); // 希望data能快速传递,而非通过内存拷贝

4. 庞大的设计空间
SoC架构师需要在面积、功耗、性能、灵活性之间做出权衡。设计空间随加速器数量指数级增长,需要更好的建模和设计探索工具。


总结

本节课中我们一起学习了加速器级并行性这一前沿概念。我们从计算机架构利用并行性的历史脉络讲起,经历了比特级、指令级、线程级和数据级并行性,最终看到当前系统级芯片正朝着集成多种异构加速器的方向发展。ALP的核心挑战在于如何定义和管理硬件与软件之间不断扩大的“协同设计区”,以解决可编程性、并发调度、高效通信和复杂设计空间探索等问题。这不仅是技术的演进,更是设计哲学从“硬件隐藏一切”向“软硬件协同暴露与优化”的转变。理解这一趋势,对于未来参与高性能、高能效计算系统设计至关重要。

017:神经网络与TPU设计

在本节课中,我们将跟随Google的Cliff Young,探讨神经网络设计的思考,特别是TPU的设计理念。我们将从科学探索与工程实践的辩证关系出发,审视当前机器学习革命中的机遇与挑战,并深入了解TPU等专用加速器的设计思路与未来方向。


科学革命与工程实践

上一节我们介绍了课程背景,本节中我们来看看Cliff Young对当前机器学习领域科学探索与工程实践关系的看法。

计算机科学作为一个学科,其名称中明确包含“科学”一词,这有时令人感到不安。我们正处于机器学习革命的一个有趣节点:工程实践领先于科学理解。科学与工程之间的对话,对于我们在构建机器和理解机器学习技术潜力方面取得深刻进展至关重要。

工业革命的历史提供了一个类比。詹姆斯·瓦特在1770年左右发明了早期蒸汽机,但直到大约80年后,开尔文勋爵和热力学领域才为其提供了坚实的科学解释。如果我们能更早地理解其背后的科学原理,或许就能更快地开发出像丰田普锐斯这样高效的产品。

同样,对于TPU和神经网络,我们是否因为忙于构建“蒸汽机”而错过了发现“电力”的机会?我们是否因为缺乏对神经网络内部复杂动力学的科学理解,而无法构建出更高效的架构?这是当前面临的核心问题。


计算机架构革命与TPU的诞生

上一节我们讨论了科学与工程的关系,本节中我们来看看机器学习如何驱动了计算机架构的革命。

2012年AlexNet在ImageNet竞赛中的突破性表现,开启了现代深度学习时代。这一突破得以实现,很大程度上得益于NVIDIA在通用GPU(GPGPU)上的投资。NVIDIA牺牲了一年的图形性能,使GPU变得更可编程,从而为神经网络计算提供了前所未有的强大算力。

在Google内部,我们注意到矩阵乘法消耗了数据中心总CPU周期的1%,这是一个强烈的需求信号。虽然GPU性能强大,但其成本在Google的规模下变得非常高昂。这促使我们启动了TPU项目

以下是TPU v1的核心设计要点:

  • 专精于推理:TPU v1被设计为专用于神经网络推理的协处理器。
  • 脉动阵列:核心是一个256x256的脉动阵列矩阵乘法器,包含65536个算术逻辑单元。
  • 量化算术:采用8位整数运算,而非传统的32位浮点数,以大幅提升能效和性能。
  • 激进的时间表:从项目正式启动到在数据中心部署,仅用了15个月。
  • 显著的性能提升:与当时的CPU和GPU相比,在性能和能效上均获得了超过10倍的提升。

TPU v1可能是世界上第一台真正的“矩阵机器”。随后的TPU v2转向了更通用的训练任务,这要求支持浮点运算、大规模数据并行,并构建了包含256个计算节点的“Pod”级系统。TPU v3则引入了水冷技术,进一步提升了计算密度。


深度学习加速器的现状与未来

上一节我们回顾了TPU的发展历程,本节中我们来看看整个深度学习加速器领域的现状。

过去几年出现了深度学习加速器的“寒武纪大爆发”,有超过100家初创公司投身于此。市场在推理训练方面出现了分化:

  • 推理市场将趋于碎片化,因为不同场景(数据中心、手机、物联网设备)对功耗、成本和性能的要求差异巨大。
  • 训练市场则呈现出令人惊讶的架构趋同。无论是Google TPU、NVIDIA A100、华为昇腾,还是其他主要参与者,其训练芯片在高层面上都采用了相似的技术组合:密集计算单元(通常是脉动阵列)+ 高带宽内存(HBM)+ 专有高速互连

这种趋同意味着训练可能正在形成一个通用的计算范式。然而,计算机架构的历史表明,在辐射性创新之后往往会跟随大规模灭绝事件(例如,CPU在21世纪初的统治地位)。这是一个充满活力的时期,但也需要警惕收敛的迹象。


核心架构问题与科学挑战

上一节我们看到了行业的趋同,本节中我们深入探讨几个悬而未决的核心架构科学问题。

目前,许多设计决策仍基于工程经验而非科学原理。以下是一些关键的开放性问题:

脉动阵列的规模
Google TPU使用128x128的阵列,而NVIDIA和其他许多初创公司选择了更小的规模(如16x16)。目前没有明确的“正确”答案,性能表现也各有千秋。我们需要一个科学理论来解释何种规模最优及其原因。

内存系统的最佳设计
当前训练芯片普遍采用HBM,但IBM的系统展示了将主机DRAM作为HBM后备存储的潜力,这可能支持更大的模型,但尚未被广泛采用。此外,我们缺乏像Mark Hill的“缓存3C模型”那样,用于理解和设计神经网络内存层次结构(包括本地暂存器、HBM和网络内存)的清晰理论框架。

互连与并行化
训练通常采用数据并行(复制权重,汇总梯度)和模型并行(分割权重矩阵)两种方式。随着模型规模扩大到数千个节点,模型并行变得必要,但这引入了复杂的通信模式。未来的互连技术将如何演变?我们最终是否需要像人脑那样的小世界网络(密集的局部连接加上稀疏的长程连接)?目前,算法仍在快速变化,因此构建通用、高带宽的互连是更安全的选择。


数值格式:精度、效率与混合计算

上一节我们讨论了硬件结构,本节中我们来看看计算的核心——数值格式的选择。

在数值格式领域存在一场“拉锯战”:

  • 高性能计算社区倾向于要求更高的精度(如四精度浮点数),以确保复杂模拟的数值稳定性。
  • 机器学习社区则倾向于使用更低的精度(如FP16、Google的BF16、甚至INT8)来提升计算效率和能效。

TPU v1使用了8位整数,而TPU v2为训练引入了BF16浮点格式。一个有趣的发展方向是混合精度算法。硬件开始支持多种精度(如双精度、单精度、半精度),算法可以据此进行协同设计,在需要高精度的步骤(如梯度累加、某些优化器)使用高精度,在计算密集型步骤(如矩阵乘法)使用低精度,从而在保证训练效果的同时最大化硬件利用率。

未来的科学问题是:神经网络能否自己学会管理精度?为什么不能通过训练让网络在需要时组合使用多个低精度神经元来表示高精度数值,从而将精度管理的负担从硬件架构师转移到算法上?

关于新型格式(如Posits),其理论上有优势,但缺乏大规模实践来揭示其潜在缺陷。我们更倾向于使用已知缺陷和应对方案的成熟格式。


稀疏性:机遇与挑战

上一节我们探讨了数值精度,本节中我们转向另一个可能带来巨大效率提升的方向——稀疏性。

稀疏性有太多类型:权重剪枝、Dropout、混合专家系统、注意力稀疏化、图神经网络等。当前的挑战在于如何在训练中有效利用稀疏性

硬件处理稀疏计算的主要难点在于随机访存关联查找。经典的高性能计算稀疏库(如CSR/CSC格式)在稀疏度极高(>98%)时才有效率,而神经网络的稀疏度通常在70%到98%之间。最近的研究表明,通过将稀疏访问模式“分块”并限制在GPU的单个流多处理器内,可以有效地利用硬件局部性,这是一个有希望的方向。

科学问题在于:我们能否实现稀疏训练? 如果能,我们将能直接发现更优的网络结构。工程问题在于:是否存在值得构建的稀疏架构? 其关键在于如何以可接受的硬件开销来高效处理关联查找操作。稀疏性的价值取决于我们能达到多高的稀疏度,以及该稀疏度是否可靠。


未解之谜与未来展望

上一节我们分析了稀疏性的潜力,本节中我们来看看神经网络中那些令人困惑且可能指引未来方向的“怪异”现象。

科学革命往往源于对异常现象的观察。神经网络领域充满了这类“怪事”:

  • 知识蒸馏:为什么先训练一个大模型,再用它来教导一个小模型,比直接训练这个小模型效果更好?这背后的原理是什么?
  • 反馈对齐:在反向传播中使用完全随机的反向矩阵竟然也能训练网络,这颠覆了传统认知。
  • 彩票假设:训练似乎只是从随机初始化的权重中“释放”出早已存在的子网络。
  • 矩阵分解:为什么某些因式分解(如可分离卷积)有效,而其他则无效?

这些现象表明,我们对神经网络为何工作以及如何工作缺乏根本性的科学理解。目前,工程价值驱动着我们前进,但探索这些“为什么”可能为下一代更高效的算法和硬件指明方向。

当前,大型语言模型(如GPT-3)正在引发一场“太空竞赛”,推动着模型规模和计算需求的极限。这属于“大科学”范畴。但最终,经济可行的、可普及的智能助手需要成本削减和效率提升。未来的进步可能更多地来自桌面级设备上的创新,而非仅仅依赖万级节点的大型集群。


总结与反思

本节课中,我们一起探讨了机器学习硬件设计的前沿思考。

我们回顾了TPU的设计理念与发展历程,审视了深度学习加速器行业的现状与趋同趋势。我们深入讨论了多个悬而未决的架构科学问题,包括脉动阵列规模、内存系统设计、互连技术、数值格式选择以及稀疏计算的机遇与挑战。最后,我们列举了神经网络中诸多未被科学解释的“怪异”现象,强调了在工程实践飞速发展的同时,加强基础科学理解的重要性。

Cliff Young的分享启示我们,在构建强大机器学习硬件的同时,应当时刻保持科学探究的精神。理解“为什么”不仅能帮助我们建造更好的“蒸汽机”,或许还能让我们更早地发现“电力”。科学与工程的协同并进,将是推动机器学习领域持续突破的关键。


感谢Cliff Young带来的精彩分享和启发性的讨论。

018:机器学习的未来是微小而光明的

概述

在本节课中,我们将跟随哈佛大学副教授、ML Commons 创始成员 Vijay Janapa Reddi 的分享,探讨机器学习领域一个快速发展的分支——微型机器学习。我们将了解其核心概念、面临的挑战、所需的系统基础设施,以及如何通过社区协作推动这一领域的发展。


个人背景与核心观点

首先,让我们了解一下讲者的背景,这有助于理解他看待问题的视角。

我本科毕业于圣克拉拉大学,硕士毕业于科罗拉多大学博尔德分校,博士毕业于哈佛大学。之后在德克萨斯大学奥斯汀分校任教,并在谷歌休假工作过一段时间。

在我的研究历程中,有几个关键经验塑造了我对当前问题的看法:

第一,网络工作站项目。这个源自伯克利的项目让我认识到,微小的、商品化的系统通过巧妙的架构设计,可以集合起来解决宏大的问题。其核心启示是:微小的商品化系统能够对解决重大问题产生显著影响

第二,运行时编译器研究。在哈佛攻读博士期间,我主要研究编译器,特别是运行时或即时编译器。这项研究让我深入理解了硬件与软件的协同设计,以及如何通过审视整个计算栈(从硬件到应用软件)的交互来优化系统。

第三,移动计算研究。在德克萨斯大学期间,我深入研究了如何构建高能效的移动设备。当时我发现,尽管移动设备数量庞大且发展迅速,但研究界却将大量精力集中在数据中心和大型仓库级计算系统上。这促使我开始关注那些被主流忽视但潜力巨大的领域。

这些经验共同指向几个原则:关注廉价、可扩展的商品化系统;重视硬件与软件的跨层协同设计;以及构建开源工具和框架以促进生态系统繁荣。这些原则将贯穿我们今天对微型机器学习的讨论。


什么是微型机器学习?

上一节我们回顾了影响我研究视角的关键经验,本节中我们来看看这些视角如何应用于一个新兴领域——微型机器学习。

微型机器学习是机器学习领域增长最快的方向之一。它专注于在资源极度受限的微控制器设备上运行机器学习模型。我所说的“微小”,是指内存可能只有 16KB 的 SRAM 和 1MB 的闪存。这些设备需要在超低功耗(通常低于 1毫瓦)下,直接在传感器端进行实时数据分析,而不是将数据卸载到云端或大型计算设备。

微型机器学习的愿景是实现始终在线的机器学习,并最终依靠电池或能量收集设备运行,甚至实现生物降解,以减少电子垃圾。


为何需要微型机器学习?

我们已经了解了微型机器学习的定义,你可能会问:为什么我们需要它?以下是一些现实世界的应用场景和驱动力:

以下是微型机器学习的几个关键应用场景:

  • 关键词唤醒:例如“Okay Google”或“Hey Siri”,这是设备上的微型语音识别。
  • 视觉唤醒词:例如智能门铃检测到有人时自动拍照或开门。
  • 异常检测:例如通过声音分析预测工业电机的故障,实现预测性维护。
  • 智能设备:例如能感知用户习惯并自动启动的咖啡机、烤箱等。

这些应用看似简单,但部署到现实世界却异常复杂。以在办公室安装摄像头进行人员检测为例,你需要获得建筑许可、聘请电工布线、签订合同,整个过程成本高昂、效率低下。

而如果该智能传感功能可以集成在一个微型、电池供电、能持续工作数年的设备中,你就可以直接将其贴在墙上,无需任何复杂的部署流程。这极大地降低了机器学习的应用门槛,使其能够真正“无处不在”。

另一个例子是野生动物保护。在森林中部署用于监测盗猎的摄像头,如果设备功耗高达几十瓦,就需要庞大的太阳能电池板和频繁的电池更换,难以实现。微型机器学习使得超低功耗的智能监测成为可能。

因此,微型机器学习的核心价值在于:将现有机器学习能力“压缩”到极致,从而解锁海量的真实世界应用场景


核心挑战:系统基础设施

上一节我们看到了微型机器学习的巨大潜力,本节中我们来看看实现它的首要挑战——构建能够支持其发展的系统基础设施。

要让机器学习在嵌入式设备上运行,首先需要一个推理框架。这听起来简单,但嵌入式系统的异构性和资源限制带来了巨大挑战。

硬件层面的碎片化问题
在数据中心,我们面对的硬件架构(如x86 CPU、NVIDIA GPU)相对统一。但在嵌入式领域,情况截然不同。仅以ARM Cortex-M系列微控制器为例,就有M0、M3、M4、M7、M33等多种型号,它们的指令集架构和功能(如是否有浮点单元)各不相同。此外,还有Pensilica DSP、Qualcomm DSP、Synopsis微控制器等多种解决方案。每个芯片厂商都会为了极致的能效而对硬件进行深度定制,导致生态高度碎片化。一个为特定微控制器编译的模型,很可能无法在另一个上运行。

资源极度受限
内存是主要瓶颈。微控制器的SRAM可能只有16KB,闪存约1MB。这1MB的空间需要容纳推理引擎库和神经网络权重。相比之下,即使经过量化、剪枝等优化,最精简的MobileNet模型也仍有几MB大小。

软件与库的假设不成立
在通用计算中我们习以为常的功能,在嵌入式系统中可能不存在或不可用。

  • 动态内存分配:会导致内存碎片。在内存极度受限的环境中,碎片化可能使应用崩溃。嵌入式开发者要求确定性:要么启动时立即失败,要么一直稳定运行。
  • 操作系统与库依赖:不能假设存在操作系统或标准库支持,因为不同微控制器提供的支持差异很大。

因此,设计一个通用的微型机器学习推理框架,核心难题是:如何构建一个能在高度异构的生态系统中运行,且不依赖动态内存分配和外部库支持的通用推理框架?


解决方案:TensorFlow Lite Micro 的设计哲学

面对上述挑战,我们团队开发了 TensorFlow Lite Micro。它的设计选择可能有些反直觉。

为何选择解释器架构?
通常,解释器(如Python)因性能开销大而被认为效率低下。但在微型机器学习中,每个算子(如卷积)的执行需要成千上万个周期,解释器调度的相对开销就显得微不足道了。解释器架构带来了关键优势:

  1. 灵活性:模型保持为原始文件,易于进行无线更新。
  2. 可扩展性:允许硬件供应商为其特定架构提供高性能算子库。框架开发者无需为所有碎片化的ISA编写优化内核,只需调用硬件供应商提供的库即可。这通过一个硬件抽象层实现。

TensorFlow Lite Micro 的核心设计原则

  • 极小的二进制体积:不链接外部库以控制体积。
  • 无动态内存分配:保证运行的确定性和稳定性。
  • 裸机运行:不依赖任何操作系统。
  • 可移植性:目标是能够在各种异构的嵌入式系统上运行。

这种设计使得 TensorFlow Lite Micro 能够作为一个基础层,连接上层的模型优化工具链和底层多样化的硬件,从而支持微型机器学习生态的发展。


衡量进步:微型机器学习基准测试

有了运行框架,下一个问题是如何衡量和比较不同微型机器学习系统的优劣?这就需要基准测试。

衡量机器学习系统性能本身就很复杂,涉及应用场景、数据集、模型、框架、编译器、优化库、硬件等多个层次。在微型机器学习领域,还需加入功耗、内存占用等独特指标。

机器学习基准测试的通用目标

  1. 确保结果可复现
  2. 工作负载具有代表性,能反映实际生产需求。
  3. 鼓励创新,设定合理的标杆以推动行业进步。
  4. 保持公平和实用性,兼顾商业和研究需求。
  5. 保持可负担性,让学术界也能参与。

MLPerf 便是基于这些原则建立的社区驱动型机器学习基准测试套件。它定义了任务、参考模型、数据集、质量目标(如达到FP32精度的特定百分比)和一套清晰的运行规则。

微型机器学习基准测试的独特性
微型机器学习与传感器紧密耦合,这是其最显著的特征。实时处理音频、视觉、时间序列等传感器数据是核心需求。因此,其基准测试需要反映这些特点。

TinyMLPerf 基准套件
目前,TinyMLPerf 社区确定了四个初始基准测试:

  1. 关键词检测:有限词汇的语音唤醒。
  2. 视觉唤醒词检测:二元分类,如检测图像中是否有人。
  3. 异常检测:基于声音的时间序列分析,用于预测性维护。
  4. 微型图像分类:使用极小的ResNet8模型进行图像分类。

我们与嵌入式基准测试专家EEMBC合作,开发了开源的测试工具“runner”,用于在目标设备上执行基准测试并精确测量性能和功耗。第一轮正式提交将于近期开始。


推动社区:研究与教育

上一节我们讨论了衡量技术的标尺,本节我们来看看如何培育和壮大微型机器学习社区本身。

促进研究创新
微型机器学习是一个典型的交叉学科领域,涉及嵌入式系统、机器学习、应用开发。为了凝聚研究力量,我们创办了 TinyML Research Symposium,汇集来自不同领域的学者,共同探讨微型机器学习特有的数据集、算法、应用和跨层优化问题。

教育与普及
这或许是最重要的一环。我们不仅要推进前沿研究,更有责任让更多人掌握并善用这项技术。
传统机器学习教学侧重于模型设计和训练。但要真正“应用”机器学习,需要端到端的部署能力,包括数据收集、预处理、训练、为部署优化模型,以及在目标设备上执行推理。

微型机器学习提供了一个完美的教学场景:学生可以在一个小小的嵌入式设备上完成从数据收集到模型部署的完整闭环,亲身实践负责任的人工智能设计。

为此,我们设计了 TinyML 在线课程(可在edX上找到),并配套了开发套件,旨在全球范围内推广应用的机器学习。课程特别强调了人工智能伦理,因为与传感器深度结合的微型机器学习设备,未来可能以更隐蔽的方式影响人们的行为,我们必须从开始就灌输负责任的设计理念。

例如,我们有一个项目帮助纳瓦霍语使用者创建自己的关键词检测模型。当技术能够服务于个人的、本土化的需求时,它的意义和影响力会更加深远。


总结

本节课中,我们一起探讨了微型机器学习这一充满活力的领域。

我们首先了解了其核心定义:在资源极度受限的微控制器上进行超低功耗的实时机器学习推理。接着,我们探讨了其巨大的应用潜力,以及实现它所面临的核心挑战——高度碎片化的硬件生态和极端的资源限制。

针对这些挑战,我们介绍了 TensorFlow Lite Micro 作为一种解决方案,其解释器架构和独特设计旨在实现跨平台的可移植性和确定性。然后,我们讨论了如何通过 TinyMLPerf 基准测试来科学地衡量和比较不同系统的进展,这是推动领域发展的关键。

最后,我们认识到,技术的进步离不开社区的繁荣。通过 TinyML Research Symposium 促进跨学科研究,以及通过 教育和普及 让全球更多人能够接触、理解和应用微型机器学习,对于实现其“让一切设备变得智能”的光明未来至关重要。

机器学习的未来不仅是庞大的云和数据中心,也是微小、无处不在、并且光明的。这需要我们共同构建强大的工具、公平的标尺和包容的社区。

019:高级技术

在本节课中,我们将深入探讨如何利用更先进的底层技术来设计和优化深度学习硬件。我们将重点关注“内存内计算”这一核心概念,并分析几种利用不同存储技术(如闪存、SRAM)来实现高效矩阵乘加运算的方法。课程最后将对相关挑战和机遇进行总结。


概述

大家好,欢迎来到机器学习硬件课程的第22讲。本学期已接近尾声。

在今天的课程中,我们将更深入地探讨技术栈,思考人们如何利用更先进的技术为深度学习硬件创造机会。深度学习硬件领域实际上有很多激动人心的新动态,尤其是在初创公司方面。例如,Cerebras公司制造了世界上最大的晶圆级处理器芯片,旨在通过将计算贴近数据来减少数据移动的能耗。许多初创公司和研究机构正在重新审视“内存内计算”等想法,因为深度学习应用的规律性和容错性使得一些过去难以实现的技术变得可行。本节课我们将聚焦于利用内存技术进行计算,特别是模拟计算方式,以实现更高的能效。


数据处理的核心挑战:数据移动

在之前的课程中,我们讨论的一个重要原则就是数据移动。即使在数字领域,数据流优化的核心也是试图降低数据移动的成本。我们讨论了推拉模型、环形网络等架构权衡。对于数据密集型操作,能耗主要由数据移动主导。特别是当使用低精度计算时,计算本身能耗显著降低,这使得数据移动的能耗占比更加突出。因此,优化计算基板以提高效率的终极目标,是尽可能将数据移动到离处理器更近的地方。


解决方案:利用数据局部性

在数字或系统架构领域,一个最重要的架构原则是局部性。我们如何利用局部性来减少数据移动?在深度学习背景下,我们拥有非常规整的架构,例如金字塔式的内存层次结构。通过利用数据重用和数据局部性,我们可以将频繁使用的数据放在离计算单元更近的地方。我们讨论过两种重用类型:

  • 时间重用:如果一个数据块即将被再次使用,就将其保留在附近。
  • 空间重用:通过广播网络,将一份数据同时分发给多个计算单元。

在模拟计算和内存内计算的讨论中,这两种重用类型依然存在,只是通过不同的硬件设计来实现。


内存内计算的概念

“内存内计算”或“存算一体”并非新概念。过去五六十年间,几代工程师一直致力于将计算尽可能靠近内存。总体而言,它尚未被广泛采用,我们稍后会讨论一些根本性的技术原因,如可扩展性、非理想特性等。对于通用计算,精度通常非常重要,而且应用程序的多样性和控制流的复杂性使得为通用工作负载设计存算一体硬件非常困难。

然而,深度学习是一个对硬件设计者来说非常有趣且令人兴奋的范例。它功能强大,能解决许多问题,并且虽然不简单,但非常规整。大量的规律性使得一些过去对通用工作负载不可行的想法,对深度学习变得可行。深度学习具有确定性行为且对误差有一定容忍度,这使得存算一体面临的许多挑战变得不那么严峻。因此,人们开始重新审视这些想法,探索是否能将其用于深度学习计算。

从高层次看,这个概念相当直接。我们试图将计算尽可能靠近数据。在典型的数字加速器模板中,我们从缓冲区读取输入激活和权重,然后在一个计算单元进行运算,并存储部分和。而在存算一体中,我们更像是采用了权重固定的数据流。我们不是将输入和权重数据都提取到某个计算发生的地方,而是将输入数据送到存储权重的内存阵列中,计算就在存储权重的内存内部完成,然后我们从内存中获取累加结果。在这里,内存不仅用于存储权重,还用于计算结果。这种计算通常以模拟方式进行。

对于任何用于深度学习的数据存算一体技术,你都会看到类似的系统架构图。权重被分布式存储,输入激活被读取。如果计算以模拟方式进行,我们通常需要对输入激活进行数模转换,并对累加的部分和进行模数转换。最近的一些研究也在关注,为了获得合理的精度,数模转换器和模数转换器需要怎样的精度。总的来说,在高层架构上,系统其余部分大多数时候仍然是数字的,但具体被模拟化的部分是乘积累加运算。事实证明,这部分运算以模拟方式实现是相当可行的。


内存内计算的一般架构

如果我们放大这个架构图,可以看到更多细节。输入仍然需要从输入激活存储器中读取,但不需要移动的是权重,因为权重就驻留在内存中,计算也在内存中完成。当输入被移动时,我们需要进行数模转换,将数字输入转换为模拟信号。同时,我们仍然有一个类似于空间重用的广播机制,通过字线来跨列重用输入激活。

具体来说,乘法运算的实现方式取决于技术,但累加通常是通过位线以电流相加的方式完成的。我们不是像在数字领域那样进行加法运算,而是在模拟领域将电流在位线上累加起来,然后通过模数转换器将最终的总电流转换回部分和,用于输出激活。基本原理是相同的,我们仍然利用了一些重用。累加大多数时候是通过位线进行电流相加来实现的。

另一个非常重要的因素是位线累加所支持的精度或准确度。即使对于低精度算术,累加也有较高的精度要求,因为我们需要将权重和输入结合起来。这也是许多存算一体方案面临的挑战之一,与数模/模数转换器设计的精度和复杂性有关。

再次强调,即使是初创公司的方案或研究想法,其重点也是如何在模拟领域进行乘积累加运算。但这些设计中的大部分其他计算,例如残差加法等其他算子,在大多数情况下仍然需要在数字领域完成。我们还没有看到完全模拟的深度学习计算硬件,大多数设计是模拟和数字组件的混合。就目前所见的设计而言,模拟组件只出现在乘积累加部分。

这是深度学习硬件的一些通用模式。输入激活在转换后通过字线传送,权重存储在存储单元中,输出部分和在位线上累加。这些是通用原则。


内存技术概览

在讨论具体技术之前,我们先简要回顾不同的内存类型。构建内存有不同的方法,我们可以根据内存容量和需求使用不同的技术。许多关于存算一体的讨论都与随机存取存储器有关,特别是非易失性存储器(如商业闪存)和易失性存储器。我们将看到,一些商业初创公司正在使用基于闪存的非易失性存储器进行深度学习处理。在研究方面,也有大量工作探索使用SRAM或DRAM技术来支持内存内计算。

接下来,我们将使用三个驱动性示例,来讨论非易失性存储器、SRAM甚至DRAM如何用于内存内计算。


技术示例一:基于闪存的存算一体

有一些初创公司正在这个领域尝试使用闪存技术,并且已经有硬件可用。在深入之前,我们先简要了解一下闪存晶体管,并建立连接,说明它为何能用于执行乘积累加操作。

闪存晶体管的关键概念与我们目前所见的大多数晶体管类似,但有一个新特点:栅极并不直接连接,而是有一个新的浮栅。你可以将其视为一个电荷存储层,我们可以在这里存储额外的电荷。通过存储额外电荷,从功能角度来看,这实际上可以用来改变晶体管的阈值电压。

对于典型的晶体管,阈值电压是固定的。而对于闪存晶体管,特别是带有浮栅的,我们可以通过编程改变浮栅中的电荷量来改变阈值电压,这成为了一种可编程地改变晶体管行为的方式。我们将主要关注所谓的单级闪存晶体管,即存储0或1,但也有多级闪存单元可用,通过调制浮栅中存储的电荷量,可以存储多位信息(如2位甚至4位)。

那么,这如何改变晶体管行为呢?对于闪存晶体管,我们使用浮栅来改变单元的阈值电压。如果没有存储电荷,晶体管处于开启状态;如果存储了电荷,则处于关闭状态。我们如何区分是存储了1还是0呢?区别在于它改变了晶体管的阈值电压,使得在有电荷和无电荷的情况下,具有不同的电压-电流特性。具体来说,如果没有电荷(左侧情况),我们有一个相对较低的阈值电压;如果有电荷(右侧情况),则需要更高的阈值电压才能开启晶体管。因此,我们有两种不同的电压-电流特性:低阈值电压对应开启状态(存储1),高阈值电压对应关闭状态(存储0)。

为了判断是存储1还是0,我们施加一个介于开启阈值电压和关闭阈值电压之间的电压。通过施加这个电压,我们可以观察晶体管是开启还是关闭。如果晶体管开启(有电流),则意味着它存储的是1(浮栅无电荷)。如果晶体管关闭(无电流),则意味着它存储的是0(浮栅有电荷)。这种技术已经商业化,主要用于存储。但因为它可以存储0和1,甚至通过不同电荷量实现多级存储,人们产生了将其不仅用作存储设备,还用作计算设备来执行乘积累加功能的想法。


闪存如何执行乘积累加

那么,我们如何使用闪存单元来执行乘积累加功能呢?这是来自Mythic公司(一家初创公司)的示意图。他们的基本想法是使用基于闪存的非易失性存储器来进行深度学习。他们执行乘积累加的基本方式如下:

乘法是通过每个闪存单元实现的。根据每个单元中存储的值(是1还是0,或者是多级单元中的某个值),通过施加栅极电压(字线电压)来查看是否产生电流。权重被编程到每个单元中,输入激活则作为字线电压施加到每个单元。通过施加电压,根据权重是1还是0,我们可能从每个单元获得电流或没有电流。这就是我们进行单个乘法的方式。

对于累加,我们通过位线将所有单元的电流加在一起。单个单元可能不同,但累加总是通过将不同单元的电流直接相加来完成。这与我们在数字领域进行部分和累加的想法相同。

因此,尽管一些技术看起来很复杂,但根本上,它们是通过位线累加进行乘法运算,而乘法则取决于技术。对于闪存单元,乘法基本上是通过将权重存储在浮栅中,然后通过向字线施加输入电荷来查看是否能开启单元,从而实现乘以1或乘以0的操作。

Mythic公司的想法是通过使用这种基于闪存的非易失性存储器,可以获得高性能和低功耗,特别是可以跳过大量的权重数据移动能耗(输入仍然需要移动)。他们目前主要专注于推理,在极低精度方面表现相当出色。当精度提高时,问题会变得更棘手,例如在单个单元中存储多个值时的误差容忍度。他们似乎在精度和能效方面都达到了合理水平,例如每焦耳5万亿次操作是一个合理的能效数字。

具体来说,技术相当直接,但需要考虑很多细节,核心仍然是在模拟领域进行矩阵乘法中的乘积累加部分。我们将讨论可扩展性和精度方面的一般性挑战,但这是该领域的一项商业化努力,并且已经提供了有趣的产品来支持此类计算。


挑战与考量

关于权重存储在闪存位中的问题:是的,权重存储在闪存位中。对于许多此类硬件,它们假设我们不会频繁重写或更新权重。因此,可扩展性非常重要。我们需要布局或配置硬件,以便所有权重都可以存储在硬件上,这样在运行时就不需要覆盖权重,因为写入或更改权重总是昂贵的部分。与数字领域中我们讨论的重用(重新获取权重并存储在寄存器中)不同,在这里,我们需要复制或拥有足够大的阵列来存储网络的所有权重。

Mythic公司有另一种示意图显示其芯片规模也相当大。他们的做法是将芯片的不同分区用于不同层的不同权重。因此,在大多数情况下,至少对于目标场景,实际上不需要重写权重。

如果模型有10层,是否可以同时进行所有层的乘积累加?不一定。如果有10层,我们仍然可以像数字硬件中那样进行流水线处理。例如,当第一层处理第N张图像时,第二层可以处理第N-1张图像的输出,依此类推。大多数时候,即使对于单个层,你也需要将所有权重布局到单元上。

正如Brian Zimmer下周客座讲座可能会更详细地介绍的那样,这肯定是一个挑战。但同样,正如我们所提到的,即使是一些旨在获得高片上内存大小和高可扩展性的数字硬件也会遇到这些问题。有些问题可以通过流水线等技术来解决,但在这里,权重被编程一次后就保持不变。许多Mythic的用例,至少从我们之前看到的一些讲座来看,是针对安防摄像头等进行视觉人体识别。在这种情况下,可以合理地假设你有一个固定的网络,可能网络并不非常复杂,然后你将网络固定在硬件上,永不更改。

正如Dan已经提到的,对此类存储器进行编程在延迟方面非常慢,而且对于许多非易失性存储器,还存在耐久性问题。此外,我们假设权重的大小可以与总内存匹配。如果你处理的是一个无法容纳的巨大模型,通常这类硬件针对的是较小的目标网络,或者它们拥有足够多的硬件。但更改权重在这里始终是一个挑战。

我们已经讨论了精度问题。在不产生高错误率影响精度的情况下,实际可以存储多少位?这是许多使用非易失性存储器的硬件公司面临的挑战。还有许多其他可用技术,你会看到更多研究出版物使用这类新兴非易失性存储器件来支持存算一体。它们仍然存在相同的问题:更改权重的编程过程非常具有挑战性,例如可以更改多少次、速度有多快,以及始终存在的精度问题。对于Mythic针对的安防摄像头等用例可能没问题,但对于其他场景,这种方案的通用性如何?另一方面,正如微型机器学习讲座中提到的,安防摄像头用例中的模型确实相当小,这是一个足够大的市场,可以覆盖硬件的部分非经常性工程成本。


项目进展与客座讲座预告

在后勤方面,我们最后一位客座演讲者是来自英伟达的Brian Zimmer,期待他的讲座。在思考模拟和内存计算的总体机遇和问题时,我们今天的讨论更侧重于机遇方面,即为什么它是可行的。Brian将为我们提供更多关于采用此类技术所面临挑战的观点。

关于项目方面,检查点一已经完成,大家做得很好。大多数团队似乎都在正轨上,并取得了很好的进展。有几个团队可能需要调整方向或认真考虑什么是可行的。我们期待在检查点二看到目前的进展。与检查点一类似,我们有一个签到电子表格,链接相同,只是不同的标签页,时间仍然是周二和周四。请选择你的时间段,以便我们有机会再次与你交谈(即使是线上)。同样,准备两到三张幻灯片展示你当前的进展,没有特定格式,但这次我们期待看到更具竞争性的结果。上次主要是关于你尝试做什么、拥有的基础设施和总体架构图。对于检查点二,这确实是你展示至少非常接近交付成果以及一些定量结果和评估的机会,这些将是项目的重要组成部分。


技术示例二:基于SRAM的存算一体

接下来,我们将简要讨论SRAM。基本原理是相似的,我们仍然调制字线和位线。快速回顾一下我们在数字逻辑课中讨论过的6T SRAM单元:字线用于选择要读取或写入的单元,数据通过位线和位线互补对差分地写入或读取。

总的来说,这与基于闪存的非易失性内存内计算有更多的相似之处而非差异。位线仍然用于存取,我们仍然通过位线和位线互补对进行累加。具体是使用位线还是位线互补对,取决于存储的值。

例如,如果我们存储的是-1,那么-1在这里表示为1。如果左下角晶体管中存储的是1,我们就会对位线进行放电(对于-1,我们放电位线)。但如果我们存储的是+1,我们就会对位线互补对进行放电。然后,通过比较位线和位线互补对,我们得到最终的累加值。

同样,正如我提到的,累加仍然通过位线完成,我们使用字线来选择启用哪个单元,然后根据存储的不同值(即权重),输入被视为字线中的启用信号,部分和累加通过位线完成。

这是基于SRAM的累加。我们已经看到了很多这方面的研究,可以说在这个领域有更多的研究试图使其可行。这里存在一些根本性的挑战,除了我们讨论过的精度问题之外,这些挑战对SRAM设计来说是相当根本的。

与闪存相比,SRAM的写入要容易得多,所以我们肯定没有那个问题。但与数字设计相比,精度问题仍然存在。这里的另一个挑战是可扩展性。我们提到过SRAM设计,通常我们希望拥有足够大的SRAM阵列以获得足够的密度和面积来实现更多重用。但一般来说,阵列越大,其尺寸(宽和长)就越大。位线越长,位线电容就越高。我们之前讨论过的充放电本质上是单元电容和位线电容之间的电荷重新分配。我们基于每个单元的电容和位线电容进行电荷重新分配。如果我们有一条超长的位线(即大型阵列),位线电容会很高,这使得通过单个单元的充放电产生的电压差很难辨别,因为我们进行的是电荷重新分配。对于大型SRAM单元,很难感知单个单元的电荷是如何重新分配的。因此,这也存在误差容忍度问题。最终,我们无法观察到单元中发生的所有累加。

因此,对于目前所见的大多数设计(同样,主要在研究领域),它们通常非常小。一个自然而然的问题是:这能做到多大?因为我们不能一直构建千字节级别的阵列,我们需要做得更大。但一旦我们做得更大,就会遇到这种电荷重新分配问题。

我从Novin Burma那里找到了一份非常有趣且全面的不同技术比较。当然,我们看到内存内计算具有非常好的能效(图中蓝色部分),但一旦涉及到可扩展性,许多设计都处于较低水平。请记住,这是一个对数刻度。通常,为了获得合理的性能和精度,我们最多只能看到单个数字或几十千字节的小型阵列。而对于其他数字设计,我们通常考虑的是大得多的规模,即使几十或几百千字节在数字加速器设计中也是非常标准的。因此,阵列可扩展性是SRAM设计面临的最大挑战之一。


总结

时间有点不够了,我们就讲到这里。我们将在Brian的客座讲座中看到他涵盖的更多内容,也可能再谈一点关于DRAM的设计,那可能更不常见。我想说,最流行的设计要么是基于非易失性存储器的,要么是基于SRAM的,这是两种最常用的设计。我们主要讨论了它们为何可行,可能感觉相当直观和直接。但我们也会在Brian的讲座中看到一些更具体的挑战。

本节课我们一起探讨了利用先进技术进行内存内计算以优化深度学习硬件的核心思想。我们分析了数据移动是主要能耗瓶颈,而存算一体通过将计算贴近数据来应对这一挑战。我们重点介绍了基于闪存和SRAM的两种存算一体实现方式,了解了其利用模拟计算进行乘积累加的基本原理,同时也指出了它们在精度、可扩展性、权重更新等方面面临的挑战。这是一个充满机遇与挑战的活跃研究领域。

很高兴见到大家,祝大家本周愉快,我们下周再见。保重,再见。

020:模拟与内存计算面临的问题

概述

在本节课中,我们将跟随NVIDIA的Brian Zimmer,探讨在深度学习中采用模拟计算和内存计算所面临的核心挑战与机遇。我们将从数字计算与模拟计算的基本对比出发,分析模拟/内存计算在追求更高能效和面积效率时遇到的七个关键问题,并思考该领域的未来发展方向。

数字计算与模拟计算对比

上一节我们介绍了课程背景,本节中我们来看看数字计算与模拟计算的基本区别。

数字计算系统通常包含输入SRAM、权重SRAM和输出SRAM。数据从存储中读出,在算术逻辑单元(ALU)中进行乘加运算,结果再写回存储。这个过程可以用类似CPU的指令来描述,其核心是使用标准单元(如全加器、半加器、逻辑门)构建的乘法器。整个数据路径可以通过约100行的RTL代码描述,并由综合工具进行优化实现。

模拟计算或内存计算的核心理念,是将计算“折叠”到存储阵列内部进行,以规避数字计算中的一些低效环节。其典型流程是:从输入SRAM读取数字值,通过数模转换器(DAC)转换为模拟电压或电流。这个模拟信号被施加到存储权重的内存单元(可以是SRAM、RRAM、DRAM等)上。通过同时开启多个存储行,利用位线上的电荷或电流求和效应直接完成乘积累加运算。最后,通过模数转换器(ADC)将模拟结果转换回数字值,并存入输出SRAM。其优势在于,电流域的求和近乎“免费”,有望节省大量在数字乘法器和加法器中开关逻辑门的能量。

数字计算的性能基线

在深入探讨模拟计算的挑战之前,我们需要建立一个清晰的数字计算性能基线,作为比较的基准。

数字系统通过架构优化来提升效率,核心思想是数据复用。例如,在卷积运算中:

  • 输入激活复用:从输入SRAM读取一次数据,可广播到多个计算通道,从而分摊读取能耗。
  • 权重复用:从权重SRAM读取一组权重,可用于多次计算,分摊读取和存储能耗。
  • 部分和累加:中间结果在累加器中暂存,最终写回输出,分摊写操作能耗。

通过调整复用因子、关键路径和计算精度(如4位、8位),可以在性能(TOPS/mm²)和能效(TOPS/W)之间进行权衡,形成一个广阔的设计空间。一个常见的能效指标是TOPS/W,即每瓦特每秒可执行的万亿次操作。

模拟/内存计算的愿景与范畴

模拟计算的愿景在于利用神经网络本身对非完全精确计算的容忍性。即使最高精度的网络也有错误率,因此或许可以牺牲少量计算精度来换取显著的能效提升。

我们需要区分几个概念:

  • 模拟计算:在模拟域(电压、电流、时间)执行核心数学运算。
  • 内存计算:在存储数据的内存阵列内部或附近执行计算。它可以是模拟的,也可以是数字的(例如,在内存中逐周期进行数字累加)。

应用场景广泛,从需要数千个GPU的数据中心,到功耗极低的边缘设备。目前,大多数模拟/内存计算研究集中于推理任务,因为:

  1. 新型存储器通常读操作优于写操作。
  2. 推理系统更容易构建。
  3. 训练通常需要更高精度,而模拟方法目前难以实现。

面临的七大核心问题

以下是模拟和内存计算领域需要解决的七个核心研究问题。

1. 面积效率问题

面积效率(如TOPS/mm²)是关键但常被忽视的指标。它直接影响芯片成本和可解决问题的规模。低面积效率会重新引入“内存墙”问题,因为低效的存储或计算单元增大了数据必须移动的距离。

影响面积效率的因素包括:

  • 存储单元密度与变异:高密度存储单元(如多级RRAM)变异更大。
  • 设计规则:自定义存储单元(如增加晶体管或电容)通常需使用更保守的设计规则,难以与经过高度优化的标准6T SRAM单元竞争。
  • 工艺节点落后:许多新型存储器技术比最先进的数字工艺落后几代,限制了片上存储容量。

一个极端的例子是,早期某些低面积效率的设计,若想实现实时高分辨率目标检测,需要多个光罩尺寸的芯片,这在实际中不可行。

2. 实现高精度计算的问题

数字计算可以相对容易地适配不同精度(4位、8位、浮点)。而模拟设计在精度提升方面存在“悬崖效应”,需要为不同的精度范围完全改变设计方案。

挑战体现在多个方面:

  • 权重精度:例如,通过晶体管尺寸比例在单个位单元中存储多比特信息。但工艺变异会导致比例失配,限制可实现的精度。
  • 输入精度:通过字线电压或脉冲宽度表示多比特输入。在先进工艺中,字线的高电阻会导致阵列首尾单元看到的信号波形不同,引入误差。
  • 符号处理:处理有符号数需要额外设计,例如使用差分位线(正负值分开)或原位取反,这会增加面积开销。

报告变异性的方法多样,但各有局限:

  • 分离测试DAC/ADC:无法反映位单元和整体计算路径的误差。
  • 测量实际累加值:对大量真实或极端输入/权重组合进行测量,绘制输出误差分布,更能反映系统级表现。
  • 报告网络精度损失:在标准数据集(如CIFAR-10, ImageNet)上运行完整网络,报告精度下降百分比。这是最直接的证据,但受网络选择、量化方法等非硬件因素影响大,难以横向比较。

3. 收益递减问题

即使在模拟域实现了“零能耗”的乘加运算,其在整体系统能效提升上也存在上限。

原因在于:

  • 阿姆达尔定律:在数字基线中,乘加运算本身的能耗可能只占系统总能耗的~50%。其余能耗来自数据移动、存储读写、控制逻辑等。因此,即使完美优化MAC,最大理论增益也只有约2倍。
  • 工艺节点劣势:若模拟计算模块必须采用旧工艺节点实现,那么其他数字部分(SRAM、互连)的能效也会比先进节点差,可能抵消核心计算带来的增益。

因此,必须从全系统角度评估能效,而不仅仅是核心模拟宏单元的性能。

4. 数据复用(摊销)问题

数字架构通过巧妙的数据复用大幅降低存储访问能耗。而许多内存计算方案在进行原位乘加时,权重一旦与当前输入相乘,就无法被下一个输入复用,导致存储访问开销无法被摊销。

后果严重:

  • 在数字基线中,通过复用,权重读取能耗可能被分摊16倍或更多。模拟方案需要在此单项上实现6倍以上的能效优势才能打平。
  • 在某些极端情况下(如位串行近似乘法),缺乏复用会导致操作数量呈平方增长,能效和面积效率极低。

此外,不同应用的数据复用程度差异巨大。例如,高分辨率图像处理中权重复用次数远高于低分辨率,这会影响对片外存储访问成本的容忍度。

5. 模数转换器(ADC)的限制问题

模拟计算的结果需要通过ADC转换回数字信号。ADC的成本(面积、能耗)随精度位数呈指数增长。

核心矛盾在于:

  • 一次模拟累加涉及大量单元(如1024个通道),理论上可能产生需要极高精度ADC(如25位)才能无剪裁表示的巨大数值范围。
  • 实际中,可以通过剪裁(Clipping)分布尾部的极端值,来降低对ADC精度的要求。

量化训练技术是关键辅助手段:

  • 训练后量化(PTQ)与量化感知训练(QAT):通过选择合适的量化范围(如使用99.9%分位数而非最大值作为范围上限)和重新训练,可以让网络权重分布更适应量化,在较低比特数下保持精度,从而降低对ADC精度的需求。

目前有两种主要设计思路:

  1. 短行 + 低精度ADC:每次只开启少数几行,使用简单高效的低比特(如3-4位)ADC,然后在数字域进行多组结果的累加。
  2. 长行 + 高精度ADC:一次开启很多行(如>1000行),使用昂贵的高精度ADC,但其成本被大量的操作次数所摊销。

6. 灵活性问题

专用模拟/内存计算硬件难以适应快速演变的算法和多样化的网络结构。

具体挑战包括:

  • 权重更新与流水:对于多层网络,需要重复使用同一计算阵列。权重加载可能带来延迟和能耗开销,需要复杂的“乒乓”缓冲或双阵列设计来隐藏权重更新延迟。
  • 负载均衡:若以空间方式映射不同网络层到硬件不同部分,需要精细的负载均衡以保证高利用率。时间复用的方式(同一硬件依次执行各层)在灵活性上通常更有优势。
  • 阵列尺寸选择:确定最优的位线长度(即一次计算涉及的通道数)需要在ADC摊销收益和灵活性之间权衡。
  • 电压频率缩放:数字设计可通过调节电压来灵活权衡性能与能效,而模拟电路可能对工作点更敏感。

7. 确定性问题

数字电路通过设计余量确保所有芯片行为一致。模拟/内存计算芯片则因工艺变异,每个芯片的行为都会有细微差异。

这引发了系统级问题:

  • 这种芯片间的差异是否可接受?对于安全摄像头或许可以,但对于自动驾驶的行人检测则可能至关重要。
  • 如何定义可接受的精度波动范围(例如1%的精度损失)?这需要与算法和系统需求共同考虑。

总结与展望

本节课中,我们一起学习了模拟与内存计算在加速深度学习时面临的七大核心问题:面积效率、高精度实现、收益递减、数据复用、ADC限制、灵活性以及确定性。

总结来看:

  • 数字计算难以被击败:对于每一个模拟优化技巧,通常都存在对应的数字优化方案。数字设计流程成熟,且能快速适应算法变化。
  • 软件栈是关键差异点:高效的软件映射和编译优化对发挥硬件性能至关重要,更灵活的硬件通常更容易获得好的软件支持。
  • 模拟计算仍有价值与机会:该领域已取得显著进展。其最佳应用场景可能在于更专用、对能效和面积有极端要求的领域,而非追求通用性。
  • 训练技术需持续进步:需要更多能有效处理低精度和非理想硬件特性的训练算法,以释放模拟硬件的潜力。

模拟与内存计算是一个充满挑战但机遇并存的研究方向,其发展需要电路、架构、算法等多个层面的协同创新。

021:端到端部署 🚀

在本节课中,我们将探讨机器学习加速器的端到端部署。我们将超越单个加速器内核的性能,审视在实际部署(无论是云端还是边缘)时需要考虑的完整处理流水线、系统级约束和实际挑战。


概述:超越加速器内核

上一节我们讨论了加速器级并行性。本节中,我们来看看将加速器集成到完整系统中的实际考量。一个常见的误解是,只需优化神经网络加速器即可。然而,端到端部署涉及从数据预处理到后处理的整个流水线,其中许多步骤可能仍在CPU上运行,并受到数据移动、调度和系统碎片化的影响。


完整的处理流水线

在评估硬件性能时,我们常看到仅报告卷积或矩阵乘法等核心算子性能的数据。然而,一个真实的机器学习应用流水线包含更多阶段。

以下是典型机器学习部署流水线中的关键组成部分:

  • 数据获取与注入:从源(如摄像头、数据库)获取原始数据。
  • 数据预处理:调整数据格式以供模型使用,例如调整图像大小、视频帧提取、特征修剪或格式转换。
  • 机器学习推理/训练:执行核心的神经网络计算。
  • 后处理:对模型输出进行分析、解释或格式化。

来自Facebook和Google的数据表明,预处理和数据移动阶段可能消耗相当多的计算周期,有时甚至成为处理速率的瓶颈。例如,在将数据从CPU馈送到TPU的过程中,数据移动所花费的时间可能非常显著。


阿姆达尔定律与系统瓶颈

阿姆达尔定律指出,系统的整体加速受限于其顺序执行部分。即使我们极大地加速了可并行部分(例如使用专用加速器),顺序部分最终将成为瓶颈。

在机器学习部署的语境下:

  • 可并行部分:通常是密集的神经网络算子(如卷积),这正是大多数加速器优化的目标。
  • 顺序部分:包括数据预处理、后处理、框架开销、调度以及CPU与加速器之间的数据移动。

因此,仅优化“蓝色”的AI计算部分可能无法实现预期的端到端性能提升。必须考虑整个流水线的性能剖析。


部署场景的多样性

机器学习工作负载的部署场景多种多样,对性能有不同的要求:

  • 单流:处理单个数据流(如单个摄像头),通常有严格的延迟要求。
  • 多流:同时处理多个数据流(如自动驾驶汽车的多摄像头),涉及复杂的调度和资源共享。
  • 服务器:处理来自用户的异步、不可预测的请求,需要保证服务质量。
  • 离线批处理:处理大量数据,主要追求高吞吐量,对延迟不敏感。

MLPerf等基准测试套件试图为这些不同场景提供标准化的评估方法。在评估或选择硬件时,必须明确目标应用属于哪种场景。


实际部署约束

在实际部署加速器时,会遇到一些在学术论文或产品白皮书中常被忽略的约束。

1. CPU仍然至关重要 🖥️

尽管专用加速器备受关注,但CPU在许多部署中仍然扮演着核心角色:

  • 现有基础设施:数据中心已有大量CPU,对于计算强度不高的任务,直接使用CPU更为经济。
  • 编程简易性:CPU的编程模型成熟、工具链完善,部署难度远低于为各种定制加速器编写代码。
  • 处理流水线:如前所述,预处理、后处理、控制逻辑等通常仍在CPU上运行。

2. 热约束与性能可变性 🔥

在边缘设备(如VR/AR头盔、手机)上部署时,热设计和功耗预算成为关键限制因素。

  • 热限制:设备可能为了控制发热和功耗,不得不降频运行CPU/GPU,导致实际性能远低于峰值。
  • 性能可变性:即使在同代SoC中,由于制造差异、老化、共运行应用的不同,性能也可能存在波动。在碎片化严重的Android生态中,有成百上千种不同的SoC配置,这给为所有设备提供一致性能的软件优化带来了巨大挑战。

3. 资源共享与干扰 ⚡

当多个处理单元(CPU、GPU、多个加速器)共享系统资源(如最后一级缓存、内存带宽、互连总线)时,会产生干扰。

  • 干扰影响:一个代理的繁忙活动可能影响另一个代理的访问延迟,导致性能波动,难以提供稳定的服务质量保证。
  • 系统级管理:需要更智能的资源管理和调度策略,以协调CPU和加速器之间以及多个加速器之间的资源共享。

总结与展望

本节课我们一起学习了机器学习硬件端到端部署的复杂性。我们认识到:

  1. 必须审视完整流水线:评估性能时,需考虑从数据注入到结果输出的全过程,而不仅仅是核心AI算子的速度。
  2. 阿姆达尔定律依然适用:顺序执行部分(如数据预处理、移动)可能成为系统瓶颈。
  3. 部署场景多样:单流、多流、服务器、离线等场景有不同的约束和目标。
  4. 实际约束重大:CPU仍是部署基石,热限制和性能可变性影响边缘设备体验,资源共享引发的干扰是系统级设计的新挑战。

未来,随着市场碎片化加剧和集成度提高,如何设计统一的软硬件接口、管理异构计算资源、并提供可靠的服务质量,将是推动加速器广泛落地的关键。正如IBM System/360通过统一指令集架构解决了当时的碎片化问题一样,机器学习硬件领域也可能需要类似的抽象层来简化部署。


下节课预告:我们将进行课程总结与项目展示,回顾本学期所学,并欣赏同学们在机器学习硬件设计上的实践成果。

022:课程总结与展望

在本节课中,我们将对本学期的“机器学习硬件技术”课程进行总结,并探讨该领域未来的挑战与机遇。我们将回顾所学核心概念,并思考如何将这些知识应用于更广泛的硬件设计领域。

课程概述与学期回顾

本学期我们共同探索了机器学习硬件这一激动人心的领域。课程旨在连接硬件设计与机器学习应用,强调通过理解应用特性并利用核心硬件设计原则来构建更高效的专用系统。

上一节我们介绍了多种加速器架构,本节中我们来看看对整个课程的总结与反思。

随着学期接近尾声,我们已涵盖了一系列广泛的主题。我们从通用的机器学习及其不同范式入手,讨论了机器学习流程中的三到四个组件。我们探讨了所使用的各种基本运算单元(Primitives),以及如何使其运行得更快。课程初期,我们通过使用PyTorch和思考量化流程,让大家获得了更多实践体验。在后续的客座讲座中,你们也看到了该领域更前沿的研究,以及工业界如何通过支持不同格式(如Google的BFloat16、微软的MS-FP8)甚至设计自己的格式来应对这一问题。

我们还讨论了不同类型的加速器,一些定制化程度更高,一些则更灵活。例如,SambaNova的加速器相当灵活,可以处理多种应用;而TPU则专为高效执行矩阵运算而设计。我们强调了映射(Mapping)的重要性,例如亚马逊的讲座包含的两个组件就与我们的Lab2和Lab3非常契合:一部分是加速器设计(脉动阵列架构),另一部分是编译器部分(如何将运算编译到硬件上)。因此,我们也着重强调了映射的重要性,即如何将计算任务映射到硬件上。

课程还涉及了与协同设计、不同算子与训练相关的多个主题,并通过NVIDIA Brian Kelleher的客座讲座探讨了先进技术。当然,机遇众多,但我们也需要看到使用这些技术时更现实的考量,尤其是在更广泛的应用领域中,它们可能只适用于利基市场,同时也存在更本质的限制。

在系统层面,我们讨论了端到端部署以及加速器级并行的概念。随着各种应用兴趣的增长,如何协调、设计所有不同的加速器或IP,使它们能够协同工作变得尤为重要。

希望通过对所有这些主题的覆盖,能让大家对当今的做法、重要因素以及核心组成部分有一个全面的了解。主讲座阐述了核心主题,客座讲座则强化了这些主题,并展示了这些原则如何在工业实践中被采纳或应用。你们可能会发现,我们今天所讲的内容正是工业界正在做或计划做的事情。

核心设计原则与行业视角

本课程非常强调原则的重要性。许多硬件设计原则当然对机器学习非常有用,但总体上,这些原则在过去五六十年中已应用于通用硬件设计,例如利用局部性、利用并行性。所有这些原则仍然相关,并且因为我们专注于更特定、更专门的应用,实际上可以发掘出更多潜力。

课程的一个重要部分是行业视角。我们有一系列精彩的客座讲座,主讲人都是工作在最前沿、思考极具挑战性问题的科学家和工程师。你们也能看到他们或其组织所采取的问题解决方法,与本课程推荐的一些设计决策或原则有相似之处。建立这种行业联系也非常重要,我们尽力将学生与行业合作伙伴联系起来。

实验与项目实践

我们通过实验让大家做好准备。你们拥有非常多样化的背景,我们希望通过本课程至少让大家在使用一些基础设施(无论是商业化的还是我们的研究基础设施)时感到得心应手。也许以前你们觉得这些基础设施庞大复杂,缺乏经验,但通过将实验作为课程组成部分,你们至少可以以用户的身份接触这些设施。在未来的职业生涯中,你们或许可以更积极地参与这些基础设施的开发。即使不使用完全相同的设施,这也让你们对当前在学术界和工业界使用的代表性基础设施有所了解。

实验旨在让大家从不同视角看待硬件软件协同设计:从应用到硬件设计,再到更偏向编译器的映射过程思考。同时也让大家熟悉我们的研究基础设施,以便为开展项目做好准备。

在看到项目检查点一和检查点二后,我个人非常兴奋。你们所有人都完成了一些非常重要且有趣的工作,有些更新甚至让我感到有些惊喜。做得非常出色,下周我们将庆祝你们的成果。

项目展示与报告提交

以下是关于项目展示和最终报告的具体安排:

  • 项目展示:定于下周一进行。我们将使用下午的时间段,每个团队大约有20分钟时间展示项目,并留出一些问答时间。我们将使用相同的电子表格来最终确定时间段并让大家报名。
  • 最终报告:截止日期是阅读周的周五。报告不需要很长,最多8页。我们希望你们能借此机会记录所取得的进展,反思所学,描述遇到的技术挑战及解决方法。

更广阔的机遇:超越机器学习硬件

本课程专注于机器学习硬件,但在此刻,我想进行更广泛的概括。当然,机器学习领域存在大量机遇,但其他领域也存在许多机遇。我们讨论机器学习硬件或更广义的“面向X的硬件”,不仅仅是因为机器学习重要,还因为存在根本性的技术挑战,促使我们需要思考更专用的硬件。

一个表明计算机架构进入“新黄金时代”的强烈信号,是2018年图灵奖授予Hennessy和Patterson。他们总结了过去五十年的三个核心经验教训:

  1. 软件进步启发架构创新:硬件始终是为软件设计的。我们需要定量方法、基准测试来评估硬件性能。许多通用架构原则(如缓存、分支预测、预取)都受到软件行为的启发。
  2. 硬件软件接口至关重要:如何设计硬件软件接口为架构创新开辟了许多机会。指令集架构的粒度、硬件控制向软件的暴露程度,都是关键讨论点。未来的硬件设计必须充分考虑软件将如何与之交互。
  3. 市场检验架构争论:架构与半导体产业紧密相连。许多想法最终需要在工业中应用,以检验其是否解决了实际问题。市场将给出答案,目前我们看到众多初创公司和老牌企业都在进行创新,谁将胜出仍是开放的问题。

机器学习硬件正是这一趋势的一部分。它由机器学习应用强大的计算需求驱动,涉及如何向系统暴露基本运算单元,以及如何设计硬件软件之间的抽象层次。

对硬件设计师的启示:成为“文艺复兴”式的全栈思考者

对于思考连接硬件和软件领域的你们,我想强调:最终这将是一个相当复杂的软硬件系统。无论你未来是数字设计师、计算机架构师、软件工程师还是系统程序员,拥有一系统视角都至关重要。即使只负责整个拼图的一小块,也需要思考接口、集成以及如何与系统的其他部分协同工作。

从教育角度,我鼓励大家成为“文艺复兴”式的硬件设计师,不要自我设限。深入理解你的专业领域固然重要,但同时也应了解其上一层和下一层的知识。这样你至少能理解相关术语,与那些领域的专家进行有效对话,并关注其中的机遇。能够进行跨层优化、打破抽象的人,需要至少精通一个以上的领域。

未来硬件设计的思维模式

最后,我想分享两个我个人对未来硬件设计思维模式的看法:

  1. 架构具有时间性:硬件是时代的反映,随着应用和技术的假设变化而演进。不要被历史经验束缚,要有勇气构建反映当前时代挑战的硬件。核心原则(如局部性、并行性)是永恒的,但具体实现机制可以随假设变化而创新。
  2. 架构具有空间性:现代计算系统日益空间分布化。我们不再仅仅建造功能强大的单线程“摩天大楼”,而是在构建更扁平、由众多可能专门化的“房屋”(加速器)组成的架构。关键在于如何高效地组织、协调这些“房屋”,使它们能够通信、共享数据、协同工作以完成更大的任务。理解整个系统以及你构建的部分如何与周围环境集成变得非常重要。

总结与致谢

本节课中我们一起回顾了整个学期的学习历程,从机器学习硬件的基础知识到系统级思考,并展望了更广阔的硬件设计未来。我们以机器学习硬件为起点,但将其泛化到过去几年所学的经验教训中。

我衷心感谢本学期与我们并肩作战的GSI Abraham (Abe) Gonzalez,他在这个充满挑战的学期付出了巨大的努力。我也要感谢在座的所有同学,感谢你们的时间、参与和反馈。在这个虚拟学期中,与你们的互动让我个人受益匪浅,也带来了很多乐趣。

你们应该为自己感到骄傲,成功完成了三个实验和项目工作。请保持好奇与乐观。硬件设计师通常更乐观,因为我们总是在寻找解决问题的方法,而不是抱怨问题。

课程即将结束,但学习永无止境。我期待未来与大家保持联系。祝大家学期末一切顺利,享受暑假,迎接未来所有激动人心的机会。

保持联系,我们下次再见!

posted @ 2026-03-26 12:18  布客飞龙III  阅读(96)  评论(0)    收藏  举报