使用 PyTorch FSDP 微调 Llama 2 70B

通过本文,你将了解如何使用 PyTorch FSDP 及相关最佳实践微调 Llama 2 70B。在此过程中,我们主要会用到 Hugging Face Transformers、Accelerate 和 TRL 库。我们还将展示如何在 SLURM 中使用 Accelerate。

完全分片数据并行 (Fully Sharded Data Parallelism,FSDP) 是一种训练范式,在该范式中优化器状态、梯度和模型参数都会被跨设备分片。前向传播时,每个 FSDP 单元执行 all gather 以获取完整的权重,然后用它们进行计算并在计算后丢弃掉其他设备的分片。随后是反向传播,然后就是损失计算。反向传播时,每个 FSDP 单元执行 all gather 操作以获取完整的权重,并执行计算以获得本地 batch 的梯度。这些梯度通过 reduce scatter 在设备上进行均值计算并分片,这样每个设备都可以更新其对应分片的参数。

有关 PyTorch FSDP 的更多信息,请参阅此博文: 使用 PyTorch 完全分片数据并行技术加速大模型训练

技术交流

建了技术交流群!想要进交流群、获取如下原版资料的同学,可以直接加微信号:dkl88194。加的时候备注一下:研究方向 +学校/公司+CSDN,即可。然后就可以拉你进群了。

方式①、添加微信号:dkl88194,备注:来自CSDN + 技术交流
方式②、微信搜索公众号:Python学习与数据挖掘,后台回复:加群

资料1
在这里插入图片描述

资料2
在这里插入图片描述

图片

FSDP 工作流

使用的硬件

节点数: 2,至少 1 个节点
每节点 GPU 数: 8
GPU 类型: A100
GPU 显存: 80GB
节点内互联: NVLink
每节点内存: 1TB
每节点 CPU 核数: 96
节点间互联: AWS 的 Elastic Fabric Adapter (EFA)

微调 LLaMa 2 70B 面临的挑战

在尝试使用 FSDP 微调 LLaMa 2 70B 时,我们主要遇到了三个挑战:

  1. FSDP 会先加载整个预训练模型,然后再对模型进行分片。这样就意味着节点内的每个进程 (即 rank) 都会加载整个 Llama-70B 模型,因此需要 70_4_8 GB ~ 2TB 的 CPU 内存,这个算式中 4 是每个参数所需字节数,8 是每个节点的 GPU 数。这会导致 CPU 内存不足,进而导致进程终止。

  2. 使用 FULL_STATE_DICT 来保存完整中间检查点并将其卸载至 rank 0 的 CPU 内存中需要花费大量时间,且由于在此期间通信库需要无限期挂起等待保存完成,因此经常会导致 NCCL 超时错误。然而,完全关掉这个选项也不好,因为在训练结束时我们需要保存完整的模型状态字典,而不是 FSDP 式分片的状态字典。

  3. 我们需要提高速度并减少显存使用,以加快训练并节约计算成本。

下文,我们主要讨论如何一一解决上述挑战,最终微调出一个 70B 的模型!

先列出重现结果所需的所有资源:

  1. 代码库: https://github.com/pacman100/DHS-LLM-Workshop/tree/main/chat_assistant/training,代码中包含了使能 flash 注意力 V2 的热补丁

  2. FSDP 配置文件: https://github.com/pacman100/DHS-LLM-Workshop/blob/main/chat_assistant/training/configs/fsdp_config.yaml

  3. SLURM 启动脚本 - launch.slurm: https://gist.github.com/pacman100/1cb1f17b2f1b3139a63b764263e70b25

  4. 模型: meta-llama/Llama-2-70b-chat-hf

  5. 数据集: smangrul/code-chat-assistant-v1 (混合了 LIMA 和 GUANACO 数据集,且已转换为训练所需的格式)

准备工作

首先按照 此步骤 安装 Flash Attention V2。然后,安装最新的 PyTorch nightly (CUDA ≥11.8)。接着,根据 此文件 安装其余依赖软件。在本文中,我们是从主分支安装 🤗 Accelerate 和 🤗 Transformers 的。

微调

应对挑战 1

PR 25107 和 PR 1777 解决了第一个挑战,且无需用户侧更改任何代码。主要做的事情如下:

  1. 在所有 rank 上创建无权重的空模型 (使用 meta 设备)

  2. 仅在 rank 0 上将状态字典加载至模型

  3. 其他 rank 仅对 meta 设备上的参数执行 torch.empty(*param.size(), dtype=dtype)

  4. 因此,只有 rank 0 上加载了完整的模型及权重,而所有其他 rank 上的权重是空的

  5. 设置 sync_module_states=True ,以便 FSDP 实例在训练开始之前将权重广播到各 rank

