gpu加速pinterest推荐模型,参数量增加100倍,用户活跃度提高16%

OneFlow深度学习框架 OneFlow深度学习框架     2022-11-30     751

关键词:

作为图片届的“Twitter”,Pinterest首页展示给用户的图片也离不开背后的推荐模型。近期,其工程团队通过将机器学习服务从CPU转移到GPU上,使得Pinterest可以上线比之前大100倍的推荐模型。上线大模型给模型质量带来了阶跃式的提升,最终将Pinterest首页feed流的用户活跃度提高了16%。

在本文中,他们分享了如何只经过微小的投入和延迟的成本实现这一优化目标,这包括优化特定算子,整合内存传输,通过CUDA Graph技术在设备上执行静态图,以及分布式系统的重新设置。他们的实践证明,要想提高模型效果,模型参数就得变大,而使用GPU服务方案的经济效益远超CPU服务方案。

来源|Pinterest Engineering

翻译|郑泽康

Pinterest的使命是给每个人带来创造他们所热爱生活的灵感。为了实现这一使命,我们所有产品中都包含的一个关键组件就是各式各样的推荐模型,它们负责在合适的时间给合适的人展示合适的内容。我们的推荐模型是通过高级算法进行训练的一系列机器学习模型,用于理解用户在Pinterest上花费时间时的行为,这些推荐模型是通过定制的机器学习模型服务器(Scorpion Model Server, 即SMS)来运行的。

SMS 上需要面对十分艰巨的技术挑战,基于3000多亿个Pin的语料库,它必须在毫秒内为4亿多个用户提供相关推荐。之前,SMS在CPU上进行模型推理,其内核经过了多年的优化以满足我们对延迟和基础设施成本的严格要求,但即使最新一代的CPU也几乎达到了SMS服务的极限。我们必须非常审慎地确保,每次因模型变化而带来的延迟和基础设施成本的增加都是合情合理的。

机器学习领域里模型参数和计算量增加的趋势让问题变得更加严峻。在推荐系统中,具有1000亿参数量的模型已经很常见,并在业内常被提及。

在Pinterest,我们采用了稍微不同的方式,通过使用诸如Transformer的现代模型架构来扩大模型。在更大模型下,我们立即观测到模型准确率发生的质变——其大幅提升了Pinner(译注:Pinterest用户)的参与度。但是,在CPU服务器上运行这些现代模型架构几乎让成本和延迟都提升了40倍,这一代价难以承受。因此,我们转而寻求使用GPU来加速模型推理,从而可以使用合理的成本来运行这些模型。

1

优化

当我们尝试那些开箱即用的GPU服务时,很快意识到在经济高效地利用GPU运行推荐模型服务之前需要对其优化。我们首先使用分析工具来分析在模型推理过程中发生了什么,在仔细观察分析结果时,我们注意到时间线上有大量的小CUDA Kernel在执行。

这是推荐系统模型的预期行为,其中数百个特征在模型后期阶段进行特征拼接之前需要单独处理。然而,对于大量的小算子,启动CUDA Kernel带来的开销比计算开销还要昂贵。与训练时的batchsize相比,模型服务时的batchsize相对更小,进而加剧了这一问题。

上图分别是模型优化前和优化后的分析结果。CUDA Kernel时间线(用红框突出显示)表明,Kernel的启动开销(蓝色块之间的间隙)显著减少,因此GPU得到了更好得利用,它将大部分时间花费在Kernel执行中。

2

减少小op的数量

