使用 Habana Gaudi2 加速视觉语言模型 BridgeTower

🤗 宝子们可以戳 阅读原文 查看文中所有的外部链接哟!

在对最先进的视觉语言模型 BridgeTower 进行微调时,使用 Optimum Habana v1.6, Habana Gaudi2 可以达到 近 3 倍于 A100 的速度。硬件加速的数据加载以及 fast DDP 这两个新特性对性能提高贡献最大。

这些技术适用于任何性能瓶颈在数据加载上的其他工作负载,很多视觉模型的性能瓶颈在数据加载。 本文将带你了解我们用于比较 Habana Gaudi2 和英伟达 A100 80GB 上的 BridgeTower 微调性能的流程及测试基准。通过我们的演示,你会发现在基于 transformers 的模型上使用 Gaudi2 以及这些新特性是多么容易!

BridgeTower

最近,视觉语言 (Vision-Language,VL) 模型 的重要性与日俱增,它们开始在各种 VL 任务中占据主导地位。在处理多模态数据时,最常见的做法是使用单模态编码器从各模态数据中提取各自的数据表征。然后,抑或是将这些表征融合在一起,抑或是将它们输入给跨模态编码器。为了有效解除传统 VL 表征学习的算法局限性及其性能限制,BridgeTower 引入了多个 桥接层 ,在单模态编码器的顶部若干层建立与跨模态编码器的逐层连接,这使得跨模态编码器中不同语义级别的视觉和文本表征之间能够实现有效的、自底而上的跨模态对齐和融合。

仅基于 400 万张图像预训练而得的 BridgeTower 模型就能在各种下游视觉语言任务上取得最先进的性能 (详见下文基准测试)。特别地,BridgeTower 在使用相同的预训练数据和几乎可以忽略不计的额外参数和计算成本的条件下,在 VQAv2 的 test-std 子集上取得了 78.73% 的准确率,比之前最先进的模型 (METER) 的准确率提高了 1.09%。值得一提的是,当进一步增加模型参数量,BridgeTower 的准确率可达 81.15%,超过了那些基于大得多的数据集预训练出来的模型。

硬件

英伟达 A100 张量核 GPU 内含第三代 张量核技术。尽管最近新一代 H100 已发布,但目前来讲 A100 仍然是大多数云服务上最快的 GPU。这里,我们使用显存为 80GB 的卡,它的显存容量和带宽都比 40GB 版本更高。

Habana Gaudi2 是 Habana Labs 设计的第二代 AI 硬件加速卡。一台服务器包含 8 个称为 HPU 的加速卡,每张加速卡有 96GB 内存。你可查阅 我们之前的博文,以了解 Gaudi2 的更多信息以及如何在 英特尔开发者云 (Intel Developer Cloud,IDC)  上获取 Gaudi2 实例。与市面上许多其他 AI 加速器不同,用户很容易通过 Optimum Habana 使用到 Gaudi2 的高级特性。有了 Optimum Habana,用户仅需更改 2 行 代码即可将基于 transformers 的模型脚本移植到 Gaudi 上。

基准测试

为了评测训练性能,我们准备微调 BridgeTower 的 large checkpoint,其参数量为 866M。该 checkpoint 在预训练时使用了掩码语言模型、图像文本匹配以及图像文本对比损失,其预训练数据集为 Conceptual Captions、SBU Captions、MSCOCO Captions 以及 Visual Genome。

我们将在 纽约客配文竞赛数据集 上进一步微调此 checkpoint,该数据集包含《纽约客》杂志上的漫画及每个漫画对应的投票最多的配文。

除了 batch size 之外,两种加速卡的其他微调超参数都是相同的: Gaudi2 单卡可放下 40 个样本,而 A100 只能放得下 32 个样本。你可以在 这儿 找到 Gaudi2 使用的训练超参,A100 使用的超参见 这儿。

在处理涉及图像的数据集时,数据加载通常是性能瓶颈之一,这是因为一般情况下很多预处理操作都是在 CPU 上完成的 (如图像解码、图像增强等),然后再将预处理后的图像发送至训练卡。这里带来一个优化点,理想情况下, 我们可以直接将原数据发送到设备,并在设备上执行解码和各种图像变换 。但在此之前,我们先看看能不能简单地通过分配更多 CPU 资源来加速数据加载。

利用 dataloader_num_workers

如果图像加载是在 CPU 上完成的,一个简单地加速方法就是分配更多的子进程来加载数据。使用 transformers 的 TrainingArguments (或 Optimum Habana 中相应的 GaudiTrainingArguments ) 可以很容易地做到这一点: 你可以用 dataloader_num_workers=N 参数来设置 CPU 上用于数据加载的子进程的数目 ( N )。

