关于人工智能:使用英特尔-Sapphire-Rapids-加速-PyTorch-Transformers-模型

48次阅读

共计 6660 个字符,预计需要花费 17 分钟才能阅读完成。

大概一年以前,咱们 展现 [1] 了如何在第三代 英特尔至强可扩大 [2] CPU (即 Ice Lake) 集群上分布式训练 Hugging Face transformers 模型。最近,英特尔公布了代号为 Sapphire Rapids 的第四代至强可扩大 CPU,该 CPU 蕴含了令人兴奋的深度学习减速新指令。

通过本文,你将会学到如何在一个 AWS Sapphire Rapids 集群上减速一个 PyTorch 训练任务。咱们会应用 英特尔 oneAPI 汇合通信库 [3] (oneAPI Collective Communications Library, oneCCL) 来分布式化训练任务,并应用 英特尔 PyTorch 扩大库 [4] (Intel Extension for PyTorch,IPEX) 来主动应用新指令进行性能优化。因为这两个库均已集成入 Hugging Face transformers 库,咱们可能做到在不批改一行代码的前提下开箱即用地运行咱们的示例代码。

在随后的另一篇文章里,咱们还会探讨如何应用 Sapphire Rapids CPU 进行推理及其性能晋升。

为何你应该思考在 CPU 上训练

在英特尔至强 CPU 上训练一个深度学习模型是一个性价比高且可扩大的计划,在应用分布式训练或者在小数据集或中等数据集上微调模型时尤其如此。

至强 CPU 反对一些先进的个性,如 512 位先进矢量扩大 (Advanced Vector Extensions,AVX-512) 以及超线程 (Hyper-Threading),这些个性进步了深度学习模型的并行性和效率,使得咱们能够在失去更好的硬件资源使用率的同时训练得更快。

另外,一般而言,相比用于训练大型深度学习模型的专门硬件如 GPU 等而言,至强 CPU 更便宜和易得。至强 CPU 还更容易用于其余生产工作,从网络服务到数据库不一而足,这使得它们成为 IT 基础设施的一个万用且灵便的抉择。

最初,云用户还能够通过应用 spot 实例的形式进一步升高在至强 CPU 上的训练老本。Spot 实例应用闲暇计算资源,因而以折扣价售卖。与按需实例相比,spot 实例提供了高至 90% 的显著的老本节约。最初同样重要的是,CPU spot 实例一般来讲比 GPU 实例更容易取得。

当初,让咱们看一下 Sapphire Rapids 架构引入的新指令。

先进矩阵扩大 (AMX):深度学习新指令

Sapphire Rapids 架构引入了英特尔先进矩阵扩大 (Advanced Matrix Extensions, AMX) 用于减速深度学习工作负载。用户只需装置最新版本的 IPEX 即可受害于新指令,无需更改任何 Hugging Face 代码。

AMX 指令用于减速矩阵乘法,该操作是深度学习批量训练的外围操作。AMX 指令反对 Brain 浮点 (BF16) 和 8 比特整型 (INT8) 数据类型,笼罩不同训练场景的减速需要。

AMX 指令引入了新的 2 维 CPU 寄存器,称作 tile 寄存器。因为这些寄存器在上下文切换时须要保留和复原,所以须要内核相干反对。在 Linux 上,内核版本须要在 v5.16 及以上方可反对。

当初,让咱们看看怎么构建一个 Sapphire Rapids CPU 集群用于分布式训练。

构建一个 Sapphire Rapids CPU 集群

截至本文撰写之时,应用 Sapphire Rapids 服务器的最简略的形式是应用新的亚马逊 EC2 R7iz[5] 实例家族。因为它尚在预览期,你必须 登记注册 [6] 以取得拜访权限。另外,虚拟机尚未反对 AMX,因而,咱们将应用裸金属实例 (r7iz.metal-16xl, 64 vCPU, 512GB RAM)。

为防止手动设置集群中的每个节点,咱们首先建设一个主节点并依此创立一个新的亚马逊机器镜像 (Amazon Machine Image,AMI[7]),而后,咱们用这个 AMI 启动其余节点。

从网络的角度,咱们须要如下设置:

  • 关上 22 端口,用于所有实例上的 ssh 拜访创立和调试
  • 配置从主实例 (你启动训练的那个实例) 到所有其余实例 (蕴含主实例自身) 的免密 SSH 拜访。换句话说,主节点的 ssh 公钥必须在所有阶段上被受权
  • 容许集群内的所有网络通信,使得分布式训练能够不受妨碍地运行。AWS 提供了平安组这一平安便捷的形式反对这个性能。咱们只需创立一个平安组,确保所有集群内的实例属于同一平安组,并容许同一平安组内的所有网络通信即可,以下是我应用的设置:

