NeuralTalk评:7月初便看到这篇文章,这三四年的简报也在断断续续地关注YCNN、YCNN2,再到现如今KwaiNN的消息,身边快手的朋友也经常发相关岗位的招聘。本文介绍快手这方面的工作,与前些日子推送的《字节跳动APP工厂的端云一体AI落地方案:端云深度融合,模型极速上线之路》类似,写得还蛮详细。
NeuralTalk认为,本文也算是比较中规中矩的大厂AI架构与实践,而不同点在于,快手聚焦于手机平台,移动端的工程化落地更细致,这是优点更是业务基线,当然也有挑战,如文末提到的在输出效果和工程代码上,服务端与移动端的尚未完全统一等。
Y-tech///
作为国民短视频社区,快手平台平均日活跃用户 3.79 亿,全球月活跃用户达到 10 亿。在蓬勃发展的用户社区中,快手Y-tech部门研发的计算机视觉、计算机图形学、AR/VR等AI能力,落地快手旗下各App,为内容生产的各个环节提供智能创作的能力。
围绕这些AI能力的落地,我们分为四个部分展开:
第一部分先介绍一下背景,包括效果展示、整体AI架构和存在的挑战。
第二部分是快手的端上AI SDK的架构设计,设计思路包括统一接口、建设完善的公共库、功能模块化和插件化、以及统一运算流程。
第三部分针对性能这个最大的挑战,来探讨一下我们的解决思路。整体上,通过图形图像库和模型分机型下发平台这两套方案,来分别解决前后处理和模型推理这两部分的性能瓶颈。细节上,我们结合三个具体案例,来分享一下通过多种时序模式、多线程框架和缓存设计来在不同的业务场景上提高性能。
最后,我们谈谈对未来的展望。
这里展示了“童话公主”、“隐身衣”、“梵高星空”和“万物AR”这四款魔法表情特效,精致效果的背后,每一款都用到了前沿且多能力复合的AI技术,包括生成式技术(GAN)、增强现实(AR)、人脸关键点、人像分割、天空分割等等。其中,2020 年 11 月上线的 GAN 类玩法“童话魔法”,达到了数百万作品量和数十亿播放量。
除了特效拍摄,Y-tech的AI能力还落地了多样的业务场景。编辑场景的“智能抠像”可以从视频片段中抠出人像、头部或天空;相机拍摄的“智能识物”可以扫一扫识别出场景中各个物体;相册场景的“一键出片”的可以从用户的相册中分析场景和物体,自动生成影集。
这些能力的背后,是快手的一套从模型训练到端上推理的完整AI架构。
下图右侧的一列展示了开发环境的主要模块,包括数据管理、训练平台、引擎工具等一系列平台和框架。
左侧展现了端上运行时的架构,也是本次分享的重点。AI接口层、AI算法层和AI底层库这三个部分组成了Y-tech的AI SDK——YKit。YKit通过对接各个中台SDK,来落地快手旗下的各业务方App,此外业务方也可以直调YKit,提供更灵活的对接方式(NeuralTalk评:从YKit调用与直接调用各个模块的SDK可能有点混乱,可能带来一些问题如体积,包重复等问题。这个模式,即接口、算法、底层,看起来分属三个小组或团队)。
图1 快手的AI能力架构:运行环境、开发环境
YKit底层调用的KwaiNN推理引擎(前身为YCNN,NeuralTalk评:在20年4月的GMTC上,快手Y-tech AI工程团队负责人边红昌就做过题为《快手自研YCNN ,让复杂神经网络模型加速实现》的技术分享,后来也有YCNN2的消息),是快手自研的深度学习推理引擎,针对不同的硬件平台做了适配和指令级优化,相比常见的开源推理引擎,有着优秀的性能表现(NeuralTalk评:目前看其业务层都是移动端APP,这套架构支持的平台应是以支持安卓、iOS平台为主;而开发环境应该是对应不同的开源深度学习框架如TF、PyTorch等)。
在操作系统层面,YKit以同一套C++原生代码支持iOS、安卓、macOS、Windows和Linux各端。在硬件层面,YKit和KwaiNN针对不同的芯片进行了适配和优化,并自动搭配下发不同的模型,以提供最佳的效果与性能的平衡(NeuralTalk评:不同机型高中低端设备对应不同模型)。
YKit内部的算法分为若干个大类,各大类下面再细分具体的算法功能点,提供共计近百种AI能力。例如:
分割抠图类包含人像分割、头部分割、衣服分割、指甲分割等等;
人脸人体类包含人脸关键点、人体关键点、人脸属性、表情识别等等;
生成式类则实现了SDK代码和模型结构的高度复用,搭配不同的训练数据和前后处理参数,提供各种丰富的效果,包括年龄渐变、表情套系(大笑、嘟嘴、皱眉等)、童话魔法、国风等等。
图2 Ykit AI能力一览:涵盖AR、3D、分割、人体等多种能力
在YKit每日几千亿次的调用量、几亿次的模型创建量、近百种AI能力的背后,也同时对工程团队提出了巨大挑战。
图3 快手在模型上线遇到的三类挑战:效果、性能、成本
No.1效果
第一个挑战来自效果。首先是AI能力数量,如何对各种各样的AI能力和需求,做到高度复用公共基础层,接入统一的框架,决定了新功能是能够快速开发落地、还是会越来越臃肿导致拉低效率。
效果观感,则与SDK的图像前后处理能力和数据接口相关。参数可配置能力,决定了算法开发和线上迭代的效率,以及是否能满足不同的业务方需求,影响了新玩法和落地方式的丰富度。特效包装,则受到与下游特效团队SDK的接口对接的灵活性和易用性的影响。
No.2 性能
第二部分的挑战在性能。大家知道,快手的老铁人群多样化,机型分布也很广泛,如何保证在占比极高的中低端机上提供流畅的效果,直接影响到老铁们的用户体验。内存开销和崩溃率,在某些应用场景中尤其重要,例如直播过程中人脸关键点检测一旦崩溃导致App退出,会造成巨大的负面影响。包体积大小,对尤其是中低端机的安装成功率、进而到整体用户数量都有直接的影响。性能挑战这一部分,是日常开发中遇到的最常见的难题。
No.3 成本
第三个挑战是成本。这里涉及了算法从开发到上线的每个环节,包括算法和工程同学的开发投入、QA同学的测试周期、下游的业务对接效率和上游算法在后期迭代时的效率。
介绍完了背景,我们谈谈YKit针对以上挑战,在整体框架层面设计时的考虑。
图4 大纲:框架设计
YKit框架主要分为三部分:核心库、功能模块和工具链。
图5 YKit框架三大模块:核心库、功能模块、部署工具链
核心库
核心库包含了各算法公用的模块,其中接口层包含两个部分:
1. 调用接口保证了所有算法的一套从初始化、到参数设置、运行、获取结果等的统一接口;
2. 通用数据接口是一套方便在调用方和内部算法模块间进行输入输出转换的库,综合了json和pb等格式的设计优点,并提供灵活的类型转换和更高的性能,同时减少了依赖方需要发版的频率。
核心库里包含了图形图像库,图形图像库针对前后处理进行了性能优化,并封装了易于调用的接口。
模块工厂提供了功能点的插件化能力。
模型管理对不同底层硬件提供分级的模型,达到最佳性能。
数据转换提供了图像色彩空间和格式等等的转换。
引擎接口方便对底层KwaiNN引擎的调用。
日志和上报收集调用次数、线上性能、各业务方调用情况等信息,帮助不断改善YKit**(NeuralTalk评:线上数据需要不断反哺YKit、KwaiNN,这方面人员和数据需要一定程度的打通与权限)。
功能模块
功能模块在大类层面提供编译开关和配置,各大类里实现具体的二级功能点,等会儿会具体介绍。
工具链
工具链包括多端Demo,新算法开发时,只需要实现C++底层的算法功能,无需添加上层与客户端相关的逻辑代码,即可在各端运行**(NeuralTalk评:这点与字节不同,字节是全链路自动化,算法训练好后,可以快速部署测试,算法同学无需对接安卓、iOS开发)。
自动化文档用Doxygen从算法代码和Demo代码自动生成,配合前面提到的通用数据接口,保证和业务方对接时的高效。
本地素材库方便快速调试和验证。另外还有单元测试和打包平台来方便日常开发。
在运算流程上,YKit综合了各个算法功能的特点、以及上下游拍摄、特效等SDK的框架和接口,设计了两条链路的通用运算流程。算法根据自身需求,既可以运行两条链路,也可以只运行其中一条。
CPU链路提供了灵活的前后处理类型,并支持多个功能点串联。
GPU链路针对不同算法需要的后处理,提供高性能的shader运算。
图6 运算流程统一化:CPU链路与GPU链路
我们再看看算法功能点接入的设计。从提供能力的逻辑来看,YKit分为以下几层:
最底层是KwaiNN引擎,它既是YKit的基础库,也可以单独提供给业务方进行推理直调,达到最轻量化;
上层是YKit的框架层,其中的功能模块库,包含了算法功能点的模块基类,算法功能模块工厂使各功能模块在编译时注册能力,运行时动态加载,宏开关可以根据不同平台的定制能力和配置依赖库;
再上层是核心模块,如人脸关键点这样高频使用的能力,随YKit包一起提供,以达到快速加载,提升用户体验;
最上层是动态模块,在安卓上由特效素材或业务逻辑触发动态下发,可使包体积减小50%。
图7 功能插件化:从能力模块、算法模块、基础库和KwaiNN引擎
接下来的第三部分,我们谈谈快手在性能方面的探索和实践。
图8 大纲:性能优化和配套工具链
YKit的流程和算法能力虽然多样,但是总结下来整体运算分为两个主要部分:前后处理和模型推理。针对前后处理部分,我们的解决思路是建立一个高效易用的图形图像库,提升前后处理的效率。对模型推理部分,KwaiNN引擎已经做了大量的底层优化,YKit要做的就是为各硬件平台和机型进行最优的模型适配,整个过程做到自动化和智能化,提升落地效率。下面分别看一下这两个部分。
图9 性能问题定位的全流程链路
YKit中建立了一套图形图像库,提供统一的上层接口,这样算法在开发时无需关注不同的硬件平台,图形图像库的运算后端会适配对应的算子,包括CPU基础计算、Neon、OpenGL、Metal等后端。目前有50多个优化后的算子,并且在不断扩充中(NeuralTalk评:这里前后预处理在GPU上应该是GL,而KwaiNN后端计算应该是CL)。
图10 图形图像库运算架构:Arm CPU、GL、Metal、Vulkan
YKit配套的模型分级下发平台,默认提供了10档机型分级,包括iOS和安卓的高、中、低,华为HiAI、iPhone CoreML等等,AI能力在开启时,会拉取对应的分级模型包,充分利用底层KwaiNN针对CPU、GPU、NPU各平台的优化。模型分级下发平台还提供了丰富的可配置性,以及部署安全性。
图11 模型分级下发:从服务端配置参数到移动端下发
上面是解决性能问题的两个主要部分,下面我们举三个具体案例,来看看不同功能点在实际落地时还有哪些优化思路。
案例一
案例一是近年来大火的GAN类特效,这里我们把这个大类沉淀成了一套通用方案。
在模型上,我们对不同的效果复用8档模型结构设计,覆盖从几个G到几十M的MAC(乘法加法操作)运算量跨度区间,通过前面提到的模型分级下发平台来适配各档机型。
在时序上,我们设计了3种不同的运行模式,来达到在高端机上提供最佳效果、低端机上保证流畅度的平衡。随模型平台下发的,还有20余个可配置参数,这样新的效果玩法往往只需要通过参数来改变前后处理流程,做到快速上线。
图12 GAN类特效性能优化案例:同步模式、异步模式、压帧模式
案例二
案例二是一个运算流程更复杂的人脸动态效果,它包含了人脸关键点、人脸3D重建、人脸渲染、GAN模型推理、二次关键点计算共5个步骤。对于这么重的计算,我们利用了功能模块化设计的优势,结合了拍摄SDK的多线程架构和YKit内部多线程架构,将运算分散在3个CPU线程和1个GPU线程上,大幅提高了性能。
图13 人脸动态效果多线程架构案例:4个CPU线程与1个GPU线程的交替计算
案例三
案例三对应的是刚才PPT第二页展示的视频智能抠像的能力。在这里,视频编辑场景与实时拍摄场景的用户交互形态不同,对性能的侧重点也有不同的需求,快手的编辑SDK使用了CPU预分析和GPU渲染的两阶段设计,来提升用户播放视频时的流畅度。
YKit为此提供了推理缓存接口,这套通用接口可以用于各个AI能力,并且除了可缓存最终结果,也可对功能内的不同细粒度结果进行缓存。此外,针对不同机型等级提供了优化的缓存大小,以节省硬盘空间。在解析缓存时,YKit会进行数据校验,并支持对缺失缓存的帧进行重新推理。编辑SDK与YKit合作开发的智能抠像功能,落地后在性能上实测远优于竞品。
图14 案例三:视频编辑场景的推理缓存
最后,我们再回顾一下开头提出的三个主要挑战。在上面一系列的框架设计、配套工具和优化的背后,我们能看到针对这些问题的解决思路。
图15 “效果”挑战应对思路:
公共模块复用、统一配置接入入口
图16 “性能”挑战应对思路:模型机型分级、NPU能力、内存池、模块动态下发、完善日志
图17 “成本”挑战应对思路:模型机型分级、NPU能力、内存池、模块动态下发、完善日志
对于未来,我们有很多新的期待。
首先,我们会继续推进服务端与移动端的统一,这包括输出效果和工程代码两个层面**(NeuralTalk评:估计对于MacOS、Windwos平台的推理与移动端并不是一套代码。这里的统一应是推理);
其次,对于机型分布广泛的老铁们,我们会不断打磨更高的性能,让更多的人能够体验到酷炫的AI能力;
此外,开发效率始终是我们想要提升的点。
最终的目标,还是为用户提供更好的AI服务,持续提升每个人独特的幸福感。
图18 未来展望:推理统一、进一步优化中低端机型性能、对内开发流程优化
往期回顾
- 嵌入式AI简报2021-08-05
- 嵌入式AI简报2021-07-18
- 嵌入式AI简报(2021-07-01)
- 嵌入式AI简报 (2020-08-26)
- 嵌入式AI简报(2020-08-06)
- 嵌入式AI简报(2020-07-18)
- 嵌入式AI简报(2020-07-18)
- 嵌入式AI简报 (2020-07-02)
- 嵌入式AI简报 (2020-06-17)
- 嵌入式AI简报 (2020-06-03)
- 嵌入式AI简报 (2020-05-15)
- 嵌入式AI简报 (2020-04-26)
- 嵌入式AI简报 (2020-04-04)
- 嵌入式AI简报 (2020-03-19)
- 嵌入式AI简报 (2020-03-02)
- 嵌入式AI简报 (2020-02-16)
- 嵌入式AI简报 (2020-01-27)
- 嵌入式AI简报 (2020-01-06)
本作品采用知识共享署名-相同方式共享 4.0 通用许可协议进行许可。
欢迎关注公众号,关注模型压缩、低比特量化、移动端推理加速优化、部署。
更多嵌入式AI相关技术干货请关注嵌入式AI专栏。