百度搜索的RLHF性能优化实践

news2024/9/24 1:23:41

作者 | 搜索架构部

导读

本文大语言模型在未经标注的大量文本上进行预训练后,可能产生包含偏见、泄露隐私甚至对人类构成威胁的内容。OpenAI 最先提出了基于人类反馈的强化学习算法(Reinforcement Learning fromHuman Feedback, RLHF),将人类偏好引入到大模型的对齐过程中,从而让大语言模型能够生成符合人类预期的输出。笔者长期在搜索领域应用大模型提升搜索质量,发现RLHF在搜索结果的相关性、准确性和无害性等方面均有显著的提升,同时也观察到由于RLHF 流程相比预训练以及SFT更加复杂,导致在训练效率上,其系统吞吐率远低于预训练或者SFT,这严重制约了 RLHF 的应用与发展。当前业界和学界在预训练阶段和推理部署阶段的性能优化进展非常丰富,但在强化学习尤其是RLHF性能优化的公开资料较少。我们注意到,RLHF 和预训练共享大多数分布式训练技术,因此在优化手段上,RLHF 既要吸收预训练的方法,也要结合自身的特点做针对性地优化。

RLHF 目前已经发展出多种算法,本文将谈一谈 RLHF 的性能优化问题,我们以PPO为例来讨论 RLHF 的性能优化。PPO 优化过程同预训练有显著不同,且较为复杂,因此比较适合用来讨论 RLHF 的性能优化。最近学术界也开始涌现出一批使用监督微调的对齐方式,从而简化对齐过程,如 DPO 算法等,但是其优化手段可被囊括在 PPO 优化手段之内。

我们的优化手段包括文本生成速度优化、动态显存优化、系统并行优化等。经过优化后,我们的方案能够保证效果的同时,大幅提升性能。我们也针对搜索业务场景需求对业界主流方案进行了对比测试,性能大幅优于其他方案。

01 PPO 算法流程

PPO 优化流程涉及四个不同的模型,分别是Actor、Critic、Reward和Reference,是一个典型的多角色多阶段的过程,大致流程如下

PPO的训练阶段同预训练几乎一样,都是先前向计算损失函数,而后进行反向传播。唯一不同的是PPO训练涉及两个模型。PPO的采样阶段是预训练没有的,采样阶段只有纯粹的前向推理计算,包括文本生成和奖励计算等。由于逐token生成的特性,文本生成的效率一直是业界关注的焦点,在PPO流程中更是超过训练时间而成为整个系统的瓶颈。

02 软硬件配置与基线吞吐率分析

为简化讨论,本文以下表中所列的软硬件配置为基准进行讨论。但是本文所提到的优化手段并不受限于下述条件。

2.1 基础配置

2.2 训练配置

其中:

  • prompt_length是prompt数据集的最大长度,prompt的长度分布应该较为均匀,其平均长度也应该接近这个值;

  • generate_lenght是生成文本的最大长度,当生成超过这个阈值时文本会被截断;

  • generate_batch_size是生成文本时的batch_size,这个值越大则GPU利用率越高,但同时会带来更高的显存占用;

  • global_batch_size和micro_batch_size最初由梯度累积概念引入,详情可在网上搜索,这里需要重点说明的是,micro_batch_size是决定系统吞吐率以及显存占用最关键的参数,global_batch_size理论上同系统吞吐率以及显存占用关系不大,也就是说可以无限制的扩大。但如果处理不好,梯度聚合过程也可能导致大量的显存消耗,从而导致global_batch_size无法连续调节,后面会有一个案例具体说明;

  • ppo_iter指的是ppo算法每轮在全量采样数据上迭代几次。

2.3 显存分配方式

全参微调条件下,至少需要1280G(2*8*80G)显存,典型的显存分配方式如下:

图片