让咱们开始创立集群的主节点。

设置主节点

咱们首先启动一个装置了 Ubuntu 20.04 AMI (ami-07cd3e6c4915b2d18) 并退出了咱们之前创立的平安组的 r7iz.metal-16xl 实例,用于创立主节点。该 AMI 尽管只蕴含了 Linux v5.15.0,然而侥幸的是英特尔和 AWS 曾经为这个内核版本打上了 AMX 反对的补丁。因而,咱们不须要降级内核至 v5.16。

一旦实例运行起来后,咱们 ssh 登录上它并通过 lscpu 命令查看 AMX 是否的确已被反对。你应该会在 flags 局部看到如下内容:

amx_bf16 amx_tile amx_int8

而后,咱们开始装置本地依赖以及 Python 依赖。

sudo apt-get update 

# Install tcmalloc for extra performance (https://github.com/google/tcmalloc)
sudo apt install libgoogle-perftools-dev -y

# Create a virtual environment
sudo apt-get install python3-pip -y
pip install pip --upgrade
export PATH=/home/ubuntu/.local/bin:$PATH
pip install virtualenv

# Activate the virtual environment
virtualenv cluster_env
source cluster_env/bin/activate

# Install PyTorch, IPEX, CCL and Transformers
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 oneccl_bind_pt==1.13 -f https://developer.intel.com/ipex-whl-stable-cpu
pip3 install transformers==4.24.0

# Clone the transformers repository for its example scripts
git clone https://github.com/huggingface/transformers.git
cd transformers
git checkout v4.24.0

接着,咱们应用 ssh-keygen 创立一个新的 ssh 密钥对,命名为 cluster,并保留在缺省地位 (~/.ssh)。

最初,咱们用该实例创立一个新的 AMI。

设置集群

一旦 AMI 准备就绪,咱们用它启动另外 3 个 r7iz.16xlarge-metal 实例,不要忘了把他们退出之前创立的平安组中。

当这些实例启动的时候,咱们 ssh 登录进主节点并实现网络设置。首先,咱们编辑位于 ~/.ssh/config 的 ssh 配置文件,使其反对从主节点到其余节点的免密连贯,这里咱们只需应用它们各自的公有 IP 及之前创立的密钥对即可。以下是我的配置文件。

Host 172.31.*.*
   StrictHostKeyChecking no

Host node1
    HostName 172.31.10.251
    User ubuntu
    IdentityFile ~/.ssh/cluster

Host node2
    HostName 172.31.10.189
    User ubuntu
    IdentityFile ~/.ssh/cluster

Host node3
    HostName 172.31.6.15
    User ubuntu
    IdentityFile ~/.ssh/cluster

到此为止,咱们能够应用 ssh node [1-3] 去免密连贯任何节点。

在主节点侧,咱们创立一个 ~/hosts 文件,并填入集群中所有节点的名称,这些名称已在下面的 ssh 配置文件中定义。咱们用 localhost 代表主节点,因为咱们会在该节点启动训练脚本。我的文件如下所示。

localhost
node1
node2
node3

集群现已准备就绪,让咱们开始训练吧!

启动一个分布式训练任务

在本例中,咱们将在 SQUAD[8] 数据集上微调一个用于问答的 DistilBERT[9] 模型。如果你想试试别的示例的话,只管去做吧。

source ~/cluster_env/bin/activate
cd ~/transformers/examples/pytorch/question-answering
pip3 install -r requirements.txt

咱们首先冒个烟,启动一个单实例训练任务。请留神如下几个重要的标记变量:

  • no_cuda 确保应用 CPU 进行训练,疏忽 GPU
  • use_ipex 使能 IPEX 库,确保 AMX 和 AVX 指令的应用
  • bf16 使能 BF16 训练
export LD_PRELOAD="/usr/lib/x86_64-linux-gnu/libtcmalloc.so"
python run_qa.py --model_name_or_path distilbert-base-uncased \
--dataset_name squad --do_train --do_eval --per_device_train_batch_size 32 \
--num_train_epochs 1  --output_dir /tmp/debug_squad/ \
--use_ipex --bf16 --no_cuda

不用等到工作实现,咱们只运行 1 分钟用于确保所有的依赖已被失常装置。同时,这也给了咱们一个单实例训练的基线性能:1 个 epoch 破费大概 26 分钟 。供参考,咱们测量了同样的工作在一个相当的 Ice Lake 实例 (c6i.16xlarge) 上的性能,基于雷同的软件设置,每个 epoch 须要 3 小时 30 分钟 。减速比达到 8 倍 。咱们曾经能看到新指令带来的益处!

