如何选择最适合您的 ML 工作负载的最佳计算机
在我们日常的 AI 开发过程中,我们不断地决定在哪些最适合的计算机上运行每个机器学习 (ML) 工作负载。这些决策并不轻松,因为它们可能对开发速度和成本产生有意义的影响。为顺序算法 (例如,连接组件算法的标准实现) 分配一台带有一个或多个 GPU 的计算机可能被认为是浪费的,而在 CPU 上训练大型语言模型可能需要花费禁止性的长时间。
在大多数情况下,我们将有一系列可供选择的机器选项。在使用云服务基础设施进行 ML 开发时,我们通常有选择各种硬件规格的广泛机器类型的选择。这些通常分组为机器类型系列 (在 AWS 上称为实例类型,在 GCP 上称为机器系列,在 Microsoft Azure 上称为虚拟机系列),每个系列都针对不同类型的用例。由于有如此多的选择,很容易感到不知所措或选择过载,许多在线资源存在于帮助人们导航实例选择过程中。
在本文中,我们希望将注意力集中在为深度学习 (DL) 工作负载选择适当的实例类型上。DL 工作负载通常是极其计算密集型的,并且通常需要专用的硬件加速器,例如 GPU。我们在本文中的意图是提出一些选择 DL 机型的指导原则,并突出显示在做出此决定时应考虑的机器类型之间的一些主要区别。
此实例选择指南有何不同
在我们看来,许多现有的实例指南导致了很多机会的错失。它们通常涉及基于几个预定义属性 (例如,计算需求、内存需求、网络需求等) 对您的应用程序进行分类,并提出一个基于这些属性选择实例类型的流程图。他们往往低估了许多 ML 应用程序的高度复杂性,以及简单的事实,即用这种方式对它们进行分类并不总是足以预测它们的性能挑战。我们发现,盲目遵循这样的指南有时会导致选择次优的实例类型。正如我们将要看到的那样,我们提出的方法要更加实践和数据驱动。它涉及定义用于比较不同实例类型选项上应用程序性能的清晰指标和工具。我们相信,这种方法需要确保您真正最大化机会。
免责声明
请不要将我们提到的任何特定实例类型、DL 库、云服务提供商等视为其使用的认可。最佳选项取决于您自己项目的独特细节。此外,我们提出的任何建议都不应被视为不得不在应用之前经过仔细评估和调整以适应您的用例的谦虚建议。
第一部分:实例类型选择的建议原则
与任何其他重要的开发设计决策一样,强烈建议您拥有明确的指导方针以达到最佳解决方案。最简单的方法就是使用您以前项目使用过的计算机类型和/或最熟悉的计算机类型。然而,这样做可能会使您错过显著降低成本和/或整体开发时间加快的机会。在本节中,我们提出了一些实例类型搜索的指导原则。
定义用于比较的清晰指标和工具
也许我们将要讨论的最重要的指导原则是需要明确定义比较不同实例类型上应用程序性能的指标及其测量工具。如果没有清晰定义您正在尝试优化的效用函数,您将无法知道您选择的机器是否是最佳的。您的效用函数可能在项目之间有所不同,甚至可能在单个项目的过程中发生变化。当您的预算紧张时,您可能会优先考虑降低成本而不是加快速度。当重要的客户截止日期临近时,您可能更喜欢以任何代价加快速度。
示例:每美元度量样本数 在之前的文章中(例如,这里),我们提出了每美元样本,即每花费一美元,我们模型中馈入的样本数量,作为运行DL模型(用于训练或推断)性能的一种度量。 每美元样本的公式如下:
其中,每秒样本数=批量大小*每秒批量数。训练实例成本通常可以在网上找到。当然,仅优化这个度量可能是不够的:它可能最小化训练的总成本,但没有包括考虑总体开发时间的度量,您可能会错过所有客户的截止日期。另一方面,开发速度有时可以通过在多个实例上并行训练来控制,从而使我们达到速度目标,而不考虑选择的实例类型。在任何情况下,我们的简单示例演示了考虑多个性能度量并根据ML项目的详细信息(例如预算和调度限制)对它们进行权衡的必要性。
如果没有一种方法来衡量度量,则制定度量是无用的。您必须将所选指标的测量定义和构建到您的应用程序中。在下面的代码块中,我们显示了一个简单的基于PyTorch的训练循环,其中我们包括一行简单的代码,以便定期打印每秒处理的样本平均数。将其除以实例类型的发布成本(每秒)即可得到上述每美元成本的指标。
import time batch_size = 128 data_loader = get_data_loader(batch_size) global_batch_size = batch_size * world_size interval = 100 t0 = time.perf_counter() for idx, (inputs, target) in enumerate(data_loader, 1): train_step(inputs, target) if idx % interval == 0: time_passed = time.perf_counter() - t0 samples_processed = global_batch_size * interval print(f'{samples_processed / time_passed} samples/second') t0 = time.perf_counter()
有多种选择
一旦我们清楚地定义了我们的效用函数,选择最佳实例类型就是找到最大化效用函数的实例类型。显然,我们可以选择的实例类型的搜索空间越大,我们就可以达到更好的整体效用结果。因此,希望有大量的选项。但我们还应该在实例类型上追求多样性。深度学习项目通常涉及运行多个应用负载,这些应用负载在其系统需求和系统利用模式上差异很大。一个工作负载的最优机器类型可能与另一个工作负载的最优机器类型在其规格上差异很大。拥有一个大且多样化的实例类型集将增加您最大化项目所有工作负载性能的能力。
考虑多个选项
一些实例选择指南将建议将您的DL应用程序分类(例如,根据模型的大小和/或它是否执行训练或推断),并相应地选择(单个)计算实例。例如,AWS推广某些类型的实例(例如Amazon EC2 g5系列)用于ML推断,其他(更强大的)实例类型(例如Amazon EC2 p4系列)用于ML训练。然而,正如我们在介绍中提到的那样,我们认为盲目遵循这样的指导可能会导致性能优化的机会被忽视。事实上,我们发现对于许多训练工作负载,包括具有大型ML模型的工作负载,我们的效用函数通过被认为是面向推断的实例进行了最大化。
当然,我们不希望您测试每种可用的实例类型。基于硬件规格,有许多实例类型可以(和应该)被淘汰。我们不建议花时间在CPU上评估大型语言模型的性能。如果我们知道我们的模型需要高精度算法才能成功收敛,我们将不会花时间在Google Cloud TPU上运行它(参见此处)。但除了明显的硬件限制外,我们认为实例类型只应基于性能数据结果被淘汰。
多GPU Amazon EC2 g5实例通常被认为不适合用于训练模型的原因之一是,与Amazon EC2 p4相反,GPU之间的通信小猪AI是PCIe而不是NVLink,因此支持的数据吞吐量要低得多。然而,虽然高速的GPU到GPU通信确实对多GPU训练非常重要,但是PCIe支持的带宽可能对您的网络足够,或者您可能会发现其他性能瓶颈阻止您充分利用NVLink连接的速度。唯一确定的方法是通过实验和性能评估。
为了实现我们的效用函数目标,任何实例类型都是公平竞争的对象,在我们搜索实例类型的过程中,我们经常为低功率、更环保、被低估和价格更低的弱势群体加油。
以最大化选项的方式开发您的工作负载
不同的实例类型可能对我们的实现施加不同的限制。它们可能需要不同的初始化序列,支持不同的浮点数据类型或依赖于不同的SW安装。考虑到这些差异来开发您的代码将减少您对特定实例类型的依赖,并增加您利用性能优化机会的能力。
一些高级API包括对多个实例类型的支持。例如,PyTorch Lightening内置支持在许多不同类型的处理器上运行DL模型,将对每个处理器所需的实现细节隐藏在用户之后。支持的处理器包括CPU、GPU、Google Cloud TPU、HPU(Habana Gaudi)等。然而,请记住,为在特定处理器上运行所需的一些适应可能需要更改模型定义的代码(而不更改模型体系结构)。您可能还需要包括在加速器类型上有条件的代码块。一些API优化可能是为特定加速器实现的,而不是为其他加速器实现的(例如,针对GPU的缩放点积注意力(SDPA)API)。有些超参数,例如批次大小,可能需要调整才能达到最大性能。您可能需要进行其他更改的示例在我们关于专用AI训练加速器主题的系列博客文章中有所展示。
(重新)持续评估
重要的是,在我们当前的DL运行时优化领域中,性能比较结果很快就会过时。新的实例类型定期发布,扩展我们的搜索空间并提供增加效用的潜力。另一方面,受欢迎的实例类型可能会到达生命周期终点或由于全球需求高而变得难以获取。软件堆栈不同级别的优化(例如,请参见此处)也可以极大地推动性能指针。例如,PyTorch最近发布了一种新的图形编译模式,据报道可以在现代GPU上加速训练高达51%。这些加速(截至本文撰写时)还没有在其他加速器上演示。这是一个相当大的加速,可能迫使我们重新评估以前的实例选择决策。(有关PyTorch编译模式的更多信息,请参见我们最近发布的有关该主题的文章。)因此,性能比较不应该是一次性活动;为了充分利用所有这些令人难以置信的创新,应该定期进行评估和更新。
第2部分:实例类型之间的差异
了解您可以使用的实例类型的详细信息,特别是它们之间的差异,对于决定哪些实例类型用于性能评估非常重要。在本节中,我们将这些分为三类:硬件规格,SW堆栈支持和实例可用性。
硬件规格
潜在实例类型之间最重要的区别在于它们的硬件规格的细节。有许多硬件细节可能会对深度学习工作负载的性能产生重大影响。这些包括:
- 硬件加速器的具体规格:我们使用哪些AI加速器(例如GPU/HPU/TPU),每个加速器支持多少内存,可以运行多少FLOP,支持哪些基本类型(例如bfloat16/float32)等?
- 硬件加速器之间通信的方式及其支持的带宽
- 多个实例之间通信的方式及其支持的带宽(例如,实例类型是否包括高带宽网络,例如Amazon EFA或Google FastSocket)。
- 样本数据摄入的网络带宽
- 整体CPU计算能力(通常负责样本数据输入管道)和加速器计算能力之间的比例。
要全面详细了解AWS上ML实例类型硬件规格的差异,请查看以下TDS帖子:
选择适合AWS深度学习的GPU
如何选择适合Amazon EC2 GPU实例的深度学习训练和推理-从最佳性能到…
towardsdatascience.com
深入了解您使用的实例类型的详细信息不仅对于了解哪些实例类型与您相关很重要,而且对于了解和克服在开发过程中发现的运行时性能问题也很重要。这在我们以前的许多博客文章中已经得到了证明(例如,在此处)。
软件堆栈支持
您考虑的实例类型的SW支持矩阵应该是您实例类型搜索的另一个输入。一些软件组件、库和/或API仅支持特定的实例类型。如果您的工作负载需要这些内容,则您的搜索空间将更有限。例如,一些模型依赖于为GPU构建的计算内核,而不是其他类型的加速器。另一个例子是Amazon SageMaker提供的用于模型分发的专用库,它可以提高多实例训练的性能,但是截至本文撰写时,仅支持有限数量的实例类型(更多详情,请参见此处)。还要注意,一些较新的实例类型(例如基于AWS Trainium的Amazon EC2 trn1实例)对它们支持的框架有限制。
实例可用性
过去几年中,芯片短缺的时间延长了,导致硬件组件和特别是GPU等加速器供应下降。不幸的是,这与最近在大型生成AI模型开发方面取得的里程碑所驱动的对这些组件需求的显着增加重合。供需不平衡已经导致我们无法获得我们选择的机器类型的情况不确定。
实例类型的可用性是评估和选择的重要输入。不幸的是,很难衡量可用性,甚至更难预测和计划。实例的可用性可以非常突然地发生变化。它今天可能在这里,明天可能就不在了。
请注意,在使用多个实例的情况下,我们可能不仅需要实例类型的可用性,还需要它们在同一数据中心的共存(例如,请参见此处)。ML工作负载通常依赖于实例之间的低网络延迟,它们之间的距离可能会影响性能。
另一个重要的考虑因素是低成本spot实例的可用性。许多云服务提供商提供优惠的计算引擎,从多余的云服务容量中获得(例如,AWS中的Amazon EC2 Spot实例,在Google Cloud Platform中的Preemptible VM实例以及Microsoft Azure中的Low-Priority VMs)。spot实例的缺点是它们可能会被中断并从您手中被夺走,而几乎没有警告。如果可用,并且如果您在应用程序中编写了容错性,则spot实例可以实现相当大的成本节约。
总结
在本文中,我们回顾了一些选择深度学习工作负载实例类型的考虑事项和建议。实例类型的选择可能对您项目的成功和发现最优实例的过程产生关键影响,因此应该以适当的方式来处理。本文远非全面。可能有其他甚至关键的考虑因素,我们没有讨论,可能适用于您的深度学习项目,应该予以考虑。
过去几年中AI发展的爆炸伴随着许多新的专用AI加速器的推出。这增加了可用实例类型选项的数量,并为优化提供了机会。它也使得寻找最优实例类型变得更具挑战性和更令人兴奋。愉快的寻找:)!!