这种分配方式的好处如下:

  • 计算负载均衡——除了文本生成阶段只有actor参与以外,其他时间两机的计算大致相同;

  • 显存负载均衡;

  • actor和refer共享初始热启checkpoint、critic和reward共享初始checkpoint,每台机器只需存储一份热启checkpoint

2.4 系统关键部分耗时

2.5 吞吐率计算

系统各关键部分全部为串行执行,一次ppo迭代的耗时为:

可以计算得到系统吞吐率为 256 sample / 1376 s / 16 gpu = 0.012 sample / gpu / s。

03 文本生成速度优化

文本生成大约占了百分之八十左右的耗时,根据阿姆达尔定律:

图片

如果能够加速两倍,整个系统就能够取得接近1.67倍的提速,这是非常可观的。目前业界成熟的大模型应用范式是先在训练框架上进行模型训练,然后再使用专门的推理框架进行模型推理服务,推理加速往往是推理框架重点关注的问题。对于训练框架,一方面在功能上推理往往只起辅助作用,比如校验当前训练结果等,另一方面训练框架大多针对训练特性做优化,很难同时兼容推理的一些优化特性。因此,本项目中引入英伟达的TRT-LLM进行文本生成阶段的加速,不过在讨论TRT-LLM之前,先来探讨一下文本生成速度慢的一些可能原因。

3.1 文本生成速度慢可能的原因

1. 为避免重复计算,文本生成接口均采用kv cache机制,这种机制将文本生成切分成两个阶段,既context阶段和decode阶段。其中context阶段就是对prompt计算kv,因此该阶段也被称作prefill阶段。decode阶段则是逐token生成的过程,由于kv cache大大减少了计算量,该阶段变成访存密集型任务,GPU计算单元的利用率较低。且kv-cache需要额外消耗大量的显存,限制了batch_size的大小,这又进一步降低了GPU计算单元的利用率;

2. 无效生成——由于batch内prompt长短不齐,简单的文本生成策略会从最短的prompt长度位置开始,造成大量的无效生成。当batch内某个句子生成结束后,仍然会跟随batch内其他未结束的句子一起继续生成,又会造成大量的无效生成;

图片

3. 大模型由于参数量过大,单显卡的显存往往无法匹配训练时的显存需求,类Megatron-LM的训练框架使用模型并行将显存需求分散到多张显卡。模型并行包括张量并行和流水并行两种机制,在推理时,这两种机制都会引入的额外通信开销。如果使用pp,还会引入空泡,导致生成效率进一步下降。实际上推理所需的显存远低于训练,10B左右的模型完全可以放在单卡上做推理,从而避免模型并行带来的开销。

3.2 TRT-LLM为什么可以提高文本生成速度

对于问题1,TRT-LLM通过引入paged attention机制优化显存占用,从而提高batch_size,改善吞吐率;

  • 对于问题2,TRT-LLM通过引入inflight batching机制替换已完成的生成任务,大大减少了无效生成,对于序列长度分布极不均匀的场景,甚至观察到了5倍左右的吞吐率提升;

  • 对于问题3,部署TRT-LLM可以无需遵照训练时的模型切分方式,因此也可以降低模型切分带来的开销。

3.3 引入TRT-LLM后带来的问题

3.3.1 额外的显存占用

很显然,TRT-LLM也需要消耗显卡的计算和存储资源,不过由于文本生成和训练在时间上是错开的,可以通过offload的方式错峰使用显存,使得训练和文本生成在显卡使用上互不影响。

3.3.2 参数更新

TRT-LLM以独立进程的方式部署,由于Actor的每轮更新,必须同步更新相应的TRT-LLM模型,简单的参数更新方法如下

3.3.2.1 naive方案

1.actor保存checkpoint到磁盘(训练框架所支持的格式);

2.再t转换为HuggingFace格式的checkpoint;

3.将HuggingFace格式的checkpoint转换成trtllm格式的checkpoint;

4.将TRT-LLM格式的checkpoint转换为TensorRT engine;

5.TRT-LLM Runtime从磁盘中加载TensorRT engine。