下面是在 2 个 GPU 上加载 7B 模型的输出日志片段,它测量了各个阶段内存的消耗及其加载的模型参数量。我们可以观察到,在加载预训练模型时,rank 0 和 rank 1 的 CPU 峰值内存分别为 32744 MB1506 MB 。因此可知,仅有 rank 0 加载了预训练模型,这就实现了 CPU 内存的有效利用。你可在 此处 找到完整日志。

accelerator.process_index=0 GPU Memory before entering the loading : 0
accelerator.process_index=0 GPU Memory consumed at the end of the loading (end-begin): 0
accelerator.process_index=0 GPU Peak Memory consumed during the loading (max-begin): 0
accelerator.process_index=0 GPU Total Peak Memory consumed during the loading (max): 0
accelerator.process_index=0 CPU Memory before entering the loading : 926
accelerator.process_index=0 CPU Memory consumed at the end of the loading (end-begin): 26415
accelerator.process_index=0 CPU Peak Memory consumed during the loading (max-begin): 31818
accelerator.process_index=0 CPU Total Peak Memory consumed during the loading (max): 32744

accelerator.process_index=1 GPU Memory before entering the loading : 0
accelerator.process_index=1 GPU Memory consumed at the end of the loading (end-begin): 0
accelerator.process_index=1 GPU Peak Memory consumed during the loading (max-begin): 0
accelerator.process_index=1 GPU Total Peak Memory consumed during the loading (max): 0
accelerator.process_index=1 CPU Memory before entering the loading : 933
accelerator.process_index=1 CPU Memory consumed at the end of the loading (end-begin): 10
accelerator.process_index=1 CPU Peak Memory consumed during the loading (max-begin): 573
accelerator.process_index=1 CPU Total Peak Memory consumed during the loading (max): 1506

应对挑战 2

该挑战可以通过在配置 FSDP 时将状态字典类型设为 SHARDED_STATE_DICT 来解决。设为 SHARDED_STATE_DICT 后,每个 rank 各自保存各自 GPU 所需要的分片,这使得用户可以快速保存中间检查点并快速从其恢复训练。而当使用 FULL_STATE_DICT 时,第一个进程 (rank 0) 会用 CPU 收集整个模型,然后将其保存为标准格式。

我们可以用以下命令创建相应的 accelerte 配置文件:

accelerate config --config_file "fsdp_config.yaml"

图片

fsdp 配置

你可以从此处获取生成的配置文件: fsdp_config.yaml。在该配置文件中,分片策略是 FULL_SHARD 。我们使用 TRANSFORMER_BASED_WRAP 作为自动模型包装策略,它使用 _no_split_module 来搜索 transformer 块名并自动进行嵌套 FSDP 包装。我们使用 SHAARDED_STATE_DICT 把中间检查点和优化器状态保存为 PyTorch 官方推荐的格式。同时,如上一节 应对挑战 1 中所述,我们还需要确保训练开始时用 rank 0 来广播参数。从配置文件中你还可以看到我们用的是 bf16 混合精度训练。

那么,在保存最终检查点时,如果将其保存成单个文件呢?我们使用的是以下代码段:

if trainer.is_fsdp_enabled:
    trainer.accelerator.state.fsdp_plugin.set_state_dict_type("FULL_STATE_DICT")

trainer.save_model(script_args.output_dir) # 或者 , 如果整个模型小于 50 GB (即 LFS 单文件的最大尺寸),你还可以使用 trainer.push_to_hub() 把模型推到 hub 上去。

应对挑战 3

为了加快训练速度并减少显存占用,我们可以使用 flash 注意力并开启梯度检查点优化,从而在微调的同时节省计算成本。当前,我们用了一个热补丁来实现 flash 注意力,具体代码可见 这儿。

FlashAttention: Fast and Memory-Efficient Exact Attention with IO-Awareness 一文基于对底层硬件 (即 GPU) 的内存层次结构的深刻理解而引入了一种更快、更节省内存的无损注意力加速算法。底层硬件在设计内存层次结构时,遵循的实践原则是: 带宽/速度越高的内存,其容量越小,因为它更贵。

根据博文 根据第一性原理让深度学习性能起飞,我们可以发现,当前硬件上的注意力模块是 内存带宽受限 的。原因是注意力机制 主要由逐元素操作 组成,如下左图所示。我们可以观察到,掩码、softmax 和 dropout 操作占用了大部分时间,而非需要大量 FLOP 的矩阵乘法。

图片