dataloader_num_workers 参数的默认值为 0,表示仅在主进程中加载数据。这个设置很多情况下并不是最佳的,因为主进程有很多事情需要做。我们可以将其设置为 1,这样就会有一个专有的子进程来加载数据。当分配多个子进程时,每个子进程将负责准备一个 batch。这意味着内存消耗将随着工作进程数的增加而增加。一个简单的方法是将其设置为 CPU 核数,但有时候有些核可能在做别的事情,因此需要尝试找到一个最佳配置。

下面,我们跑两组实验:

  • 8 卡分布式混合精度 ( bfloat16 / float ) 训练,其中数据加载由各 rank 的主进程执行 (即 dataloader_num_workers=0 )

  • 8 卡分布式混合精度 ( bfloat16 / float ) 训练,且每 rank 各有 1 个用于数据加载的专用子进程 (即 dataloader_num_workers=1 )

以下是这两组实验在 Gaudi2 和 A100 上分别测得的吞吐量: dataloader_num_workers=0``dataloader_num_workers=1

设备dataloader_num_workers=0dataloader_num_workers=1
Gaudi2 HPU532.4 samples/s639.7 samples/s
A100 GPU210.5 samples/s296.6 samples/s

首先,我们看到 dataloader_num_workers=1 时 Gaudi2 的速度是 A100 的 2.16 倍,在 dataloader_num_workers=0 时是 A100 的 2.53 倍,这与我们之前 报告的数据 相当!

其次,我们还看到 为数据加载分配更多资源可以轻松实现加速: Gaudi2 上加速比为 1.20,A100 上加速比为 1.41。

我们尝试了将数据加载子进程增加到数个,但实验表明其 在 Gaudi2 和 A100 上的性能均没有比 dataloader_num_workers=1 更好。因此, 使用 dataloader_num_workers=1 通常是加速涉及到图像的工作负载时首先尝试的方法!

你可以在 这儿 找到可视化的 Gaudi2 Tensorboard 日志,A100 的在 这儿。

Optimum Habana 的 fast DDP

在深入研究硬件加速的数据加载之前,我们来看一下另一个非常简单的 Gaudi 分布式运行的加速方法。新发布的 Optimum Habana 1.6.0 版引入了一个新功能,允许用户选择分布式策略:

  • distribution_strategy="ddp" 使用 PyTorch 的 DistributedDataParallel (DDP) 实现

  • distribution_strategy="fast_ddp" 使用 Gaudi 自有的更轻量级且一般来讲更快的实现

Optimum Habana 的 fast DDP 不会像 DDP 那样将参数梯度分割到存储桶 (bucket) 中。它还会使用 HPU 图 (graph)  来收集所有进程的梯度,并以最小的主机开销来对它们进行更新 (在 all_reduce 操作之后)。你可以在 这儿 找到其实现。

只需在 Gaudi2 上使用 distribution_strategy="fast_ddp" (并保持 dataloader_num_workers=1 ) 即可将每秒吞吐提高到 705.9, 比 DDP 快 1.10 倍,比 A100 快 2.38 倍!

因此,仅添加两个训练参数 ( dataloader_num_workers=1distribution_strategy="fast_ddp" ),我们即可在 Gaudi2 上实现 1.33 倍的加速,与使用 dataloader_num_workers=1 的 A100 相比,加速比达到 2.38 倍。

使用 Optimum Habana 实现硬件加速的数据加载

为了获得更多的加速,我们可以将尽可能多的数据加载操作从 CPU 上移到加速卡上 (即 Gaudi2 上的 HPU 或 A100 上的 GPU)。在 Gaudi2 上,我们可以使用 Habana 的 媒体流水线 (media pipeline)  来达到这一目的。

给定一个数据集,大多数的数据加载器会做如下操作:

  1. 获取数据 (例如,存储在磁盘上的 JPEG 文件)

  2. CPU 读取编码图像

  3. CPU 对图像进行解码

  4. CPU 对图像进行变换来增强图像

  5. 最后,将图像发送至设备 (尽管这通常不是由数据加载器本身完成的)

与在 CPU 上完成整个过程后再把准备好训练的数据发送到加速卡相比,更高效的工作流程是先将编码图像发送到加速卡,然后由加速卡执行图像解码和增强:

  1. 同上

  2. 同上

  3. 将编码图像发送至加速卡

  4. 加速卡对图像进行解码

  5. 加速卡对图像进行变换来增强图像