上述几个步骤涉及多次磁盘IO,由于模型参数量极大(23GB,参数格式为bf16),总耗时超过15分钟。如果是离线部署,这个方案是可以接受的,且框架有自带的转换脚本,无需额外的开发工作。但是强化学习需要在线更新,15分钟的更新时间会严重拖慢系统速度。幸运的是TensorRT提供了在线更新的接口。另外观察到上述的多次转换是由各个框架格式不兼容造成的,需要手动实现参数转换功能。

3.3.2.2 refit方案

前置条件

TRT engine需开启refit选项(开启方法可参考TRT-LLM文档,此选项会导致dump的TensorRT engine大10M左右,但不会影响性能)

主要步骤

1.(训练进程)将Actor模型的参数转换成TensorRT engine的参数格式,并拷贝到共享内存中(逐Tensor转换和拷贝,主要涉及到一些Tensor的拆分、合并以及转置操作等);

2.(训练进程)将Actor模型的参数和优化器状态等固定显存占用unload到cpu内存中(为TRT-LLM推理腾退显存,可unload部分参数),通知(RPC方式)TRTLLM进程加载最新参数;

3.(TRT-LLM进程)加载cpu内存中保存的TensorRT engine;

4.(TRT-LLM进程)遍历共享内存中的参数并改写TensorRT engine (逐Tensor改写)

整个过程消除了磁盘IO,更新时间优化到20s左右;另外如果考虑使用单卡部署TRT-LLM,从而消除不必要的通讯开销以及空泡(PP),还可以使用共享内存+NCCL通讯的方式更新参数,如下图所示:

图片

相比于共享内存,显卡间的NCCL通讯速度极快,参数拷贝时间几乎可以忽略不计。

3.4 吞吐率改进状况

1. 系统关键部分耗时

从耗时统计中可以看出,TRT-LLM对文本生成速度提升了超过30倍,大大超出预期。

2. 吞吐率计算

系统各关键部分全部为串行执行,一次ppo迭代的耗时时间为:

可以计算得到系统吞吐率为 256 sample / 456 s / 16 gpu = 0.035 sample / gpu / s,相较于基线吞吐率提升了将近192%。

04 动态显存优化

RLHF训练过程中显存常常是紧缺资源,显存会造成两个问题,一是训练过程中突然出现的OOM警告,使得跑了很长时间的任务失败;二是为了避免OOM刻意调小batch_size,使得显卡计算单元的利用率下降,训练时间延长。大模型训练过程中的显存占用分为固定显存占用以及动态显存占用。固定显存主要包括参数、梯度和优化器状态,对于类Megatron-LM框架来说,固定显存通过模型并行切分之后,继续优化的空间较小,因此需要开发人员关注的是动态显存优化。动态显存主要包括前向的激活以及临时变量等,下面将介绍这两种显存的优化方法。另外对于推理框架来说,激活和临时变量相比kv cache几乎可以忽略不计,而通过引入paged attention技术,kv cache显存占用已经得到了很好的优化,因此这里不多做讨论。

4.1 选择性激活重算 + 序列并行

在反向传播过程中,需要前向过程中的激活参与计算,因此需要保存这部分结果。激活所占的显存比例随着模型规模、batch_size以及序列长度的增加而逐步增加。对特定的模型,当需要增加batch_size以提升训练速度或者需要适配长文本训练任务时,显存会成为最棘手的问题。可通过重算技术来减小激活显存消耗,也就是只保存少部分中间激活,剩余的部分在需要时重新计算。重算对激活显存的优化效果是立竿见影的,但是同时也导致了速度的严重退化。最新的重算技术选择激活显存占用小同时计算较慢的算子作为检查点,而显存占用大并且计算较快的算子的中间结果则被丢弃,这种选择性重算技术虽然在激活显存优化能力上有所下降,但是能够保证速度退化不至于过于严重。