注意力机制的性能瓶颈

这正是 flash 注意力解决的问题,其想法是 去除冗余的 HBM 读/写操作。该算法通过将所有内容保留在 SRAM 中,待执行完所有中间步骤后再将最终结果写回到 HBM,即 算子融合 来实现这一目的。下图简要描述了算子融合是如何克服内存瓶颈的。

图片

算子融合

在前向和反向传播过程中我们还使用了 平铺 (Tiling) 优化技巧,将 NxN 大小的 softmax 分数计算切成块,以克服 SRAM 内存大小的限制。在使用平铺技巧时,我们会使用在线 softmax 算法。同时,我们还在反向传播中使用了 重计算 技巧,以大大降低在前向传播过程中存储整个 NxN softmax 分数矩阵所带来的内存消耗。

如欲深入理解 flash 注意力,请参考博文 ELI5: FlashAttention、根据第一性原理让深度学习性能起飞 以及原始论文 FlashAttention: Fast and Memory-Efficient Exact Attention with IO-Awareness。

综合运用所有手段

你可参考 此脚本,以在 SLURM 中用 Accelerate 启动器运行训练。下面还给出了一个等效命令,展示了如何使用 Accelerate 启动器来运行训练。请注意,该命令会覆盖 fsdp_config.yaml 中的 main_process_ipmain_process_portmachine_ranknum_processes 以及 num_machines 配置。另一个需要重点注意的是,这里的存储是所有节点共享的。

accelerate launch \
    --config_file configs/fsdp_config.yaml \
    --main_process_ip $MASTER_ADDR \
    --main_process_port $MASTER_PORT \
    --machine_rank \$MACHINE_RANK \
    --num_processes 16 \
    --num_machines 2 \
    train.py \
    --model_name "meta-llama/Llama-2-70b-chat-hf" \
    --dataset_name "smangrul/code-chat-assistant-v1" \
    --max_seq_len 2048 \
    --max_steps 500 \
    --logging_steps 25 \
    --eval_steps 100 \
    --save_steps 250 \
    --bf16 True \
    --packing True \
    --output_dir "/shared_storage/sourab/experiments/full-finetune-llama-chat-asst" \
    --per_device_train_batch_size 1 \
    --gradient_accumulation_steps 1 \
    --dataset_text_field "content" \
    --use_gradient_checkpointing True \
    --learning_rate 5e-5 \
    --lr_scheduler_type "cosine" \
    --weight_decay 0.01 \
    --warmup_ratio 0.03 \
    --use_flash_attn True

整个微调过程需要约 13.5 小时,下图给出了训练损失曲线。

图片

训练损失曲线

下例给出了使用上述模型完成的一段对话:

System Prompt: You are a helpful, respectful and honest assistant. Always answer as helpfully \
as possible, while being safe. Your answers should not include any harmful, \
unethical, racist, sexist, toxic, dangerous, or illegal content. Please ensure that \
your responses are socially unbiased and positive in nature.

If a question does not make any sense, or is not factually coherent, explain why \
instead of answering something not correct. If you don’t know the answer to a \
question, please don’t share false information.

- Human: What is Deep Learning? Explain like a Pirate.

+ Assistant: Arrr Grumete! Are ye lookin' fer a proper explanation o' Deep Learnin'?
+ Alright then, listen up me hearty! Deep Learnin' be a type o' machine learnin' that uses artificial neural networks to analyze data.
+ Aye, ye heard that right, mateys! Artificial neural networks be models o' the human brain, but instead o' using neurons, they use interconnected nodes or "artificial neurons" to process information.
+ These nodes work together to form layers o' processing units that can learn from large amounts o' data.
+ The more data these systems receive, the better they get at recognizing patterns and makin' decisions on their own.
+ So hoist the sails and set course for adventure with deep learnin', me hearties! It's a treasure trove o' knowledge just waitin' to be discovered.
+ Fair winds and following seas!

- Human: Now explain it like a chef.

+ Assistant: Certainly! Here's an explanation of deep learning from a culinary perspective:

+ Think of a recipe as a sequence of steps used to transform raw ingredients into a delicious dish.
+ Similarly, in deep learning, there are multiple layers of "ingredients" (or features) that are combined and transformed through various operations to produce a final output or prediction.
+ Each layer builds upon the previous one, refining and enhancing the representation of the input data until it reaches the desired outcome.
+ Just as different spices enhance the flavors of food, each layer adds depth and complexity to the model's understanding of the input, allowing it to make more accurate predictions.
+ And much like how chefs must carefully balance the amount of salt, sugar, and other seasonings in a recipe, the training process in deep learning involves adjusting the weights and biases of the network to achieve the perfect blend of accuracy and efficiency.
+ With enough practice and experimentation, anyone can become a master chef... I mean, a master of deep learning! Bon appétit!

