大约一年以前,我们 展示 了如何在第三代 英特尔至强可扩展 CPU (即 Ice Lake) 集群上分布式训练 Hugging Face transformers 模型。最近,英特尔发布了代号为 Sapphire Rapids 的第四代至强可扩展 CPU,该 CPU 包含了令人兴奋的深度学习加速新指令。

通过本文,你将会学到如何在一个 AWS Sapphire Rapids 集群上加速一个 PyTorch 训练任务。我们会使用 英特尔 oneAPI 集合通信库 (oneAPI Collective Communications Library, oneCCL) 来分布式化训练任务,并使用 英特尔 PyTorch 扩展库 (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 实例家族。由于它尚在预览期,你必须 登记注册 以获得访问权限。另外,虚拟机尚未支持 AMX,因此,我们将使用裸金属实例 (r7iz.metal-16xl, 64 vCPU, 512GB RAM) 。

为避免手动设置集群中的每个节点,我们首先建立一个主节点并依此创建一个新的亚马逊机器镜像 (Amazon Machine Image,AMI) ,然后,我们用这个 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 数据集上微调一个用于问答的 DistilBERT 模型。如果你想试试别的示例的话,尽管去做吧。

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-uncased \
--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 模型是一个灵活,可扩展且性价比高的解决方案,特别是在你的数据集和模型是小尺寸或者中等尺寸情况下。

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

如你有任何问题或反馈,请通过留言方式告诉我们。

感谢阅读!


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

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

头图: 茶叶蛋蛋


使用英特尔 Sapphire Rapids 加速 PyTorch Transformers 模型的更多相关文章

  1. 英特尔与 Facebook 合作采用第三代英特尔® 至强® 可扩展处理器和支持 BFloat16 加速的英特尔® 深度学习加速技术,提高 PyTorch 性能

    英特尔与 Facebook 曾联手合作,在多卡训练工作负载中验证了 BFloat16 (BF16) 的优势:在不修改训练超参数的情况下,BFloat16 与单精度 32 位浮点数 (FP32) 得到了 ...

  2. 英特尔® 至强® 平台集成 AI 加速构建数据中心智慧网络

    英特尔 至强 平台集成 AI 加速构建数据中心智慧网络 SNA 通过 AI 方法来实时感知网络状态,基于网络数据分析来实现自动化部署和风险预测,从而让企业网络能更智能.更高效地为最终用户业务提供支撑. ...

  3. 面向英特尔® x86 平台的 Unity* 优化指南: 第 1 部分

    原文地址 目录 工具 Unity 分析器 GPA 系统分析器 GPA 帧分析器 如要充分发挥 x86 平台的作用,您可以在项目中进行多种性能优化,以最大限度地提升性能. 在本指南中,我们将展示 Uni ...

  4. 英特尔® 硬件加速执行管理器安装指南 — Microsoft Windows*

    介绍 本文将指导您安装英特尔® 硬件加速执行管理器(英特尔® HAXM),这是一款可以使用英特尔® 虚拟化技术(VT)加快 Android* 开发速度的硬件辅助虚拟化引擎(管理程序). 前提条件 英特 ...

  5. 什么是英特尔® Edison 模块?

    英特尔® Edison 模块 是一种 SD 卡大小的微型计算芯片,专为构建物联网 (IoT) 和可穿戴计算产品而设计. Edison 模块内含一个高速的双核处理单元.集成 Wi-Fi*.蓝牙* 低能耗 ...

  6. 基于英特尔® 至强™ 处理器 E5 产品家族的多节点分布式内存系统上的 Caffe* 培训

    原文链接 深度神经网络 (DNN) 培训属于计算密集型项目,需要在现代计算平台上花费数日或数周的时间方可完成. 在最近的一篇文章<基于英特尔® 至强™ E5 产品家族的单节点 Caffe 评分和 ...

  7. 基于英特尔® 至强 E5 系列处理器的单节点 Caffe 评分和训练

    原文链接 在互联网搜索引擎和医疗成像等诸多领域,深度神经网络 (DNN) 应用的重要性正在不断提升. Pradeep Dubey 在其博文中概述了英特尔® 架构机器学习愿景. 英特尔正在实现 Prad ...

  8. 英特尔15天开发IDF硬享公社App全过程

    4月8日英特尔智能硬件大赛在上海决赛,4月13日英热尔智能硬件大赛10强在深圳首秀.英特尔辗转两大城市来顾全两地智能硬件创业者,移动直播就成了用户们最重要的观看渠道. 这次英特尔两大会事现场直播都在官 ...

  9. 跨代的对决 英特尔i7-6700HQ对比i7-4720HQ性能测试

    http://itianti.sinaapp.com/index.php/cpu 跨代的对决 英特尔i7-6700HQ对比i7-4720HQ性能测试 2015-10-13 19:46:31 来源:电脑 ...

  10. Intel 英特尔

    英特尔 英特尔 基本资料   公司名称:英特尔(集成电路公司)    外文名称:Intel Corporation(Integrated Electronics Corporation)    总部地 ...

随机推荐

  1. 齐博x1再来个抛砖引玉 内容页根据关键词调用相关内容 新功能哦!

    昨天升级了一个隐藏的功能,今天就简单的做个说明怎么用,反正也不能浪费不是 那就用内容页面关键词读取相关内容为例吧. 前台是你模型中已经存在keywords字段  关键词支持 空格分割,号分割 那么就开 ...

  2. 初识vue3.0

    vue3.0 源码组织方式的变化 采用ts重写 独立的功能模块提取到单独的包中 90%的api兼容Vue2.x Composition API 组合api 解决vue2.x options api 开 ...

  3. 万字详解JVM,让你一文吃透

    摘要:本文将带大家详细地了解关于JVM的一些知识点. 本文分享自华为云社区<[JVM]关于JVM,你需要掌握这些 | 一文彻底吃透JVM系列>,作者: 冰 河 . JDK 是什么? JDK ...

  4. LabVIEW+OpenVINO在CPU上部署新冠肺炎检测模型实战

    前言 之前博客:[YOLOv5]LabVIEW+OpenVINO让你的YOLOv5在CPU上飞起来给大家介绍了在LabVIEW上使用openvino加速推理,在CPU上也能感受丝滑的实时物体识别.那我 ...

  5. jmeter执行报错:java.lang.UnsupportedClassVersionError解决办法

    做个记录. 问题记录: jmeter版本:5.4.1 本地Java版本:1.8.0_151 执行jmeter,报错: 2022-10-14 12:06:27,372 ERROR o.a.j.JMete ...

  6. 1.docker的基本使用

    1.简介 Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows操作系统的机器上,也可以实现虚拟化.容器是完 ...

  7. Https Webservice接口的免证书调用

    目录 前言 思路 方案 Axis调用 HttpClient调用 参考链接 前言 在调用https协议的Webservice接口时,如果没有做证书验证,一般会报javax.net.ssl.SSLHand ...

  8. 嵌入式-C语言基础:指针

    指针就是地址,变量的值可以通过两种方式访问,一个是通过变量名,一个是通过地址访问. 从而引出一个问题,即什么是指针变量?整型(字符)变量就是存放整形(字符)的变量,指针变量就是存放指针的变量,也就是存 ...

  9. 禁用显卡自动更新(解决官办驱动和OEM驱动相冲)

    起因 有一天打开MC(我的世界)时候突然显示显卡不支持,想了想可能是自己捣鼓电脑的时候弄坏了,提示说版本不支持,一看自己的驱动还是上古版本,但是之前都是可以正常玩的,想着更新下驱动就行了呗,更新完&q ...

  10. laravel框架 url地址传参

    //前端页面 <a title="编辑" onclick="xadmin.open('编辑','{{url("admin/Manager/edit&quo ...