这样我们就可以利用加速卡强大的计算能力来加速图像解码和变换。请注意,执行此操作时需要注意两个问题:

  • 设备内存消耗将会增加,因此如果没有足够的可用内存,你需要减小 batch size。这可能会降低该方法带来的加速。

  • 如果在使用 CPU 数据加载方案时,加速卡的利用率已经很高 (100% 或接近 100%) 了,那就不要指望把这些操作卸载到加速卡会获得加速,因为它们已经忙得不可开交了。

我们还提供了一个示例,以帮助你在 Gaudi2 上实现这一优化: Optimum Habana 中的 对比图像文本示例 提供了一个可直接使用的媒体流水线 (media pipe),你可以将其直接用于类似于 COCO 那样的包含文本和图像的数据集!只需在命令中加一个 --mediapipe_dataloader 即可使能它。

感兴趣的读者可以参阅 Gaudi 的 文档,该文档对这一机制的底层实现给出了一些概述。读者还可以参考 这个文档,它给出了目前支持的所有算子的列表。

We are now going to benchmark a run with dataloader_num_workers=1 , distribution_strategy="fast_ddp" and mediapipe_dataloader since all these optimizations are compatible with each other:

现在我们测试一下 dataloader_num_workers=1distribution_strategy="fast_ddp"mediapipe_dataloader 在不同组合时的性能,所有这些优化都是相互兼容的: dataloader_num_workers=0``dataloader_num_workers=1``dataloader_num_workers=1 + distribution_strategy="fast_ddp"``dataloader_num_workers=1 + distribution_strategy="fast_ddp" + mediapipe_dataloader

设备dataloader_num_workers=0dataloader_num_workers=1dataloader_num_workers=1 + distribution_strategy="fast_ddp"dataloader_num_workers=1 + distribution_strategy="fast_ddp" + mediapipe_dataloader
Gaudi2 HPU532.4 samples/s639.7 samples/s705.9 samples/s802.1 samples/s
A100 GPU210.5 samples/s296.6 samples/s//

与之前基于 dataloader_num_workers=1distribution_strategy="fast_ddp" 的性能数据相比,我们又额外获得了 1.14 倍的加速。

因此,Gaudi2 上的最终结果比最开始快了 1.51 倍,而且 仅需增加 3 个简单的训练参数。 这个结果 也比使用 dataloader_num_workers=1 的 A100 快 2.70 倍!

如何复现我们的基准测试

要复现我们的基准测试,你首先需要能够访问 英特尔开发者云 (Intel Developer Cloud,IDC)  上的 Gaudi2 实例 (更多信息,请参阅 本指南)。

然后,你需要安装最新版本的 Optimum Habana 并运行 run_bridgetower.py ,您可以在 此处 找到这个脚本。具体操作命令如下:

pip install optimum[habana]
git clone https://github.com/huggingface/optimum-habana.git
cd optimum-habana/examples/contrastive-image-text
pip install -r requirements.txt

运行脚本时使用的基本命令行如下:

python ../gaudi_spawn.py --use_mpi --world_size 8 run_bridgetower.py \
--output_dir /tmp/bridgetower-test \
--model_name_or_path BridgeTower/bridgetower-large-itm-mlm-itc \
--dataset_name jmhessel/newyorker_caption_contest --dataset_config_name matching \
--image_column image --caption_column image_description \
--remove_unused_columns=False \
--do_train --do_eval --do_predict \
--per_device_train_batch_size="40" --per_device_eval_batch_size="16" \
--num_train_epochs 5 \
--learning_rate="1e-5" \
--push_to_hub --report_to tensorboard --hub_model_id bridgetower\
--overwrite_output_dir \
--use_habana --use_lazy_mode --use_hpu_graphs_for_inference --gaudi_config_name Habana/clip \
--throughput_warmup_steps 3 \
--logging_steps 10

上述命令行对应于 --dataloader_num_workers 0 。如果要运行其他配置,你可以视情况添加 --dataloader_num_workers 1--distribution_strategy fast_ddp--mediapipe_dataloader

如要将模型和 Tensorboard 日志推送到 Hugging Face Hub,你必须事先登录自己的帐户:

huggingface-cli login

在 A100 上运行的话,你可以使用相同的 run_bridgetower.py 脚本,但需要做一些小更改:

  • GaudiTrainerGaudiTrainingArguments 替换为 transformersTrainerTrainingArguments

  • 删除 GaudiConfiggaudi_configHabanaDataloaderTrainer 的相关代码

  • 直接从 transformers 导入 set_seed : from transformers import set_seed

