构建具有出色性能的系统需要很好地理解算法和模型以捕获问题的统计方面。同时,对底层硬件至少有一点了解也是必不可少的。当前部分不能替代有关硬件和系统设计的适当课程。相反,它可以作为理解为什么某些算法比其他算法更有效以及如何实现良好吞吐量的起点。一个好的设计可以很容易地产生一个数量级的差异,反过来,这可以在能够训练网络(例如,在一周内)和根本不能(在 3 个月内,从而错过最后期限)之间产生差异). 我们将从查看计算机开始。然后我们将放大以更仔细地查看 CPU 和 GPU。
图 13.4.1每个程序员都应该知道的延迟数。
不耐烦的读者可以通过 图 13.4.1来解决。它摘自 Colin Scott 的 互动帖子 ,该帖子很好地概述了过去十年的进展。原始数字来自 Jeff Dean 2010 年在斯坦福的演讲。下面的讨论解释了这些数字的一些基本原理,以及它们如何指导我们设计算法。下面的讨论是非常高层次和粗略的。它显然不能替代适当的课程,而只是为统计建模人员提供足够的信息以做出适当的设计决策。对于计算机体系结构的深入概述,我们建议读者参阅 (Hennessy 和 Patterson,2011 年)或最近关于该主题的课程,例如Arste Asanovic的课程。
13.4.1。电脑
大多数深度学习研究人员和从业者都可以使用具有相当数量内存、计算能力、某种形式的加速器(如 GPU)或其倍数的计算机。计算机由以下关键部件组成:
能够执行我们给它的程序(除了运行操作系统和许多其他东西)的处理器(也称为 CPU),通常由 8 个或更多内核组成。
内存 (RAM),用于存储和检索计算结果,例如权重向量和激活以及训练数据。
速度范围为 1 GB/s 到 100 GB/s 的以太网网络连接(有时是多个)。在高端服务器上可以找到更高级的互连。
用于将系统连接到一个或多个 GPU 的高速扩展总线 (PCIe)。服务器有多达 8 个加速器,通常以高级拓扑连接,而桌面系统有 1 个或 2 个,具体取决于用户的预算和电源的大小。
耐用存储设备,例如磁性硬盘驱动器、固态驱动器,在许多情况下使用 PCIe 总线连接。它提供训练数据到系统的高效传输,并根据需要存储中间检查点。
图 13.4.2计算机组件的连接性。
如图13.4.2所示,大多数组件(网络、GPU 和存储)都通过 PCIe 总线连接到 CPU。它由多个直接连接到 CPU 的通道组成。例如,AMD 的 Threadripper 3 有 64 个 PCIe 4.0 通道,每个通道都能够在两个方向上进行 16 Gbit/s 的数据传输。内存直连CPU,总带宽高达100GB/s。
当我们在计算机上运行代码时,我们需要将数据混洗到处理器(CPU 或 GPU)、执行计算,然后将结果从处理器移回 RAM 和持久存储。因此,为了获得良好的性能,我们需要确保它可以无缝运行,而不会有任何一个系统成为主要瓶颈。例如,如果我们不能足够快地加载图像,处理器将无事可做。同样,如果我们不能足够快地将矩阵移动到 CPU(或 GPU),它的处理元素就会饿死。最后,如果我们想通过网络同步多台计算机,后者不应该减慢计算速度。一种选择是交错通信和计算。让我们更详细地了解各种组件。
13.4.2。记忆
最基本的内存用于存储需要随时访问的数据。目前 CPU RAM 通常是 DDR4类型,每个模块提供 20–25 GB/s 的带宽。每个模块都有一个 64 位宽的总线。通常使用成对的内存模块来允许多个通道。CPU 有 2 到 4 个内存通道,即它们有 4 0GB/s 到 100 GB/s 的峰值内存带宽。每个通道通常有两个库。例如 AMD 的 Zen 3 Threadripper 有 8 个插槽。
尽管这些数字令人印象深刻,但它们确实只说明了部分情况。当我们想从内存中读取一部分时,我们首先需要告诉内存模块在哪里可以找到信息。也就是说,我们首先需要将地址发送到RAM。完成此操作后,我们可以选择只读取单个 64 位记录或一长串记录。后者称为突发读取. 简而言之,向内存发送地址并设置传输大约需要 100 ns(具体取决于所使用的内存芯片的具体时序系数),随后的每次传输仅需 0.2 ns。简而言之,第一次阅读的成本是后续阅读的 500 倍!请注意,我们每秒最多可以执行 10,000,000 次随机读取。这表明我们尽可能避免随机内存访问,而是使用突发读取(和写入)。
当我们考虑到我们有多家银行时,事情就有点复杂了。每个银行都可以在很大程度上独立地读取内存。这意味着两件事。一方面,随机读取的有效数量高达 4 倍,前提是它们均匀分布在内存中。这也意味着执行随机读取仍然是一个坏主意,因为突发读取也快了 4 倍。另一方面,由于内存对齐到 64 位边界,最好将任何数据结构对齐到相同的边界。 当设置了适当的标志时,编译器几乎会 自动执行此操作。我们鼓励好奇的读者复习一下关于 DRAM 的讲座,例如Zeshan Chishti的讲座。
GPU 内存需要满足更高的带宽要求,因为它们的处理元素比 CPU 多得多。总的来说,有两种选择可以解决这些问题。首先是使内存总线显着变宽。例如,NVIDIA 的 RTX 2080 Ti 具有 352 位宽的总线。这允许同时传输更多信息。其次,GPU 使用特定的高性能内存。消费级设备,例如 NVIDIA 的 RTX 和 Titan 系列通常使用GDDR6 总带宽超过 500 GB/s 的芯片。另一种方法是使用 HBM(高带宽内存)模块。它们使用非常不同的接口,并直接与专用硅晶圆上的 GPU 连接。这使得它们非常昂贵,而且它们的使用通常仅限于高端服务器芯片,例如 NVIDIA Volta V100 系列加速器。不出所料,GPU 内存通常比 CPU 内存小得多,因为前者的成本较高。就我们的目的而言,它们的性能特征大体上相似,只是速度快得多。出于本书的目的,我们可以安全地忽略细节。它们仅在调整 GPU 内核以实现高吞吐量时才重要。
13.4.3。贮存
我们看到 RAM 的一些关键特性是带宽和 延迟。存储设备也是如此,只是差异可能更加极端。
13.4.3.1。硬盘驱动器
硬盘驱动器(HDD) 已经使用了半个多世纪。简而言之,它们包含许多带有磁头的旋转盘片,可以定位以在任何给定轨道上读取或写入。高端磁盘在 9 个盘片上最多可容纳 16 TB。HDD 的主要优点之一是它们相对便宜。它们的众多缺点之一是它们通常的灾难性故障模式和相对较高的读取延迟。
要理解后者,请考虑 HDD 以大约 7,200 RPM(每分钟转数)旋转的事实。如果它们快得多,它们就会因施加在盘片上的离心力而破碎。在访问磁盘上的特定扇区时,这有一个主要的缺点:我们需要等到盘片旋转到位(我们可以移动磁头但不能加速实际磁盘)。因此,在请求的数据可用之前,它可能需要 8 毫秒以上的时间。一种常见的表达方式是 HDD 可以以大约 100 IOP(每秒输入/输出操作)的速度运行。这个数字在过去二十年中基本保持不变。更糟糕的是,增加带宽同样困难(大约为 100–200 MB/s)。毕竟,每个磁头都读取一条比特轨道,因此,比特率仅与信息密度的平方根成比例。因此,HDD 正迅速降级为非常大的数据集的归档存储和低级存储。
13.4.3.2。固态硬盘
固态硬盘 (SSD) 使用闪存来持久存储信息。这允许更快地访问存储的记录。现代 SSD 可以以 100,000 到 500,000 IOP 的速度运行,即比 HDD 快 3 个数量级。此外,它们的带宽可以达到 1–3GB/s,即比 HDD 快一个数量级。这些改进听起来好得令人难以置信。实际上,由于 SSD 的设计方式,它们具有以下警告。
SSD 以块(256 KB 或更大)的形式存储信息。它们只能作为一个整体来写,这会花费大量时间。因此,SSD 上的按位随机写入性能非常差。同样,写入数据通常会花费大量时间,因为必须读取、擦除块,然后用新信息重写。到目前为止,SSD 控制器和固件已经开发出算法来缓解这种情况。尽管如此,写入速度可能会慢得多,尤其是对于 QLC(四级单元)SSD。提高性能的关键是维护一个 操作队列,尽可能在大块中优先读取和写入。
SSD 中的存储单元磨损相对较快(通常在几千次写入后就已经磨损)。磨损级保护算法能够将退化传播到许多单元上。也就是说,不建议将 SSD 用于交换文件或日志文件的大量聚合。
最后,带宽的大幅增加迫使计算机设计人员将 SSD 直接连接到 PCIe 总线。能够处理此问题的驱动器称为 NVMe(增强型非易失性内存),最多可使用 4 个 PCIe 通道。在 PCIe 4.0 上这相当于高达 8GB/s。
13.4.3.3。云储存
云存储提供可配置的性能范围。也就是说,存储分配给虚拟机是动态的,无论是数量还是速度,都由用户选择。我们建议用户在延迟太高时增加 IOP 的配置数量,例如,在使用许多小记录进行训练期间。
13.4.4。处理器
中央处理器 (CPU) 是任何计算机的核心部件。它们由许多关键组件组成:能够执行机器代码的处理器内核、连接它们的总线(特定拓扑在处理器型号、代数和供应商之间有很大差异),以及允许更高带宽和更低延迟内存的缓存访问比从主存储器读取可能的访问。最后,几乎所有现代 CPU 都包含矢量处理单元,以辅助高性能线性代数和卷积,因为它们在媒体处理和机器学习中很常见。
图 13.4.3 Intel Skylake 消费者四核 CPU。
图 13.4.3描绘了 Intel Skylake 消费级四核 CPU。它有一个集成的 GPU、缓存和连接四个内核的环形总线。以太网、WiFi、蓝牙、SSD 控制器和 USB 等外围设备要么是芯片组的一部分,要么直接连接 (PCIe) 到 CPU。
13.4.4.1。微架构
每个处理器内核都包含一组相当复杂的组件。虽然各代和供应商之间的细节有所不同,但基本功能几乎是标准的。前端加载指令并尝试预测将采用哪条路径(例如,用于控制流)。然后将指令从汇编代码解码为微指令。汇编代码通常不是处理器执行的最低级别代码。相反,复杂的指令可以被解码成一组更底层的操作。这些然后由实际执行核心处理。通常后者能够同时执行许多操作。例如, 图 13.4.4的 ARM Cortex A77 核心能够同时执行多达 8 个操作。
图 13.4.4 ARM Cortex A77 微架构。
这意味着高效的程序可能能够在每个时钟周期执行多条指令,前提是它们可以独立执行。并非所有单位生而平等。一些专注于整数指令,而另一些则针对浮点性能进行了优化。为了增加吞吐量,处理器还可以在分支指令中同时遵循多个代码路径,然后丢弃未采用的分支的结果。这就是为什么分支预测单元(在前端)很重要,以至于只追求最有希望的路径。
13.4.4.2。矢量化
深度学习非常需要计算。因此,要使 CPU 适合机器学习,需要在一个时钟周期内执行许多操作。这是通过矢量单元实现的。它们有不同的名称:在 ARM 上它们被称为 NEON,在 x86 上它们(最近一代)被称为 AVX2 单元。一个共同点是它们能够执行 SIMD(单指令多数据)操作。图 13.4.5显示了在 ARM 上如何在一个时钟周期内添加 8 个短整数。
图 13.4.5 128 位 NEON 矢量化。
根据体系结构的选择,此类寄存器的长度可达 512 位,最多可组合 64 对数字。例如,我们可能将两个数字相乘并将它们与第三个数字相加,这也称为融合乘加。英特尔的 OpenVino使用这些在服务器级 CPU 上实现深度学习的可观吞吐量。但请注意,这个数字与 GPU 能够实现的目标相比完全相形见绌。例如,NVIDIA 的 RTX 2080 Ti 拥有 4,352 个 CUDA 核心,每个核心都可以随时处理这样的操作。
13.4.4.3。缓存
考虑以下情况:如上图 13.4.3所示,我们有一个普通的 4 核 CPU 核,运行频率为 2 GHz。此外,假设我们的 IPC(每时钟指令数)计数为 1,并且这些单元启用了 256 位宽度的 AVX2。我们进一步假设至少有一个用于 AVX2 操作的寄存器需要从内存中检索。这意味着 CPU 消耗 4×256bit=128bytes每个时钟周期的数据。除非我们能够转移 2×109×128=256×109每秒向处理器发送的字节数,处理元素将饿死。不幸的是,这种芯片的内存接口仅支持 20–40 GB/s 的数据传输,即低一个数量级。解决方法是尽可能避免从内存加载新数据,而是将其缓存在 CPU 本地。这是缓存派上用场的地方。通常使用以下名称或概念:
寄存器严格来说不是缓存的一部分。他们帮助阶段性指示。也就是说,CPU 寄存器是 CPU 可以以时钟速度访问而不会造成任何延迟损失的内存位置。CPU 有几十个寄存器。有效地使用寄存器取决于编译器(或程序员)。例如 C 编程语言有一个register关键字。
L1 缓存是抵御高内存带宽需求的第一道防线。L1 缓存很小(典型大小可能为 32–64 KB)并且通常分为数据和指令缓存。当在一级缓存中找到数据时,访问速度非常快。如果在那里找不到它们,搜索将沿着缓存层次结构向下进行。
二级缓存是下一站。根据体系结构设计和处理器大小,它们可能是独占的。它们可能只能由给定的核心访问或在多个核心之间共享。L2 缓存比 L1 更大(通常每个内核 256–512 KB)并且更慢。此外,要访问 L2 中的某些内容,我们首先需要检查以了解数据不在 L1 中,这会增加少量的额外延迟。
L3 缓存在多个内核之间共享,并且可能非常大。AMD 的 Epyc 3 服务器 CPU 拥有分布在多个小芯片上的高达 256 MB 的缓存。更典型的数字在 4–8 MB 范围内。
预测接下来需要哪些存储元件是芯片设计中的关键优化参数之一。例如,建议以正向遍历内存,因为大多数缓存算法将尝试提前读取而不是向后读取。同样,将内存访问模式保持在本地是提高性能的好方法。
添加缓存是一把双刃剑。一方面,它们确保处理器内核不会缺少数据。同时,它们增加了芯片尺寸,占用了本来可以用于提高处理能力的面积。此外,高速缓存未命中的代价可能很高。考虑最坏的情况,错误共享,如图13.4.6所示。当处理器 1 上的线程请求数据时,内存位置缓存在处理器 0 上。为了获得它,处理器 0 需要停止它正在做的事情,将信息写回主内存,然后让处理器 1 从内存中读取它。在此操作期间,两个处理器都在等待。这样的代码很可能运行 得更慢与高效的单处理器实现相比,在多个处理器上。这是缓存大小存在实际限制(除了它们的物理大小)的另一个原因。
图 13.4.6虚假共享(图片由英特尔提供)。
13.4.5。GPU 和其他加速器
可以毫不夸张地说,如果没有 GPU,深度学习就不会成功。出于同样的原因,GPU 制造商的财富因深度学习而大幅增加的说法也十分合理。硬件和算法的这种共同进化导致了这样一种情况,即无论好坏,深度学习都是更可取的统计建模范例。因此,有必要了解 GPU 和相关加速器(如 TPU)的具体优势 (Jouppi等人,2017 年)。
值得注意的是在实践中经常出现的区别:加速器针对训练或推理进行了优化。对于后者,我们只需要计算网络中的前向传播。反向传播不需要存储中间数据。此外,我们可能不需要非常精确的计算(FP16 或 INT8 通常就足够了)。另一方面,在训练期间,所有中间结果都需要存储以计算梯度。此外,累积梯度需要更高的精度以避免数值下溢(或溢出)。这意味着 FP16(或与 FP32 的混合精度)是最低要求。所有这些都需要更快、更大的内存(HBM2 与 GDDR6)和更强的处理能力。例如,英伟达的 图灵 T4 GPU 针对推理进行了优化,而 V100 GPU 更适合训练。
回忆一下图 13.4.5中所示的矢量化。将矢量单元添加到处理器内核使我们能够显着提高吞吐量。例如,在图 13.4.5的示例中,我们能够同时执行 16 个操作。首先,如果我们添加不仅优化向量之间的操作而且优化矩阵之间的操作会怎样?这种策略导致了张量核(稍后将介绍)。其次,如果我们添加更多的内核会怎样?简而言之,这两种策略总结了 GPU 中的设计决策。 图 13.4.7给出基本处理块的概述。它包含 16 个整数和 16 个浮点单元。除此之外,两个张量核心可加速一小部分与深度学习相关的附加操作。每个流式多处理器由四个这样的块组成。
图 13.4.7 NVIDIA 图灵处理块(图片由 NVIDIA 提供)。
接下来,将 12 个流式多处理器组合成图形处理集群,组成高端 TU102 处理器。充足的内存通道和 L2 缓存补充了设置。图 13.4.8 有相关的细节。设计这种设备的原因之一是可以根据需要添加或删除单个块,以允许更紧凑的芯片并处理良率问题(有故障的模块可能不会被激活)。幸运的是,在 CUDA 和框架代码层下,对此类设备进行编程对于随意的深度学习研究人员来说是隐藏的。特别是,如果有可用资源,多个程序可能会在 GPU 上同时执行。尽管如此,了解设备的局限性以避免选择不适合设备内存的模型是值得的。
图 13.4.8 NVIDIA 图灵架构(图片由 NVIDIA 提供)
最后一个值得更详细地提及的方面是张量核。它们是最近趋势的一个例子,即添加对深度学习特别有效的更优化电路。例如,TPU 添加了一个脉动阵列( Kung, 1988 )用于快速矩阵乘法。那里的设计是为了支持极少数(第一代 TPU 中的一个)大型操作。张量核在另一端。它们针对涉及之间的小型操作进行了优化4×4和16×16 矩阵,取决于它们的数值精度。 图 13.4.9给出了优化的概览。
图 13.4.9图灵中的 NVIDIA 张量核心(图片由 NVIDIA 提供)。
显然,在优化计算时,我们最终会做出某些妥协。其中之一是 GPU 不太擅长处理中断和稀疏数据。虽然也有明显的例外,例如 Gunrock (Wang等人,2016 年),但稀疏矩阵和向量的访问模式并不适合 GPU 擅长的高带宽突发读取操作。匹配这两个目标是一个活跃的研究领域。参见例如DGL,这是一个为图形深度学习而调整的库。
13.4.6。网络和总线
每当单个设备不足以进行优化时,我们需要将数据传输到它或从它传输数据以同步处理。这就是网络和总线派上用场的地方。我们有许多设计参数:带宽、成本、距离和灵活性。一方面,我们的 WiFi 范围很广,非常易于使用(毕竟没有电线),价格便宜,但它提供的带宽和延迟相对一般。头脑正常的机器学习研究人员不会使用它来构建服务器集群。在下文中,我们将重点关注适合深度学习的互连。
PCIe是一种专用总线,用于每条通道的超高带宽点对点连接(在 16 通道插槽中的 PCIe 4.0 上高达 32 GB/s)。延迟大约为个位数微秒 (5 μs)。PCIe 链接很宝贵。处理器数量有限:AMD 的 EPYC 3 有 128 条通道,Intel 的 Xeon 每个芯片最多有 48 条通道;在桌面级 CPU 上,数字分别为 20 (Ryzen 9) 和 16 (Core i9)。由于 GPU 通常有 16 条通道,这限制了可以全带宽连接到 CPU 的 GPU 数量。毕竟,它们需要与存储和以太网等其他高带宽外围设备共享链路。就像 RAM 访问一样,由于减少了数据包开销,大容量传输更可取。
以太网是最常用的计算机连接方式。虽然它比 PCIe 慢得多,但它非常便宜且安装灵活,并且覆盖的距离更长。低档服务器的典型带宽为 1 GBit/s。高端设备(例如,云中的C5 实例)提供 10 到 100 GBit/s 的带宽。与之前的所有情况一样,数据传输具有显着的开销。请注意,我们几乎从不直接使用原始以太网,而是使用在物理互连之上执行的协议(例如 UDP 或 TCP/IP)。这进一步增加了开销。与 PCIe 一样,以太网旨在连接两个设备,例如计算机和交换机。
交换机允许我们以任意一对设备可以同时执行(通常是全带宽)点对点连接的方式连接多个设备。例如,以太网交换机可能以高截面带宽连接 40 台服务器。请注意,交换机并不是传统计算机网络所独有的。甚至可以 切换PCIe 通道。这发生在例如将大量 GPU 连接到主机处理器时,如P2 实例的情况。
在超高带宽互连方面,NVLink是 PCIe 的替代方案。它提供每条链路高达 300 Gbit/s 的数据传输速率。服务器 GPU (Volta V100) 有六个链接,而消费级 GPU (RTX 2080 Ti) 只有一个链接,以降低的 100 Gbit/s 速率运行。我们建议使用 NCCL来实现 GPU 之间的高数据传输。
13.4.7。更多延迟数字
第 13.4.7 节和 第 13.4.7 节中的摘要来自Eliot Eshelman,他将数字的更新版本维护为GitHub 要点。
行动 | 时间 | 笔记 |
---|---|---|
一级缓存引用/命中 | 1.5纳秒 | 4个周期 |
浮点加法/乘法/FMA | 1.5纳秒 | 4个周期 |
L2 缓存引用/命中 | 5纳秒 | 12 ~ 17 周期 |
分支预测错误 | 6纳秒 | 15 ~ 20 次循环 |
L3 缓存命中(非共享缓存) | 16纳秒 | 42个周期 |
L3缓存命中(在另一个核心共享) | 25纳秒 | 65个周期 |
互斥锁定/解锁 | 25纳秒 | |
L3缓存命中(在另一个核心修改) | 29纳秒 | 75个周期 |
L3 缓存命中(在远程 CPU 插槽上) | 40纳秒 | 100 ~ 300 次循环 (40 ~ 116 ns) |
QPI 跳到另一个 CPU(每跳) | 40纳秒 | |
64MB 内存参考。(本地 CPU) | 46纳秒 | Broadwell E5-2690v4 上的 TinyMemBench |
64MB 内存参考。(远程 CPU) | 70 纳秒 | Broadwell E5-2690v4 上的 TinyMemBench |
256MB 内存参考。(本地 CPU) | 75 纳秒 | Broadwell E5-2690v4 上的 TinyMemBench |
英特尔傲腾随机写入 | 94纳秒 | UCSD 非易失性系统实验室 |
256MB 内存参考。(远程 CPU) | 120纳秒 | Broadwell E5-2690v4 上的 TinyMemBench |
英特尔傲腾随机读取 | 305纳秒 | UCSD 非易失性系统实验室 |
通过 100 Gbps HPC 结构发送 4KB | 1微秒 | 基于 Intel Omni-Path 的 MVAPICH2 |
使用 Google Snappy 压缩 1KB | 3微秒 | |
通过 10 Gbps 以太网发送 4KB | 10微秒 | |
随机写入 4KB 到 NVMe SSD | 30微秒 | DC P3608 NVMe SSD(QOS 99%为500μs) |
向/从 NVLink GPU 传输 1MB | 30微秒 | 在 NVIDIA 40GB NVLink 上约为 33GB/s |
向/从 PCI-E GPU 传输 1MB | 80微秒 | 在 PCIe 3.0 x16 链路上约为 12GB/s |
从 NVMe SSD 随机读取 4KB | 120微秒 | DC P3608 NVMe SSD (QOS 99%) |
从 NVMe SSD 顺序读取 1MB | 208微秒 | ~4.8GB/s DC P3608 NVMe SSD |
随机写入 4KB 到 SATA SSD | 500微秒 | DC S3510 SATA 固态硬盘 (QOS 99.9%) |
从 SATA SSD 随机读取 4KB | 500微秒 | DC S3510 SATA 固态硬盘 (QOS 99.9%) |
同一数据中心内的往返 | 500微秒 | 单向 ping 约为 250μs |
从 SATA SSD 顺序读取 1MB | 2 毫秒 | ~550MB/s DC S3510 SATA SSD |
从磁盘顺序读取 1MB | 5 毫秒 | ~200MB/s 服务器硬盘 |
随机磁盘访问(查找+旋转) | 10 毫秒 | |
发包 CA->Netherlands->CA | 150 毫秒 |
表:常见的延迟数字。
行动 | 时间 | 笔记 |
---|---|---|
GPU 共享内存访问 | 30纳秒 | 30~90 个周期(bank 冲突增加延迟) |
GPU 全局内存访问 | 200纳秒 | 200~800次循环 |
在 GPU 上启动 CUDA 内核 | 10微秒 | 主机 CPU 指示 GPU 启动内核 |
向/从 NVLink GPU 传输 1MB | 30微秒 | 在 NVIDIA 40GB NVLink 上约为 33GB/s |
向/从 PCI-E GPU 传输 1MB | 80微秒 | ~12GB/s 在 PCI-Express x16 链路上 |
表:NVIDIA Tesla GPU 的延迟数。
13.4.8。概括
设备有操作开销。因此,重要的是要针对少量的大额转账而不是许多小额转账。这适用于 RAM、SSD、网络和 GPU。
矢量化是性能的关键。确保您了解加速器的特定功能。例如,某些 Intel Xeon CPU 特别适合 INT8 运算,NVIDIA Volta GPU 擅长 FP16 矩阵-矩阵运算,而 NVIDIA Turing 在 FP16、INT8 和 INT4 运算方面表现出色。
由于小数据类型导致的数值溢出可能是训练期间的一个问题(并且在推理期间的程度较小)。
别名会显着降低性能。例如,64 位 CPU 上的内存对齐应该按照 64 位边界进行。在 GPU 上,保持卷积大小对齐是个好主意,例如,与张量核心对齐。
将您的算法与硬件相匹配(例如,内存占用和带宽)。当将参数装入缓存时,可以实现很大的加速(数量级)。
我们建议您在验证实验结果之前先在纸上勾勒出新算法的性能。数量级或更多的差异是令人担忧的原因。
使用分析器调试性能瓶颈。
训练和推理硬件在价格和性能方面有不同的优势。
13.4.9。练习
编写C代码测试访问相对于外部存储器接口对齐或未对齐的内存是否存在速度差异。提示:注意缓存效果。
测试按顺序访问内存或以给定步幅访问内存之间的速度差异。
您如何测量 CPU 上的高速缓存大小?
您将如何在多个内存通道中布置数据以获得最大带宽?如果你有很多小线程,你会如何布局?
企业级 HDD 的转速为 10,000 rpm。HDD 在读取数据之前需要花费最坏情况的绝对最短时间是多少(您可以假设磁头几乎是瞬间移动)?为什么 2.5 英寸 HDD 越来越受商业服务器欢迎(相对于 3.5 英寸和 5.25 英寸驱动器)?
假设 HDD 制造商将存储密度从每平方英寸 1 Tbit 提高到每平方英寸 5 Tbit。您可以在 2.5 英寸 HDD 的环上存储多少信息?内轨和外轨有区别吗?
从 8 位到 16 位数据类型增加了大约四倍的硅数量。为什么?为什么 NVIDIA 会在其 Turing GPU 中添加 INT4 运算?
通过内存向前阅读与向后阅读相比快多少?这个数字在不同的计算机和 CPU 供应商之间是否不同?为什么?编写 C 代码并进行试验。
你能测量你的磁盘的缓存大小吗?典型的 HDD 是什么?SSD 需要缓存吗?
测量通过以太网发送消息时的数据包开销。查看 UDP 和 TCP/IP 连接之间的区别。
直接内存访问允许 CPU 以外的设备直接写入(和读取)内存。为什么这是个好主意?
查看 Turing T4 GPU 的性能数据。为什么当您从 FP16 到 INT8 和 INT4 时,性能“仅”翻了一番?
在旧金山和阿姆斯特丹之间往返,一个包裹最短需要多长时间?提示:您可以假设距离为 10,000 公里。
Discussions
-
硬件
+关注
关注
11文章
3251浏览量
66104 -
pytorch
+关注
关注
2文章
803浏览量
13143
发布评论请先 登录
相关推荐
评论