另一种激活显存优化技术是序列并行,这个技术由Megatron-LM引入,其核心思想仍然是使用通讯换取显存。具体而言,Megatron-LM的作者观察到那些TP无法切分的区域,在序列轴的维度上是相互独立的,因此可以在序列轴上进行切分,如下图所示:

图片

实验中观察到,在PP=8的条件下,使用序列并行+选择性重算能够优化掉50%左右的激活显存,但是会带来20%左右的速度退化。可以将batch_size提升至原先的两倍,最终的训练速度相比之前提升接近15%。同时对于更长的文本,预期会有更大的改进。

4.2 按照micro_batch进行padding

这部分以及后面的临时显存优化是一些编程上的注意事项,并无太多的理论。具体而言,当编写训练部分的代码时为图省事,或者不经意间,会对global_batch进行padding,实际进行前向和反向计算时是以micro_batch为单位的,当global_batch内长度分布极不均匀时,由padding导致的计算时间大大增加。

图片

4.3 临时显存优化

临时显存优化的两大原则:

  1. 尽早释放

2. 避免申请过大的显存资源

以推理过程中next_logp计算的优化为例,优化前global_batch_size无法开大,对于训练效果和训练效率均会造成一定影响。下面以gbs=64,mbs=2为例说明:

图片

通过提前计算mbs,尽早释放中间显存,可以将峰值显存从gbs * N优化到mbs * N。

图片

对mbs的计算中也申请了一块2GB左右的显存,通过将计算的粒度控制在单条样本,还可以进一步降低峰值显存占用,代价是计算效率会有所降低,这点需要权衡。

4.4 吞吐率改进状况

由于优化了显存,系统可以使用更大的global_batch_size,降低了流水并行的空泡率(如果开PP的话),从而提高了训练速度。按照micro_batch进行padding由于节省了计算,又进一步提升了训练速度。总的提升大约在10%左右。

1.系统关键部分耗时

2.吞吐率计算

系统各关键部分全部为串行执行,一次ppo迭代的耗时时间为:

可以计算得到系统吞吐率为 256 sample / 432 s / 16 gpu = 0.037 sample / gpu / s,相较于基线吞吐率提升了将近208%。

05 系统并行优化

5.1 优化方法

PPO是一个典型的多阶段流程,所包含的步骤中有些有前后依赖关系,需要串行执行,也有一些步骤则没有依赖关系,可以并行执行,如下图所示:

图片

Actor的训练和Critic的训练任务在不同节点并且相互独立时,可以很容易进行并行计算。ref_logp和logp的计算任务虽然相互独立,但由于在同一节点需要共享显卡,且单个任务既可打满利用率,此时任务并行的意义不大(虽然cuda通过stream机制很容易支持并发任务)。观察到对于ref_logp计算这种仅做推理的任务,将其移动到critic所在的节点也几乎没有影响,之后便可以进行并行计算ref_logp和logp。比较复杂的是文本生成与reward计算之间的并行,两者虽分布在不同的节点,但是任务之间存在依赖关系,即reward计算所需要的句子是文本生成的结果。观察到文本生成按照batch计算并返回,可以通过下述方法重叠两者的计算。

图片

优化后的系统如下所示:

图片

系统中还存在其他一些可以并行的部分,例如actor模型的加载/卸载,共享内存拷贝和TRT-LLM模型的卸载/加载与refit_engine等,其优化方法与上述提到的思想大同小异,这里不再详细介绍。

5.2 吞吐率改进状况

1.系统关键部分耗时

2.吞吐率计算

系统各关键部分全部为串行执行,一次ppo迭代的耗时时间为

可以计算得到系统吞吐率为 256 sample / 275s / 16 gpu = 0.054 sample / gpu / s,相较于基线吞吐率提升了将近350%。

06 其他开源框架对比

实验设置:

全参数RLHF训练,采用16*A100(80G)训练。

图片

07 总结