当初,让咱们把训练任务分布式部署到 4 个实例上。一个 r7iz.16xlarge 实例有 32 个物理 CPU 核,咱们偏向于间接应用物理核而不是虚构核 (vCPUs) (KMP_HW_SUBSET=1T)。咱们决定调配 24 个核用于训练 (OMP_NUM_THREADS),2 个核用于汇合通信 (CCL_WORKER_COUNT),剩下的 6 个核给内核和其余过程应用。这 24 个训练线程调配给 2 个 Python 过程应用 (NUM_PROCESSES_PER_NODE)。因而,一个 4 节点的集群上共有 8 (NUM_PROCESSES) 个 Python 过程。

# Set up environment variables for CCL
oneccl_bindings_for_pytorch_path=$(python -c "from oneccl_bindings_for_pytorch import cwd; print(cwd)")
source $oneccl_bindings_for_pytorch_path/env/setvars.sh

export MASTER_ADDR=172.31.3.190
export NUM_PROCESSES=8
export NUM_PROCESSES_PER_NODE=2
export CCL_WORKER_COUNT=2
export CCL_WORKER_AFFINITY=auto
export KMP_HW_SUBSET=1T

当初,咱们启动分布式训练任务。

# Launch distributed training
mpirun -f ~/hosts \
 -n $NUM_PROCESSES -ppn $NUM_PROCESSES_PER_NODE  \
 -genv OMP_NUM_THREADS=24 \
 -genv LD_PRELOAD="/usr/lib/x86_64-linux-gnu/libtcmalloc.so" \
 python3 run_qa.py \
 --model_name_or_path distilbert-base-uncaased \
 --dataset_name squad \
 --do_train \
 --do_eval \
 --per_device_train_batch_size 32  \
 --num_train_epochs 1  \
 --output_dir /tmp/debug_squad/ \
 --overwrite_output_dir \
 --no_cuda \
 --xpu_backend ccl \
 --bf16

当初,一个 epoch 仅需 7 分 30 秒

工作如下图所示。图的上半局部是主节点,同时你也能够看到其余 3 个节点每个均有 2 个训练过程在运行。

4 节点的完满线性扩大须要 6 分 30 秒的训练工夫 (26 分钟除以 4)。咱们十分靠近于这个现实值,这充沛展示了该办法很高的扩展性。

论断

如你所见,在一个英特尔至强集群上训练 Hugging Face transformers 模型是一个灵便,可扩大且性价比高的解决方案,特地是在你的数据集和模型是小尺寸或者中等尺寸状况下。

以下列出了一些其余可帮忙你起步的资源:

  • Intel IPEX[10] GitHub 代码仓库
  • Hugging Face 文档: Efficient training on CPU[11] 及 Efficient training on many CPUs[12]

如你有任何问题或反馈,请通过留言形式通知咱们。

感激浏览!


英文原文: https://huggingface.co/blog/intel-sapphire-rapids

译者: Matrix Yao (姚伟峰),英特尔深度学习工程师,工作方向为 transformer-family 模型在各模态数据上的利用及大规模模型的训练推理。

头图: 茶叶蛋蛋


文内链接

[1] Hugging Face 博客文章: 应用英特尔技术减速 PyTorch 分布式微调: https://huggingface.co/blog/a…

[2] 英特尔® 至强® 可扩大处理器: https://www.intel.cn/content/…

[3] 英特尔 oneAPI 汇合通信库: https://www.intel.cn/content/…

[4] 英特尔 PyTorch 扩大库: https://github.com/intel/inte…

[5] Amazon EC2 R7iz 实例: https://aws.amazon.com/cn/ec2…\_ls

[6] 登记注册 Amazon EC2 R7iz 实例 (预览版): https://pages.awscloud.com/R7…

[7] 理解亚马逊机器镜像 (AMI): https://docs.aws.amazon.com/A…

[8] Hugging Face 平台上的数据集页面: SQUAD: https://huggingface.co/datase…

[9] Hugging Face 平台上的模型页面: DistilBERT: https://huggingface.co/distil…

[10] Intel® Extension for PyTorch 的 GitHub 页面: https://github.com/intel/inte…

[11] Hugging Face 文档页面: CPU 高效训练: https://huggingface.co/docs/t…\_train\_cpu

[12] Hugging Face 文档页面: 多 CPU 上的高效训练: https://huggingface.co/docs/t…\_train\_cpu\_many

正文完
 0