我们采取的第一个方法是找出减少小op数量的机会。我们寻找常被使用的模型组件,并尽可能对其优化。其中一个例子是Embedding的查表模块,它包含两个计算步骤:原始ID到索引的查找,索引到Embedding的查找。由于我们有大量特征,这两步操作会被重复数百次。通过使用cuCollections (https://github.com/NVIDIA/cuCollections以支持GPU上原始ID的哈希表,并实现了自定义的Embedding查找模块以合并多个查找操作,我们显著地减少了op的数量。在执行一些优化后,马上看到了更优的性能表现。

3

合并内存拷贝

同样,当我们在主机和GPU显存之间搬运Tensor时,也存在整合数据传输的机会。通用推荐模型里的一个候选样例通常会使用数百个特征作为输入,对于每一次推理,各个特征作为一个单独的tensor被拷贝到GPU显存中。虽然在主机和GPU显存之间搬运数据非常快,但是为每个请求调度数百个cudaMemcpy()函数调用的开销很快成为瓶颈。

从主机单独拷贝Tensor到 GPU vs 一次拷贝整个内存缓冲区

为了解决这个问题,我们应用了一个简单的优化将cudaMemcpy()调用次数从几百次减少到一次:不再使用Torch框架将Tensor单独移动到GPU上,而是先将所有Tensor的数据放置到一块预先分配好的连续内存缓冲区中,并一次性将缓冲区内容拷贝到GPU里,最终通过指向GPU显存缓冲区的不同偏移量来重构得到GPU上的所有张量。

该优化带来的代价是要显式管理预先分配的内存缓冲区的生命周期,以及需要对不同数据类型手动处理GPU显存对齐。但作为结果,P50数据拷贝延迟从10ms 降低到1ms以下,这证明了该优化带来的复杂性是可以接受的。

4

利用CUDA Graph

为了进一步优化模型推理过程,我们使用CUDA Graph(https://pytorch.org/blog/accelerating-pytorch-with-cuda-graphs/) 来完全消除剩余小op的开销。CUDA Graph允许我们将模型推理过程捕捉为静态图,而不是单独调度。它可以让整个计算作为一个单元进行执行,而不产生任何Kernel启动开销。我们支持将CUDA Graph作为模型服务的一个新后端。一开始加载模型时,模型服务执行一次模型推理以构建图实例,该实例可以针对实时流量重复执行。

CUDA Graph在一个批处理内(下图)执行Kernel,而不是在一个序列中逐个执行(上图),这减少了Kernel之间CPU启动带来的开销。图表来自:https://pytorch.org/blog/accelerating-pytorch-with-cuda-graphs/

CUDA Graph自身的一些限制给我们的模型服务带来了额外的复杂性。其中最大的限制是CUDA Graph要求所有Tensor都具有静态形状和布局,这对动态大小批次和不规则的变长Tensor带来了挑战。然而,我们相信为了获得更好性能进行的权衡是值得的,并且我们可以将输入Tensor补齐到精心挑选的静态形状。

5

使用更大的batchsize

最后,我们重新研究了SMS为模型推理执行的批处理策略。SMS支持动态批处理,可以让多个请求合并成更大的批次。它通常能带来更好的吞吐量,但代价是需要较短的时间以等待请求序列收集足够多的项(item)。对于CPU上的ML推断,我们通常想要将请求分成小批量来提高并行度以减小延时。然而对于GPU,其延时对batchsize并不敏感,使用更大的batchsize对GPU提升工作负载效率更重要。

这种batchsize的需求使我们重新思考了SMS里的分布式系统设置。对于CPU上的ML推断,我们使用scatter-gather结构将原始请求拆分,并在多个叶子结点上并行执行,以获得更小的延时。

此外,该架构允许我们为每个叶子结点分配一个固定的数据切片,以优化特征提取期间的缓存命中率。然而,由于GPU倾向使用大batchsize,因此删除root layer直接在原始请求中使用大batchsize更有意义。最终我们使用了CacheLib的混合缓存,它用DRAM和SSD来补偿与scatter-gather 架构设置相比的缓存容量损失。

6

结果

我们首先测量了模型单次推理的延时。我们使用c5.18x AWS实例提供CPU服务,g5.4 AWS实例提供GPU服务。

CPU延时随着batchsize线性增长,在较小的batchsize下,GPU延时几乎相同,此时Kernel启动开销占延时主导因素。然而随着batchsize增加,实际计算时间主导了延时,GPU延时以亚线性形式增长。在实践中,GPU效率提升的亮点在于SMS可以使用更大的batch工作。结合了所有优化之后,我们获得了惊人的结果,相比 CPU 服务,GPU服务在较大batchsize下的每批次的延迟提升了100倍以上。

我们的服务指标也展示了令人印象深刻的结果。通过优化模型操作,重新设置分布式系统以及优化数据传输并使用CUDA Graph,我们以30%的更低延时上线了77倍大的模型,并以适当成本增加了20%的吞吐量。

最后,两个数量级效率提升开启了Pinterest最先进的推荐模型架构。可以看到,模型质量显著地提升直接转化为更高的用户参与度。在过去的一年,我们以适当的基础设施成本将一个主要产品的用户参与度提升了16%。很快,我们将推出比我们的CPU模型大100倍的最大模型。

7

结论

将基于CPU模型服务转换成基于GPU服务的过程很复杂,但这是我们在Pinterest使用最先进推荐模型的一个必要步骤。我们能够以适当的成本提供大100倍的推荐模型,这为我们的机器学习工程师给Pinner解锁更相关和响应更迅速的推荐内容提供了基础。

(本文经授权后编译发布,原文:

https://medium.com/pinterest-engineering/gpu-accelerated-ml-inference-at-pinterest-ad1b6a03a16d

其他人都在看

欢迎体验OneFlow v0.8.0:GitHub - Oneflow-Inc/oneflow: OneFlow is a deep learning framework designed to be user-friendly, scalable and efficient.OneFlow is a deep learning framework designed to be user-friendly, scalable and efficient. - GitHub - Oneflow-Inc/oneflow: OneFlow is a deep learning framework designed to be user-friendly, scalable and efficient.https://github.com/Oneflow-Inc/oneflow/

torch中topk()无法gpu加速

...输入的数据类型与所使用的GPU不匹配,可能会导致无法GPU加速。需要确保输入的数据类型与所使用的GPU一致,才能实现GPU加速。2.数据量过小:如果输入数据量非常小,GPU加速的效果可能不如CPU快速,因为数据传输和GPU计算之间... 查看详情

r语言构建xgboost模型:使用gpu加速xgboost模型构建

R语言构建xgboost模型:使用GPU加速xgboost模型构建目录R语言构建xgboost模型:使用GPU加速xgboost模型构建#仿真数据 查看详情

喜马拉雅基于hybridbackend的深度学习模型训练优化实践

...成本完成对海量用户数据的训练。使用GPU等高性能硬件来加速模型训练已经成为CV,NLP等领域的行业标准;在使用稀疏训练数据的推荐场景下,国内外的各大厂商也在积极转向使用高性能GPU来替代传统的CPU训练集群,以提升训练... 查看详情

corr2018|horovod:fastandeasydistributeddeeplearningintensorflow(代码片段)

将深度学习模型的训练从单GPU扩展到多GPU主要面临以下问题:(1)训练框架必须支持GPU间的通信,(2)用户必须更改大量代码以使用多GPU进行训练。为了克服这些问题,本文提出了Horovod,它通过RingAllreduce实现高效的GPU间通信,而且... 查看详情

推荐模型复现:精排模型deepfmdin(代码片段)

1.DeepFM模型1.1DeepFM模型产生背景DNN的参数过大:当特征OneHot特征转换为DenseVector时,网络参数过大。FNN和PNN的交叉特性少:使用预训练好的FM模块,连接到DNN上形成FNN模型,后又在Embeddinglayer和hiddenlayer1之间增加... 查看详情

深度神经网络压缩和加速详解

...缩模型比较1.背景介绍        深度学习模型的压缩和加速是指利用神经网络参数的冗余性和网络结构的冗余性精简模型,在不影响任务完成度的情况下,得到参数量更少、结构更精简的模型.被压缩后的模型计算资源需求和内存... 查看详情

深度学习装机指南:从gpu到显示器,全套硬件推荐

前言:硬件设备,是任何一名深度学习er不可或缺的核心装备。各位初级调参魔法师们,你们有没有感到缺少那一根命中注定的魔杖?可是,各种CPU、GPU、内存条、外设,那么多品牌种类型号参数,到底该怎么选?文章内容较长... 查看详情

数学模型的过拟合和欠拟合

...或场景;训练集中的数据噪音(异常值)干扰过大;训练模型的“逻辑假设“到了模型应用时已经不能成立参数太多,模型复杂度太高;特征量太多,模型训练过度,比如决策树模型,神经网络模型1.2解决方法减少特征数量正则... 查看详情

综述论文:当前深度神经网络模型压缩和加速方法速览

ASurveyofModelCompressionandAccelerationforDeepNeuralNetworks研究背景在神经网络方面,早在上个世纪末,YannLeCun等人已经使用神经网络成功识别了邮件上的手写邮编。至于深度学习的概念是由GeoffreyHinton等人首次提出,而在2012年&#... 查看详情

模型压缩-剪枝算法详解(代码片段)

...模型,从而减少对硬件的存储、带宽和计算需求,以达到加速模型推理和落地的目的。近年来主流的模型压缩方法包括:数值量化(DataQuantization,也叫模型量化),模型稀疏化(Modelsparsification,也叫模型剪枝ModelPruning),知识... 查看详情

如何训练2457亿参数量的中文巨量模型“源1.0”

如何训练2457亿参数量的中文巨量模型“源1.0”浪潮人工智能研究院从2018年的BERT到2020年的GPT-3,NLP语言模型经历了爆发式的发展过程,其中BERT模型的参数量为3.4亿,而GPT-3的模型参数量达到了1750亿。2021年9月,浪... 查看详情

增加池化层后参数量

...道数和输出通道数相同,也就是池化的过滤器通道数为12.参数量计算在这里插入图片描述【卷积层的参数量】输入:224*224*3,64个3*3*3filter,输出featuremap224*224*64,卷积层的参数量为:(3*3*3+1)*64=1792计算公式:参数量=(filtersize+1)... 查看详情

万亿模型训练需1.7tb存储,腾讯混元如何突破gpu极限?(代码片段)

...为是AI领域过去十年最具前景的进展。未来,兼具大模型和多模态模型的AIGC模型有望成为新的技术平台。近来,腾讯发布的混元AI万亿大模型登顶权威中文测评基准CLUE榜并超越人类水平。混元AI大模型采用腾讯太极机器学... 查看详情

pytorch在gpu上训练模型(代码片段)

...orch在GPU上训练模型为了真正利用Pytorch中Tensor的优秀属性,加速模型的训练,我们可以将训练过程转移到GPU上进行.1.首先要定义设备,如果CUDA是可用的则被定义成GPU,否则被定义成CPU.device=torch.device("cuda:0"iftorch.cuda.is_available()... 查看详情

在按键上增加模型的加速度?

】在按键上增加模型的加速度?【英文标题】:Increasingaccelerationofmodelonkeypress?【发布时间】:2018-09-1713:38:39【问题描述】:我正在尝试在开放空间中旋转单个立方体。起初,它从静止开始,然后在按键时它应该在特定按键的特... 查看详情

一块gpu搞定chatgpt;ml系统入坑指南;理解gpu底层架构

...RTX3090跑ChatGPT体量模型」而获得了人们的关注。虽然FlexGen加速后的大模型看起来仍然很慢——跑1750亿参数的语言模型时每秒1个token,但令人印象深刻的是,它已经把不可能变成了可能。传统上,大型语言模型(LLM... 查看详情

[mnist03]gpu加速和过程参数保存(代码片段)

写在前面因为之前在DSW上训练的,每个epoch大概要24s左右,时间太长了,因此今天我就想要用GPU跑,但是DSW上没有GPU了,所以我选择转战colab,而且今天我还选择了训练过程中参数保存的方法,那就是将... 查看详情

新一代ctr预测服务的gpu优化实践(代码片段)

CTR模型在互联网的搜索、推荐、广告等场景有着广泛的应用。近年来,随着深度神经网络的引入,CTR模型的推理对硬件算力的要求逐渐增加。本文介绍了美团在CTR模型优化的实践。通过分析模型结构特点,结合GPU硬件... 查看详情