综上,我们在广泛实验、对比和学习了业界主流框架的情况下,通过分析RLHF任务的特点并采用先进的大模型预训练及推理性能优化手段,使得RLHF任务性能大幅提升,能够以相对少的资源支持了业务的快速迭代和发展,取得了良好的业务效果。

————END————

推荐阅读

基于飞桨框架实现PCA的人脸识别算法

统一多场景自动编译加速——支持动态shape场景,一套架构搞定训推需求

基于飞桨框架的稀疏计算使用指南

云高性能计算平台 CHPC 让企业的传统 HPC 玩出新花样

Embedding空间中的时序异常检测

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

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

相关文章

五种多目标优化算法(MOAHA、NSGA2、NSGA3、SPEA2、MODA)性能对比,包含47个多目标测试函数,6种评价指标,MATLAB代码

一、五种多目标算法及六种评价指标简介 NSGA-III: NSGA-III是Deb在2013年提出的,用于解决高维多目标优化问题。它采用参考点基于的非支配排序方法,并引入了种群的自适应标准化和关联操作,以提高算法在高维问题上的性能和多样性 。…

线程 --- 同步与生产消费者模型

序言 在上一篇的内容中,我们学习了使用互斥锁来保护共享资源,避免多个线程竞争,造成数据不一致等问题。在这一篇文章中,我们将继续深入,学习多线程同步以及生产消费者模型。 1. 线程同步 1.1 什么是线程同步 线程互斥…

操作系统常见面试题总结

文章目录 1 操作系统基础1.1 什么是操作系统?1.2 操作系统主要有哪些功能?1.3 用户态和内核态1.3.1 什么是用户态和内核态?1.3.2 为什么要有用户态和内核态?只有一个内核态不行么?1.3.3 用户态和内核态是如何切换的&am…

HICOOL 2024全球创业大赛角出200个获奖项目

近日,经过超过200天的紧张竞争,HICOOL 2024全球创业大赛从124个国家和地区的7406个创新项目中脱颖而出,共选出了200个获奖项目。 其中,“新一代智能光学显微成像仪器与全流程解决方案”和“基于多尺度深度学习的功能型生物分子设…

Excel下拉框多选

记录一下学会一个新的知识! 两种方式 第一种方式:先在表格里写好需要的值,再在数据关联里面直接引入。 1.新建excel表格,输入下拉框需要的值。 2.点击——数据>有效性 3.选择——序列 4.数据来源——框住刚才写好的数据——…

IMU用于动物行为监测

近日,由比利时和法国组成的科研团队开展了一项创行性的研究,通过在牛颈部安装IMU(惯性测量单元),实现了对牛吃草行为的实时监测。该技术通过捕捉牛咀嚼时的微小动作,并结合机器学习算法,智能区分…

07--kubernetes.deploy与service

前言:这一章主要是deploy与service的配置及其原理,以及一些细节上的补充,同时还会附上镜像拉取策略和容器健康检查的一些操作实例,内容比较多,建议根据目录查看。 1、镜像拉取策略 IfNotPresent:在镜像已经存在的情况…

新迪天工®看图,专业的三维CAD看图工具

替代专业CAD软件,方便查看各种三维和二维CAD图纸 新迪天工看图是一款功能强大的三维模型和二维图纸查看工具,能帮助制造企业以较低的成本、较高的数据安全性实现产品设计数据的跨业务浏览和交互。 应用场景 1、设计图纸评审 可直接对三维模型和二维…

【MATLAB源码-第255期】基于matlab的长鼻浣熊优化算法(COA)无人机三维路径规划,输出做短路径图和适应度曲线.

操作环境: MATLAB 2022a 1、算法描述 长鼻浣熊优化算法(Coati Optimization Algorithm,COA)是一种新兴的群体智能优化算法,其灵感来源于长鼻浣熊在自然界中的觅食行为。长鼻浣熊是一种生活在美洲热带和亚热带森林中…

Redis中的数据类型及应用场景(面试版)