整个对话使用的格式如下:

<|system|> system message <|endoftext|> <|prompter|> Q1 <|endoftext|> <|assistant|> A1 <|endoftext|> ...

总结

我们在多节点多 GPU 上使用 PyTorch FSDP 成功微调了一个 70B Llama 模型,并在此过程中解决了各种挑战。我们看到了当前在 🤗 Transformers 和 🤗 Accelerates 中应如何初始化大模型从而有效克服 CPU 内存不足的问题。我们还给出了如何高效地保存/加载中间检查点,同时又能以易于使用的方式保存最终模型的最佳实践。为了加速训练并减少 GPU 显存使用,我们还强调了 flash 注意力和梯度检查点机制的重要性。最后,我们向大家展示了在 🤗 Accelerate 上仅需要简单的配置就可以在多节点多 GPU 上微调大模型。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

java--集合基础

1.集合和数组的特点对比 集合类的特点 提供一种存储空间可变的存储模型&#xff0c;存储的数据容量可以发生改变 集合和数组的区别 共同点&#xff1a;都是存储数据的容器 不同点&#xff1a;数组的容量是固定的&#xff0c;集合的容量是可变的 2.ArrayList集合 ArrayLi…

解决 Element-ui中 表格(Table)使用 v-if 条件切换后,表格的列的筛选不显示了

解决方法 在每个需要使用 v-if 或 v-else 的 el-table-column 上增加 key 作为唯一标识&#xff0c;这样渲染的时候就不会因为复用原则导致列数据混乱了。关于key值&#xff0c;一般习惯使用字段名&#xff0c;也可随机生成一个值&#xff0c;只要具有唯一性就可以。

Centos7云服务器上安装cobalt_strike_4.7。附cobalt_strike_4.7安装包

环境这里是阿里的一台Centos7系统。 开始安装之前首先要确保自己安装了java11及以上环境。 安装java11步骤&#xff1a; sudo yum update sudo yum install java-11-openjdk-devel把服务器端&#xff08;CS工具分服务器端和客户端&#xff09;的CS安装到服务器上后给目录下的…

mysql原理--B+树索引的使用

1.索引的代价 在介绍如何更好的使用索引之前先要了解一下使用这玩意儿的代价&#xff0c;它在空间和时间上都会拖后腿&#xff1a; (1). 空间上的代价 这个是显而易见的&#xff0c;每建立一个索引都要为它建立一棵 B 树&#xff0c;每一棵 B 树的每一个节点都是一个数据页&…

Proxmark3 Easy救砖-20231209

事情是这样的&#xff0c;在淘宝买了个PM3&#xff0c;拿到手后刷固件的&#xff0c;一不小心刷成砖头了&#xff0c;现象就是四个灯全亮&#xff0c;插上电脑USB不识别。问商家他也不太懂&#xff0c;也是个半吊子技术&#xff0c;远程给我刷机搞了半天也没有搞定&#xff0c;…

Softmax回归

一、Softmax回归关键思想 1、回归问题和分类问题的区别 Softmax回归虽然叫“回归”&#xff0c;但是它本质是一个分类问题。回归是估计一个连续值&#xff0c;而分类是预测一个离散类别。 2、Softmax回归模型 Softmax回归跟线性回归一样将输入特征与权重做线性叠加。与线性回归…

排序算法:【冒泡排序】、逻辑运算符not用法、解释if not tag:

注意&#xff1a; 1、排序&#xff1a;将一组无序序列&#xff0c;调整为有序的序列。所谓有序&#xff0c;就是说&#xff0c;要么升序要么降序。 2、列表排序&#xff1a;将无序列表变成有序列表。 3、列表这个类里&#xff0c;内置排序方法&#xff1a;sort( )&#xff0…

排序-选择排序与堆排序

文章目录 一、选择排序二、堆排序三、时间复杂度四、稳定性 一、选择排序 思想&#xff1a; 将数组第一个元素作为min&#xff0c;然后进行遍历与其他元素对比&#xff0c;找到比min小的数就进行交换&#xff0c;直到最后一个元素就停止&#xff0c;然后再将第二个元素min&…

使用NCNN在华为M5部署MobileNet-SSD

一、下载ncnn-android-vulkan ncnn-android-vulkan.zip 文件是一个压缩文件&#xff0c;其中包含了 ncnn 框架在 Android 平台上使用 Vulkan 图形库加速的相关文件和代码。 在 Android 平台上&#xff0c;ncnn 框架可以利用 Vulkan 的并行计算能力来进行神经网络模型的推理计…

