使用Intel Sapphire Rapids加速PyTorch Transformers – 第2部分
Accelerating PyTorch Transformers with Intel Sapphire Rapids - Part 2
在最近的一篇帖子中,我们向您介绍了英特尔第四代Xeon CPU,代号为Sapphire Rapids,并介绍了其新的高级矩阵扩展(AMX)指令集。通过将一组运行在Amazon EC2上的Sapphire Rapids服务器与英特尔库(如PyTorch的英特尔扩展)相结合,我们向您展示了如何以高效的方式在规模上运行分布式训练,并与上一代Xeon(Ice Lake)相比实现了8倍的加速,并且几乎线性扩展。
在本文中,我们将重点关注推理。通过使用基于PyTorch实现的流行的HuggingFace transformers,我们首先将测量它们在Ice Lake服务器上对短文本和长文本NLP token序列的性能。然后,我们将使用Sapphire Rapids服务器和最新版本的Hugging Face Optimum Intel进行相同的测试,这是一个专门用于Intel平台硬件加速的开源库。
让我们开始吧!
为什么应该考虑基于CPU的推理
在决定是否在CPU或GPU上运行深度学习推理时,有几个因素需要考虑。最重要的因素当然是模型的大小。一般来说,较大的模型可能会从GPU提供的额外计算能力中获益更多,而较小的模型可以在CPU上高效运行。
另一个需要考虑的因素是模型和推理任务的并行级别。GPU专门设计用于大规模并行处理,因此对于可以有效并行化的任务,它们可能更高效。另一方面,如果模型或推理任务的并行级别不是非常高,CPU可能是更有效的选择。
成本也是需要考虑的一个重要因素。GPU可能很昂贵,而使用CPU可能是一种更具成本效益的选择,特别是如果您的业务用例不需要非常低的延迟。此外,如果您需要能够轻松扩展或减少推理工作者的数量,或者如果您需要能够在各种硬件上运行推理,使用CPU可能是更灵活的选择。
现在,让我们设置我们的测试服务器。
设置我们的测试服务器
与之前的帖子一样,我们将使用Amazon EC2实例:
- 基于Ice Lake架构的<c6i.16xlarge实例,
- 基于Sapphire Rapids架构的
r7iz.16xlarge-metal
实例。您可以在AWS网站上了解有关新的r7iz系列的更多信息。
两个实例都有32个物理核心(因此有64个vCPU)。我们将以相同的方式设置它们:
- Ubuntu 22.04和Linux 5.15.0(
ami-0574da719dca65348
), - PyTorch 1.13和Intel Extension for PyTorch 1.13,
- Transformers 4.25.1。
唯一的区别是在r7iz实例上添加了Optimum Intel库。
以下是设置步骤。通常,我们建议使用虚拟环境来保持整洁。
sudo apt-get update
# 添加libtcmalloc以提供额外的性能
sudo apt install libgoogle-perftools-dev -y
export LD_PRELOAD="/usr/lib/x86_64-linux-gnu/libtcmalloc.so"
sudo apt-get install python3-pip -y
pip install pip --upgrade
export PATH=/home/ubuntu/.local/bin:$PATH
pip install virtualenv
virtualenv inference_env
source inference_env/bin/activate
pip3 install torch==1.13.0 -f https://download.pytorch.org/whl/cpu
pip3 install intel_extension_for_pytorch==1.13.0 -f https://developer.intel.com/ipex-whl-stable-cpu
pip3 install transformers
# 仅在r7iz实例上需要
pip3 install optimum[intel]
完成这些步骤后,我们可以开始运行我们的测试。
基准测试流行的NLP模型
在这个例子中,我们将在文本分类任务上对几个NLP模型进行基准测试:distilbert-base-uncased、bert-base-uncased和roberta-base。您可以在Github上找到完整的脚本。随意尝试使用您的模型!
models = ["distilbert-base-uncased", "bert-base-uncased", "roberta-base"]
使用16个令牌和128个令牌的句子,我们将测量单独推理和批量推理的平均和p99预测延迟。这将为我们提供对实际场景中我们可以期望的加速比的相当好的视图。
sentence_short = "这是一双非常好的鞋子,我对我的购买非常满意"
sentence_short_array = [sentence_short] * 8
sentence_long = "这款阿迪达斯Lite Racer鞋子在舒适鞋子中达到了一个非常好的平衡点。尽管在脚趾盒子上有点紧,但佩戴起来非常舒适,并提供了很好的支撑。我不会说它们是好的跑步鞋或者训练鞋,因为它们在这类鞋子中简单地缺乏大多数人所期望的踝关节和足弓支撑,并且花纹磨损得相当快,但它们绝对是舒适的。事实上,我在这些鞋子上在迪士尼乐园转了一整天,没有任何问题,如果这是一个参考的话。总之,我将这些鞋子用作它们最好的用途;多用途、经济实惠、舒适,不要期望高端运动鞋的性能,也不要期望我最喜欢的拖鞋的舒适度。"
sentence_long_array = [sentence_long] * 8
基准测试函数非常简单。在几次预热迭代之后,我们使用管道API运行1,000次预测,存储预测时间,并计算它们的平均值和p99值。
import time
import numpy as np
def benchmark(pipeline, data, iterations=1000):
# 预热
for i in range(100):
result = pipeline(data)
times = []
for i in range(iterations):
tick = time.time()
result = pipeline(data)
tock = time.time()
times.append(tock - tick)
return "{:.2f}".format(np.mean(times) * 1000), "{:.2f}".format(
np.percentile(times, 99) * 1000
)
在c6i(Ice Lake)实例上,我们只使用了一个普通的Transformers管道。
from transformers import pipeline
for model in models:
print(f"对{model}进行基准测试")
pipe = pipeline("sentiment-analysis", model=model)
result = benchmark(pipe, sentence_short)
print(f"Transformers管道,短句子:{result}")
result = benchmark(pipe, sentence_long)
print(f"Transformers管道,长句子:{result}")
result = benchmark(pipe, sentence_short_array)
print(f"Transformers管道,短句子数组:{result}")
result = benchmark(pipe, sentence_long_array)
print(f"Transformers管道,长句子数组:{result}")
在r7iz(Sapphire Rapids)实例上,我们同时使用了一个普通管道和一个Optimum管道。在Optimum管道中,我们启用<bfloat16模式以利用AMX指令。我们还将jit
设置为True
,以使用即时编译进一步优化模型。
import torch
from optimum.intel import inference_mode
with inference_mode(pipe, dtype=torch.bfloat16, jit=True) as opt_pipe:
result = benchmark(opt_pipe, sentence_short)
print(f"Optimum管道,短句子:{result}")
result = benchmark(opt_pipe, sentence_long)
print(f"Optimum管道,长句子:{result}")
result = benchmark(opt_pipe, sentence_short_array)
print(f"Optimum管道,短句子数组:{result}")
result = benchmark(opt_pipe, sentence_long_array)
print(f"Optimum管道,长句子数组:{result}")
为了简洁起见,我们只看distilbert-base-uncased的p99结果。所有时间单位均为毫秒。您可以在帖子末尾找到完整的结果。
如上图所示,与上一代Xeon CPU相比,单次预测速度提升了60-65%。换句话说,由于英特尔Sapphire Rapids和Hugging Face Optimum的结合,您可以在不改变代码的情况下将预测加速3倍。
这使您能够实现单位数的预测延迟,即使对于长文本序列,这以前只有使用GPU才能实现。
结论
第四代英特尔Xeon CPU在与Hugging Face Optimum相结合时,能够提供出色的推理性能。这是使深度学习更易于使用和更具成本效益的又一步,我们期待与英特尔的合作伙伴继续开展这项工作。
以下是一些帮助您入门的其他资源:
- GitHub上的Intel IPEX
- GitHub上的Hugging Face Optimum
如果您有问题或反馈意见,我们很乐意在Hugging Face论坛上阅读。
感谢阅读!
附录:完整结果
Ubuntu 22.04 with libtcmalloc,Linux 5.15.0 patched for Intel AMX support,PyTorch 1.13 with Intel Extension for PyTorch,Transformers 4.25.1,Optimum 1.6.1,Optimum Intel 1.7.0.dev0