五种常用数据类型介绍 Redis中存储的都是key-value对结构的数据,其中key都是字符串类型,value有5种常用的数据类型: 字符串 string 哈希 hash 列表 list 集合 set 有序集合 sorted set / zset 各种数据类型特点 解释说明: …

DP10RF001支持200MHz~960MHz(G)FSK/OOK调制无线抄表工业传感无线遥控

简介 DP10RF001是一款工作于 200MHz~960MHz 范围内的低功耗、高性能、单片集成的(G)FSK/OOK无线收发芯片。内部集成完整的射频接收机、射频发射机、频率综合器、调制解调器,只需配备简单、低成本的外围器件就可以获得良好的收发性能。 芯片支持灵活可设的数据包格式…

6U VPX总线架构:搭载飞腾D2000/FT2000 + FPGA-K7(赛灵思)

"CPU FPGA" 结构是指一种结合了中央处理器(CPU)和现场可编程门阵列(FPGA)的系统架构。这种架构利用了CPU的通用计算能力和FPGA的并行处理能力,可以提供高效能、低延迟和高灵活性的计算平台。 K7是 Xilinx 7…

Linux进程信号——信号的捕捉、保存、处理

文章目录 信号的基本概念信号保存block位图pending位图handler数组 信号处理sigset_tsigemptysetsigfillsetsigaddset sigdelsetsigismembersigprocmask 捕捉信号 信号的基本概念 信号递达:实际处理信号的动作信号未决:信号从产生到递达之间的状态信号阻…

比人还毒舌的AI上线了!

前段时间社交媒体上很火的毒舌版AI,上线后异常火爆,网友把各路名人的账号输入,川普,马斯克等一干名人被吐槽得体无完肤。 现在这个功能国内也有了,推出了微博版的AI嘴替,微博上的名人纷纷中招。 体验地址&a…

如何修改注解里面的属性值

说明:Java中,注解里的属性值在编译时就已经固定了,是无法通过AOP或者反射技术直接去修改的。本文介绍如何通过动态代理的方式来修改属性值。 搭建环境 首先,创建一个简单的Spring Boot项目,pom.xml文件如下&#xff…

声音事件检测DESED 数据集介绍

DESED dataset contains:DESED Domestic Environment sound event detection; 家庭环境声音事件检测; 1. 数据 Content内容 DESED dataset contains:DESED 数据集包含: Domestic Environment sound event detection; 家庭环境声音事件检测&#xff1…

[学习笔记]在不同项目中切换Node.js版本

文章目录 使用 Node Version Manager (NVM)安装 NVM使用 NVM 安装和切换 Node.js 版本为项目指定 Node.js 版本 使用环境变量指定 Node.js安装多个版本的 Node.js设置环境变量验证配置使用 npm 脚本切换 在开发中,可能会遇到不同的Vue项目需要不同的Node.js&#xf…

各个版本jdk新特性

jdk8新特性 方法引用:方法引用允许直接通过方法的名称来引用已经存在的方法,简化了函数式接口的实现。默认方法(Default Methods):默认方法允许在接口中定义具有默认实现的方法,以便接口的实现类可以继承该…

uniapp-Vue项目如何实现国际化,实现多语言切换,拒绝多套开发,一步到位,看这篇就够

一 安装 找到自己的项目,输入cmd进入命令行,输入安装命令,点击回车进行下载: npm install vue-i18nnext 下载完将在项目的配置文件中看到: 二 使用 2.1 在项目中创建一个文件夹如:lang 用于存放不同语言的包。这些语言文件通常为JSON格式 2.2 在项目main.js文件中引入并初…

YoloV8损失函数篇(代码加理论)

首先yolov8中loss的权重可以在ultralytics/cfg/default.yaml修改 损失函数定义ultralytics/utils/loss.py 回归分支的损失函数 DFL(Distribution Focal Loss),计算anchor point的中心点到左上角和右下角的偏移量IoU Loss,定位损失,采用CIoU…