算法——位运算

常见位运算总结 基础位运算 << >> ~与&&#xff1a;有0就是0或|&#xff1a;有1就是1异或^&#xff1a;相同为0&#xff0c;相异为1 / 无进位相加 给一个数n&#xff0c;确定他的二进制表示中的第x位是0还是1 让第x位与上1即可先让n右移x位&上一个1&#…

【docker三】Docker镜像的创建方法

目录 一、Docker镜像&#xff1a; 1、 镜像的概念 2、docker的创建镜像方式&#xff1a; 1.1、基于已有镜像进行创建&#xff1a; 1.2、基于模版创建&#xff1a; 1.3、基于dockerfile创建&#xff1a; 二、Dockerfile概述 1、Dockerfile概念&#xff1a; 2、dockerfile…

【UI自动化测试】appium+python+unittest+HTMLRunner

简介 获取AppPackage和AppActivity 定位UI控件的工具 脚本结构 PageObject分层管理 HTMLTestRunner生成测试报告 启动appium server服务 以python文件模式执行脚本生成测试报告 下载与安装 下载需要自动化测试的App并安装到手机 获取AppPackage和AppActivity 参考&#xff…

AWS攻略——使用中转网关(Transit Gateway)连接不同区域(Region)VPC

文章目录 Peering方案Transit Gateway方案环境准备创建Transit Gateway Peering Connection接受邀请修改中转网关路由修改被邀请方中转网关路由修改邀请方中转网关路由 测试修改Public子网路由 知识点参考资料 区别于 《AWS攻略——使用中转网关(Transit Gateway)连接同区域(R…

云降水物理基础

云降水物理基础 云的分类 相对湿度变化方程 由相对湿度的定义&#xff0c;两边取对数之后可以推出 联立克劳修斯-克拉佩龙方程&#xff08;L和R都为常数&#xff09; 由右式看出&#xff0c;增加相对湿度的方式&#xff1a;增加水汽&#xff08;de增大&#xff09;和降低…

SpringData JPA 搭建 xml的 配置方式

1.导入版本管理依赖 到父项目里 <dependencyManagement><dependencies><dependency><groupId>org.springframework.data</groupId><artifactId>spring-data-bom</artifactId><version>2021.1.10</version><scope>…

全新UI彩虹外链网盘系统源码V5.5/支持批量封禁+优化加载速度+用户系统与分块上传

源码简介&#xff1a; 全新UI彩虹外链网盘系统源码V5.5&#xff0c;它可以支持批量封禁优化加载速度。新增用户系统与分块上传。 彩虹外链网盘&#xff0c;作为一款PHP网盘与外链分享程序&#xff0c;具备广泛的文件格式支持能力。它不仅能够实现各种格式文件的上传&#xff…

数据接口测试工具 Postman 介绍!

此文介绍好用的数据接口测试工具 Postman&#xff0c;能帮助您方便、快速、统一地管理项目中使用以及测试的数据接口。 1. Postman 简介 Postman 一款非常流行的 API 调试工具。其实&#xff0c;开发人员用的更多。因为测试人员做接口测试会有更多选择&#xff0c;例如 Jmeter…

LeetCode-周赛-思维训练-中等难度

第一题 1798. 你能构造出连续值的最大数目 解题思路 我们先抛开原题不看&#xff0c;可以先完成一道简单的题目&#xff0c;假设现在就给你一个目标值X&#xff0c;问你能够构造出从【1~X】的连续整数&#xff0c;最小需要几个数&#xff1f; 贪心假设期望&#xff1a;我们要…

node14升级node16之后,webpack3项目无法启动处理

node从14升级到16之后&#xff0c;项目就无法启动了&#xff0c;研究了webpack3升级5&#xff0c;研究好几个小时都无法启动&#xff0c;最后发现&#xff0c;微微升级几个版本就可以了。webpack还是3 版本改了好多个的&#xff0c;但是不确定具体是哪几个起作用的&#xff0c;…

【LVGL】STM32F429IGT6(在野火官网的LCD例程上)移植LVGL官方的例程(还没写完,有问题 排查中)

这里写目录标题 前言一、本次实验准备1、硬件2、软件 二、移植LVGL代码1、获取LVGL官方源码2、整理一下&#xff0c;下载后的源码文件3、开始移植 三、移植显示驱动1、enable LVGL2、修改报错部分3、修改lv_config4、修改lv_port_disp.c文件到此步遇到的问题 Undefined symbol …