本实践中,唯品会AI平台与NVIDIA团队合作,结合NVIDIATensorRT和NVIDIAMerlinHierarchicalKV(HKV)将推理的稠密网络和热Embedding全置于GPU上进行加速,吞吐相比CPU推理服务提升高于3倍。
应对GPU推理上的难题
唯品会(NYSE:VIPS)成立于2008年8月,总部设在中国广州,旗下网站于同年12月8日上线。唯品会主营业务为互联网在线销售品牌折扣商品,涵盖名品服饰鞋包、美妆、母婴、居家、生活等全品类。
在使用GPU打开推理算力天花板过程中,遇到了如下问题:
稠密网络,如何获取更好的GPU推理性能;
Embeddingtable如何使用GPU加速查询。
为了解决上面的问题,我们选择使用了NVIDIATensorRT和MerlinHierarchicalKV。具体原因如下:
稠密网络使用TensorRT推理,通过TensorRT和自研Plugin方式获取更好的推理性能;
HierarchicalKV是一个高性能GPUTable实现,我们将热Embedding缓存在GPU中,冷Embedding则通过内存和分布式KV存储,加速查表过程。
GPU推理服务设计方案
图1.GPU推理服务工作流程图
如上图所示,支持GPU推理服务,可以分为如下几步:
TensorPS(自研训练框架)
支持离线和实时训练;
离线训练:生成天级全量模型,完成后同步给Odin;
实时训练:生成小时级别的全量模型和分钟级别的增量模型,完成后同步给Odin;
2.Odin(模型协调者)
(离线/实时)单机模型的全量模型:触发TensorRTConverter;
(离线/实时)分布式模型的全量模型:同时触发TensorRTConverter和Reshard;
(离线/实时)单机/分布式模型的增量模型:触发TensorRTConverter;
3.TensorRTConverter(模型转换器)
将Dense网络转换成TensorRTEngine;
转化完成,如果是全量模型,向模型管理API汇报全量版本;如果是增量模型,向模型管理API汇报增量版本;
4.Reshard(参数分片模块)
对模型参数分片后,向模型管理API汇报版本;
分片后参数,同步到分布式在线参数服务Atreus;
5.Thor(自研推理服务)
单机模型:通过模型管理API获取全量模型版本,拉取模型并启动推理服务Thor;
分布式模型:需要部署分布式参数服务Atreus和推理服务Thor;
如果开启了实时模型特性,Thor会定时通过模型管理API获取增量版本,拉取并更新增量模型;
6.Atreus(自研分布式在线参数服务)
仅用于分布式模型,可支持TB级参数;
如果开启了实时模型特性,Atreus会定时通过模型管理API获取增量版本,拉取并更新增量参数。
GPU模型推理
图2.前向计算流程图
如上图所示,前向计算可以分为如下几步:
H2D拷贝(CPU->GPU);
Embedding层,使用GPUTablelookup(GPU);
Dense层,使用TensorRT+自研Plugin推理(GPU);
D2H拷贝(GPU->CPU)。
稠密网络使用TensorRT在GPU上计算
图3.稠密网络TensorRT推理优化
如上图所示:
稠密网络使用TensorRT推理,结合自定义Plugin实现推理性能优化。
利用HierarchicalKV实现GPUTablelookup
图4.基于HierarchicalKV的GPUTable
如上图所示,查表过程可以分为如下几步:
将keys拷贝到GPU;
将keysconcat成一个大的mergedkeys,减少后续查表次数;
mergedkeys查GPUTable,输出mergedvalues,并输出未命中missedkeys和missedindices;
拷贝missedkeys到CPU;
查询Atreus(分布式参数服务器),获取missedvalues;
missedvalues拷贝到GPU;
将missedvalues更新到mergedvalues;
将mergedvalues输出Split成多个Tensor(和keys一一对应);
对missedkeys进行去重;
去重之后,异步更新GPUTable。
TensorRTConverter实现GPU模型转换
图5.TensorRTConverter转换流程
如上图所示,TensorRTConverter可以分为如下几步:
FreezeCPU模型;
切分模型Graph成Sparse和Dense两个子图,Sparse图在GPU上执行,Dense图经过图优化后使用TensorRT推理;
Dense图转化成ONNX模型;
优化ONNX模型,把图中OP替换成自定义的高性能TensorRTPlugin;
转换ONNX模型成TensorRTEngine;
合并Sparse图和TensorRTEngine生成GPU模型。
自研CUDAKernel,提高性能
GPUTable加速查表
基于HierarchicalKV增强了find接口,支持获取未命中keysindices等信息,在高命中率情况下有更好的性能,并贡献给社区:
voidfind(constsize_typen,constkey_type*keys,//(n)value_type*values,//(n,DIM)key_type*missed_keys,//(n)int*missed_indices,//(n)int*missed_size,//scalarscore_type*scores=nullptr,//(n)cudaStream_tstream=0)const
2.GPU支持CSR(Compressedsparserow)格式的序列特征
根据统计,序列特征有85%+的数据都是填充值,使用CSR格式压缩序列特征可以大幅度减小序列特征大小。考虑到搜推序列数据的特殊性(填充值都在序列尾部),这里仅使用value和offset两个序列表示原始稀疏矩阵,如下图:
图6.CSR的稀疏矩阵
通过Fusion的方式,减少Lookup过程CUDAKernel数量,提升推理性能。
图7.Lookup过程优化对比
优化前:N个输入对应N个LookupCUDAKernel;
优化后:通过提前合并,将CUDAKernel数量减少为3个(Concat、Lookup和Split)。
通过Fusion的方式,减少CSR处理过程CUDAKernel数量,提升推理性能,下图以ReduceSum举例。
图8.CSR处理优化流程
优化前:N对输入对应N个ReduceSumCUDAKernel;
优化后:通过提前合并,将CUDAKernel数量减少为4个(2个Concat,1个ReduceSum和1个Split)。
3.H2D,合并CPU->GPU内存拷贝
搜推模型中有较多的特征输入,GPU推理中需要将这些Tensor从CPU拷贝到GPU,频繁小内存的cudaMemcpy会导致性能下降,最佳实践是将这些Tensor打包在一块连续内存中,将整个大内存H2D拷贝到GPU。
4.Tile算子融合
搜推模型中有超过200个Tile,大量的KernelLaunch会带来GPU推理性能恶化,最佳实践是进行KernelFusion,在一个大的算子中执行多个小Kernel,从而充分发挥GPU的并发优势。
持续在搜推广场景中GPU加速
唯品会AI平台一直追求性能上的极致,未来将会持续与NVIDIA技术团队合作,继续探索使用HierarchicalKV在训练超大型模型上的GPU性能优化,在提升GPU性能方面进行不断地探索和实践,也会对GenerativeRecommenders进行探索和实践。