渲染性能优化全局视角

文/ 阿里淘系 F(x) Team – 甄子

遇到性能优化的问题,大抵都会从两个方向入手:行业标准优化手段、实际性能瓶颈问题。既能够从先进的模式、方法、套路吸收借鉴,又能够结合实际性能情况设计应对方案,已然是高质量工作的路径了,但是,路上还充斥着各种判断和选择,稍有不慎还是会泥足深陷,走上“要你命 3000 ”的道路。

在这条“要你命 3000”的道路上,大体可以分为三个部分:感知、愈合、防腐。所谓“感知”,是指对于性能的问题是否能够发现和理解?所谓“愈合”,是指对于发现和理解的性能问题是否能解决?所谓“防腐”,是指性能问题解决之后是否会在未来劣化?这三个部分已经有非常丰富的时间经验、文章和理论,这里不再赘述,我想尝试从全局和系统化的角度,去分享一下我对“渲染性能优化的本质”之愚见,并尝试提出一条从底层原理出发的路径,在渲染性能优化方向上,面对纷繁复杂的问题时,有更加精准和明确的依据和更有价值的方案。

硬件视角

广义上看性能的本质是:在体验、处理能力和功耗三个方向上找到平衡点。我这样定义的灵感是来自于硬件芯片设计,芯片设计从硬件工程视角对芯片要求:面积、性能、功耗三个方向上找到平衡点。在使用 FPGA、CPLD 进行芯片设计和验证的时候,逻辑门数量受到芯片生产工艺和面积的限制而产生一个总体的面积约束,这时候,要使用一些逻辑门组合成专用电路(所谓 IP)从而提升性能并降低功耗(专用电路功耗小于软件加通用电路),否则,只能设计成通用电路如:寄存器操作、通用处理指令……等。因此,可以看出,在条件允许的情况下,专用电路也就是所谓“专业化”能够提供更好的的面积、性能、功耗比。

有同学会问:那这些专业化的电路使用率小于通用化电路的时候怎么办?

确实,如此一来性能就会很差,这就是为何 M1 可以帮 Apple 做到行业第一的原因,因为 Apple 从软件生态到操作系统、从底层系统 API 到硬件驱动、从驱动到硬件电子电路设计时全局规划的,这种全局规划保证了软件调用最频繁的系统程序硬件化,在提高性能功耗比的同时也保证了专业化电路的使用率,这就是我所谓的:硬件视角。

又有同学问:你这个是 Apple 的体系 Android 又不能用。

确实,Android 作为一个开源生态系统不如 Apple 的封闭系统那么精练、简洁、一致,但是,只要有心,还是可以从 Android 的开源生态系统里找到蛛丝马迹,把这些开源生态系统的能力按照:软件生态到操作系统内、从底层系统 API 到硬件驱动、从驱动到硬件提供的专业电子电路的路径梳理出来,在根据这个路径对应到软件工程上,从硬件视角全局性的看待性能优化问题,充分利用底层硬件的能力。

当初在负责国际浏览器的时候,因为两印和东南亚的基础设施建设落后,移动网络条件非常差带宽感人,多媒体时代的移动互联网充斥着图片和视频,我和团队便一起研究超分辨率(一种用机器学习算法模型预测图像的技术实现传统插值无法达到的 240p 到 720p 超分辨率转换),希望能够给两印和东南亚的 UC 浏览器用户带来更好的体验。

模型和算法在团队的努力下很快就有了突破,我们已经解决了大部分模型预测带来的图像显示错误问题,但整个模型所要求的算力是两印和东南亚移动端设备所无法支撑的,即便我们用尽了降低精度、模型压缩剪枝、知识蒸馏等手段,在红米这种中低端机型(低端机型定义为 1G 内存的 ARMV7 架构处理器)上仍然只有几帧每秒的速度,根本不可用。

于是,我们把目光投向了 ARM NEON 指令优化:一种并行浮点计算和向量运算加速指令集。由于使用的是开源的 XNN 框架,我们有能力对 OP 进行 NEON 的定向优化,从而提升算法模型的前向运算速度,降低对内存和 CPU 的压力,历时近一年的努力,终于做到了每秒 24 帧的 240p 到 720p 超分辨率能力,部署在 UC Browser 上服务两印和东南亚网友。

虽然,之前在软件工程里也经常接触汇编指令优化,但这次从软件(算法模型)到系统 API、从驱动到硬件电子电路的全局优化经历,让我真正感受到硬件视角的重要性。那个每天工作到深夜,自学 Android 编程和 NEON 指令集的算法工程师就是:振奇,他也因为这个项目升到 P8 算法高级专家。

那么,你可能会问:这和前端有什么关系?我尝试举个例子来诠释他们之间的相似性。首先,前端包含了渲染和计算两个部分。渲染部分由 HTML 和 CSS 共同定义,之后,交由浏览器进行渲染,因此,浏览器确实屏蔽了大部分连接到底层能力的部分,造成前端缺乏抓手。但是,随着 WebGL、WebGPU 等全新 API 暴露,前端还是有一些抓手的。计算部分由 JavaScript 定义,之后,交由脚本引擎执行,因此,脚本引擎屏蔽了大部分连接到底层能力的部分,造成前端缺乏抓手,同时,脚本引擎基本都用虚拟机屏蔽底层指令集和硬件差异,因此,又多了一层屏蔽。但是,随着 Node.js 和 WASM 等技术让部分程序 Local 化本地执行,随着 V8 引擎用一些特殊策略让部分 JavaScript 被 Sparkplug 编译成 Local 代码执行,这种情况也会有所改变。(参考:v8.dev/blog/sparkp…

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享