本文中有关 A100 的数据是在一个含 8 张 GPU 的 Nvidia A100 80GB GCP 实例上测试而得。

请注意, --distribution_strategy fast_ddp--mediapipe_dataloader 仅适用于 Gaudi2,不适用于 A100。

总结

在处理图像时,我们提出了两个用于加速训练工作流的解决方案: 1) 分配更多的 CPU 资源给数据加载器,2) 直接在加速卡上而不是 CPU 上解码和变换图像。

我们证明,在训练像 BridgeTower 这样的 SOTA 视觉语言模型时,它会带来显著的加速: 基于 Optimum Habana 的 Habana Gaudi2 几乎比基于 Transformers 的英伟达 A100 80GB 快 3 倍!。而为了获得这些加速,你只需在训练脚本中额外加几个参数即可,相当容易!

后面,我们期待能使用 HPU 图进一步加速训练,我们还想向大家展示如何在 Gaudi2 上使用 DeepSpeed ZeRO-3 来加速 LLM 的训练。敬请关注!

如果你对使用最新的 AI 硬件加速卡和软件库加速机器学习训练和推理工作流感兴趣,可以移步我们的 专家加速计划。如果你想了解有关 Habana 解决方案的更多信息,可以在 此处 了解我们相关信息并联系他们。要详细了解 Hugging Face 为让 AI 硬件加速卡更易于使用而做的努力,请查阅我们的 硬件合作伙伴计划。

相关话题

  • 更快的训练和推理: 对比 Habana Gaudi2 和英伟达 A100 80GB

  • 大语言模型快速推理: 在 Habana Gaudi2 上推理 BLOOMZ


英文原文: https://hf.co/blog/bridgetower

原文作者: Régis Pierrard,Anahita Bhiwandiwalla

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

审校/排版: zhongdongy (阿东)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/23752.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

luajit 使用 clang编译的坑

为了尝试将LuaJIT接入虚幻Lua插件之中,需要预编译LuaJIT链接库,在桌面平台问题不大, 主要是移动平台,涉及跨平台编译,因为对跨平台编译具体细节没有系统研究,这里先记录一下跨平台编译LuaJIT的主要过程 由于官方提供的…

Pandas操作Excel

Pandas 是 Python 语言的一个扩展程序库,用于数据分析。 菜鸟教程:https://www.runoob.com/pandas/pandas-tutorial.html 读取Excel pd.read_excel(path,sheet_name,header) path:excel文件路径sheet_name:读取的sheet&#xff0…

3.netty和protobuf

1.ChannelGroup可以免遍历由netty提供,覆盖remove方法即可触发删除channel\ 2.群聊私聊 13.群聊私聊简单原理图 3.netty心跳检测机制,客户端对服务器有没有读写(读,写空闲) //IdleStateHandler(3,5,7,TimeUnite.SECONDS)是netty提供的检测状态的处理器,也加到pipeline,读,写,…

【新版系统架构补充】-嵌入式软件

嵌入式软件 嵌入式软件是指应用在嵌入式计算机系统当中的各种软件,除了具有通用软件的一般特性,还具有一些与嵌入式系统相关的特点,包括:规模较小、开发难度大、实时性和可靠性要求高、要求固化存储。 嵌入式软件分类&#xff1…

react Ref 的基本使用

类组件中使用ref 在类组件中,你可以使用createRef来创建一个ref,并将它附加到DOM元素或类组件实例上。使用ref允许你在类组件中访问和操作特定的DOM元素或类组件实例。 下面是在类组件中使用ref的步骤: 引入React和createRef: …

浅析 C 语言的共用体、枚举和位域

前言 最近在尝试阅读一些系统库的源码,但是其中存在很多让我感到既熟悉又陌生的语法。经过资料查阅,发现是 C 语言中的共用体和位域。于是,趁着课本还没有扔掉,将一些相关的知识点记录在本文。 文章目录 前言共用体 (union)枚举…

Tomcat 的内存配置

修改 Tomcat 的内存配置,你需要调整 Tomcat 的 Java 虚拟机(JVM)参数。具体来说,你需要修改 catalina.sh(Linux/macOS)或 catalina.bat(Windows)脚本中的 JAVA_OPTS 变量。以下是一般…

【LeetCode 算法】Merge Two Sorted Lists 合并两个有序链表

文章目录 Merge Two Sorted Lists 合并两个有序链表问题描述:分析代码迭代递归 Tag Merge Two Sorted Lists 合并两个有序链表 问题描述: 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 两个链表的…

GNN code Tips

1. 重置label取值范围 problem: otherwise occurs IndexError: target out of bounds # reset labels value range, otherwise occurs IndexError: target out of bounds uni_set torch.unique(labels) to_set torch.tensor(list(range(len(uni_set)))) labels_reset label…

网络开发-IO模型

基本概念 I/O即数据的读取&#xff08;接收&#xff09;或写入&#xff08;发送&#xff09;操作 通常用户进程中的一个完整I/O分为两个阶段 用户进程空间<-->内核空间内核空间<-->设备空间&#xff08;磁盘、网卡等&#xff09; I/O分为内存I/O、网络I/O和磁盘…

【编程】典型题目:寻找数组第K大数(四种方法对比)

【编程】典型题目&#xff1a;寻找数组第K大数&#xff08;四种方法对比&#xff09; 文章目录 【编程】典型题目&#xff1a;寻找数组第K大数&#xff08;四种方法对比&#xff09;1. 题目2. 题解2.1 方法一&#xff1a;全局排序&#xff08;粗暴&#xff09;2.2 方法二&#…

2023年第二届网络安全国际会议(CSW 2023)

会议简介 Brief Introduction 2023年第二届网络安全国际会议(CSW 2023) 会议时间&#xff1a;2023年10月13日-15日 召开地点&#xff1a;中国杭州 大会官网&#xff1a;www.cybersecurityworkshop.org 2023年第二届网络安全国际会议(CSW 2023)由杭州电子科技大学&#xff0c;国…

123.买卖股票的最佳时机3

目录 一、题目 二、分析代码 一、题目 123. 买卖股票的最佳时机 III - 力扣&#xff08;LeetCode&#xff09; 二、分析代码 class Solution { public:int maxProfit(vector<int>& prices) {//0表示没有操作//1表示第1次买入&#xff0c;2表示第1次卖出//3表示第2…

用html+javascript打造公文一键排版系统11:改进单一附件说明排版

一、用htmljavascript打造公文一键排版系统10中的一个bug 在 用htmljavascript打造公文一键排版系统10&#xff1a;单一附件说明排版 中&#xff0c;我们对附件说明的排版函数是&#xff1a; function setAtttDescFmt(p) {var t p;var a ;if (-1 ! t.indexOf(:))//是半角冒…

学习源码,模仿编程

一.观察者模式: 1.创建事件 2.发布事件 3.监听事件 4.效果: 二.模板方法模式

FTP使用教程

FTP使用教程 目录 一&#xff0e;FTP简介二&#xff0e;FTP搭建三&#xff0e;FTP使用 一&#xff0e;FTP简介 FTP中文为文件传输协议&#xff0c;简称为文传协议。它也是一个应用程序&#xff0c;不同的操作系统有不同的FTP应用程序&#xff0c;这些应用程序都遵守同一种协议以…

Python 程序设计入门(007)—— 列表的操作(2):列表元素的排序及统计操作

Python 程序设计入门&#xff08;007&#xff09;—— 列表的操作&#xff08;2&#xff09;&#xff1a;列表元素的排序及统计操作 目录 Python 程序设计入门&#xff08;007&#xff09;—— 列表的操作&#xff08;2&#xff09;&#xff1a;列表元素的排序及统计操作一、列…

LeetCode724. 寻找数组的中心下标

题干 给你一个整数数组 nums &#xff0c;请计算数组的 中心下标 。 数组 中心下标 是数组的一个下标&#xff0c;其左侧所有元素相加的和等于右侧所有元素相加的和。 如果中心下标位于数组最左端&#xff0c;那么左侧数之和视为 0 &#xff0c;因为在下标的左侧不存在元素。…

k8s概念-pv和pvc

回到目录 kubernetes存储卷的分类太丰富了,每种类型都要写相应的接口与参数才行&#xff0c;这就让维护与管理难度加大。 persistenvolume(PV) 是配置好的一段存储(可以是任意类型的存储卷) 也就是说将网络存储共享出来,配置定义成PV。 PersistentVolumeClaim(PVC)是用户pod使…

Python黑魔法揭秘:装饰器、生成器、异步编程、GIL、描述符和元类

Python中的某些特性被看作是“黑魔法”&#xff0c;原因在于它们的强大功能和复杂性。接下来&#xff0c;让我们深入探索这些特性。 装饰器 装饰器是修改函数或类行为的强大工具&#xff0c;它提供了一种可读性强、代码重用的方式来增强或修改函数或类的行为。装饰器就像一个…