关于ios:Metal新特性大幅度提升iOS端性能

前言

Metal 是一个和 OpenGL ES 相似的面向底层的图形编程接口,通过应用相干的 api 能够间接操作 GPU ,最早在 2014 年的 WWDC 的时候公布。Metal 是 iOS 平台独有的,意味着它不能像 OpenGL ES 那样反对跨平台,然而它能最大的开掘苹果挪动设施的 GPU 能力,进行简单的运算,像 Unity 等游戏引擎都通过 Metal 对 3D 能力进行了优化, App Store 还有相应的使用 Metal 技术的游戏专题。

阿里巴巴淘系技术部的闲鱼团队是比拟早在客户端侧抉择Flutter计划的技术团队,以后的闲鱼工程里也是一个较为简单的Native-Flutter混合工程。作为一个2C的利用,性能和用户体验始终是闲鱼技术团队在开发中比拟关注的点。而Metal这样的间接操作GPU的底层接口无疑会给闲鱼技术团队突破性能瓶颈提供一些新的思路。

上面会具体论述一下这次大会Metal相干的新个性,以及对于闲鱼技术和整个淘系技术来说,这些新个性带来了哪些技术启发与思考。

( WWDC 2020精彩内容思否专栏:https://segmentfault.com/blog…  

本篇内容来自于阿里巴巴淘系技术部,无线开发工程师岑彧。
更多精彩内容可关注【淘系技术】公众号。)

Metal相干新个性

1.Harness Apple GPUs with Metal

这一章其实次要介绍的是Apple GPU的在图形渲染上的原理和工作流,是一些比拟底层的硬件原理。当咱们应用Metal进行App或者是游戏的构建的时候,Metal会利用GPU的tile-based deferred rendering (TBDR)架构给利用和游戏带来十分可观的性能晋升。这一章次要就是介绍GPU的的架构和能力,以及TBDR架构进行图像渲染的原理和流程。总之就是号召开发者们应用Metal来构建利用和游戏。因为这个session没有波及到下层的软件开发,就不对视频的具体内容进行赘述了。详情可见:Harness Apple GPUs with Metal

2.Optimize Metal apps and games with GPU counters

这一章次要介绍了Xcode中的GPU性能剖析工具Instrument,这个工具当初曾经反对了GPU的性能剖析。而后从多个方面剖析了GPU的性能瓶颈,以及性能瓶颈呈现时的优化点。总体来说就是通过性能剖析工具来优化咱们的App或者游戏,让整个画面更加晦涩。整个章节次要分为五个局部:

1.总体介绍

这个环节次要是疾速回顾了一下Apple的GPU的架构和渲染流程。而后因为很多渲染工作都须要在不同的硬件单元上进行,例如ALU和TPU。他们对不同的吞吐量有着不同的度量。有很多GPU的性能指标须要被思考,所以推出了GPU性能计数器。这个计数器可能测量到GPU的利用率,过高和过低都会造成咱们的渲染性能瓶颈。对于计数器的具体应用,参考官网的video成果会更好:Optimize Metal apps and games with GPU counters(6:37~9:57),次要应用了Instrument工具,对于工具的全面具体的应用能够参考WWDC19的session videoGetting Started with Instruments

2.性能瓶颈剖析

这一章次要介绍了造成GPU性能瓶颈的各个方面以及它们的优化点。次要分为六个方面,如下图所示:

1.Arithmetic(运算能力)

GPU中通常通过ALU(Arithmetic Logic Unit)来解决各种运算,例如位操作,关系操作等。他是着色器外围的一部分。在这里一些简单的操作或者是高精度的浮点运算都会造成一些性能瓶颈,所以给出以下倡议来进行优化:

如上图所示,咱们能够应用近似或者是查找表的形式来替换简单的运算。此外,咱们能够将全精度的浮点数替换为半精度的浮点数。尽量避免隐式转换,防止32位浮点数的输出。以及确保所有的着色器都应用Metal的“-ffast-math”来进行编译。

2.Texture Read and Write

GPU通过Texture Processing Unit来解决纹理的读写操作。当然在读写的过程中也会遇到一些性能瓶颈问题。这里从读和写两个局部别离来给出优化点:

1.Read

如上图所示,咱们能够尝试应用mipmaps。此外,能够思考更改过滤选项。例如,应用双线性代替三线性,升高像素大小。确保应用了纹理压缩,对Asset应用块压缩(如ASTC),对运行时生成的纹理应用无损纹理压缩。

2.Write

如上图所示,咱们应该留神到像素的大小,以及每个像素中惟一MSAA样本的数量。此外,能够尝试一些优化一些逻辑写法。

3.Tile Memory Load and Store

图块内存是一组存储Thread Group和ImageBlock数据的高性能内存。当从ImageBlock或是Threadgroup读取或写入像素数据时,比方在应用Tile着色器时或者是计算分派时,能够拜访到Tile内存。那当应用GPU性能计数器发现这个方面的性能瓶颈时,咱们能够如下图所示进行优化。

思考缩小threadgroup的并行,或者是SIMD/Quadgroup操作。此外,确保将线程组的内存调配和拜访对齐到16字节。最初,能够思考从新排序内存拜访模式。

4.Buffer Read and Write

在Metal中,缓冲区只被着色器外围拜访。在这个中央发现了性能瓶颈。咱们能够如下图所示进行优化:

能够更大力度的压缩打包数据,例如应用例如packed_half3这样小的类型。此外,能够尝试向量化加载和存储。例如应用SIMD类型。防止寄存器溢出,以及能够应用纹理来均衡工作负载。

5.GPU Last Level Cache

如果在这个方面,咱们的GPU性能计数器显示一个过高的值。咱们能够如下图这样优化:

如果纹理或者是缓存区也同样显示一个过高的值,咱们能够把这个优化放到第一优先级。咱们能够思考减小工作集的大小。如果Shader正在应用Device Atomics,咱们能够尝试重构咱们的代码来应用Threadgroup Atomics。

6.Fragment Input Interpolation

分段输出插值。分段输出在渲染阶段由着色器外围进行插值。着色器外围有一个专用的分段输出插值器。这个是比拟固定和高精度的性能。咱们能优化的点不多,如下图所示:

尽可能的移除传递给分段着色器的顶点属性。

3.内存带宽

内存带宽也是影响咱们GPU性能的一个重要因素。如果在GPU性能计数器的内存带宽模块看到一个很高的值。咱们就应该如下图所示来进行优化:

如果纹理和缓存区也同样显示比拟高的值,那优化优先级应该排到第一位。优化计划也是较少Working Set的大小。此外,咱们应该只加载以后渲染过程须要的数据,只存储将来渲染过程须要的数据。而后就是确保应用纹理压缩。

4.Occupancy

如果咱们看到整体利用率比拟低,这意味着Shader可能曾经耗尽了一些外部资源,比方tile或者threadgroup内存。也可能是线程实现执行的速度比GPU创立新线程的速度快。

5.防止反复绘制

咱们通过GPU计数器能够统计到反复绘制的区域,咱们应该高校应用HSR来防止这样的重绘。咱们能够如图所示的程序来进行绘制。

3.Build GPU binaries with Metal

这一章次要给开发者们介绍了一种应用Metal的编程工作流,能够通过优化Metal的渲染编译模型来加强渲染管线,这个优化能够在应用程序启动,特地是首次启动时大大减少PSO(管线状态对象)的加载工夫。能够让咱们的图形渲染更加的高效。整个章节次要分为四个局部:

1.Metal的Shader编译模型概述

家喻户晓,Metal Shading Language是Apple为开发者提供的Shader编程语言,Metal会将编程语言编译成为一个叫做AIR的两头产物,而后AIR会在设施上进一步编译,生成每个GPU所需的特定的机器码。整个过程如下图所示:

上述过程在每个管线的生命周期中都会产生,以后Apple为了减速管线的从新编译和从新创立流程,会缓存一些Metal的办法变体,然而这个过程还是会造成屏幕的加载耗时过长。而且在以后的这个编译模型中,应用程序不能在不同的PSO(管线状态对象)中重用之前生成的机器码子程序。
所以咱们须要一种办法来缩小这个整个管线编译(即源代码->AIR->GPU二进制代码)的工夫老本,还须要一种机制来反对不同PSO之间共享子程序和办法,这样就不须要将雷同的代码屡次编译或者是屡次加载到内存中。这样开发者们就能够应用这套工具来优化App首次的启动体验。

2.Metal二进制文件介绍

Metal二进制文件就是解决上述需要的办法之一,当初开发者们能够间接应用Metal为二进制文件来管制PSO的缓存。开发者能够收集已编译的PSO,而后将它们存储到设施中,甚至能够散发到其余兼容的设施中(同样的GPU和同样的操作系统),这种二进制文件能够看做一种Asset。上面是一些例程和示意图:

总的来说就是这个Metal二进制文件能够提供开发者手动治理管线缓存的办法,这样就能够从一个设施中获取这些文件并部署到其余兼容的设施上,在iOS环境下,极大地缩小了第一次装置游戏或利用以及设施重启后的管道创立工夫。能够优化利用的首次启动体验和冷启动体验。

3.Metal对动静库的反对

动静库将容许开发者编写可重用的库代码,却能够缩小从新编译程序的工夫和内存老本,这个个性将会容许开发者将计算着色器和程序库动静链接。而且和二进制文件一样,动静库也是可序列化和可转移的。这也是解决上述需要的计划之一。
在PSO生成的时候,每个应用程序都须要为程序library生成机器码,而且应用雷同的程序库编译多个管线会导致生成反复的机器码。因为大量的编译和内存的减少,这个可能会导致更长的管线加载工夫。而动静库就能够解决这个问题。
Metal Dynamic Library容许开发者以机器码的模式动静链接,加载和共享工具办法。代码能够在多个计算管线中重用,打消了反复编译和多个雷同子程序的存储。而且这个 MTLDynamicLibrary是可序列化的,能够作为应用程序的Asset应用。MTLDynamicLibrary其实就是多个计算管线调用的导出办法的汇合。
大抵的工作流程如下:咱们首先创立一个MTLLibrary作为咱们指定的动静库,这个能够将咱们的metal代码编译为AIR。而后咱们调用办法makeDynamicLibrary,这个办法须要指定一个惟一的installname,在管线创立时,linker将会应用这个名字来加载动静库。这个办法能够将咱们的动静库编译成为机器码。这就实现了动静库的创立。
对于动静库的应用来说:通过设置MTLCompileOptions里的libraries参数,就能够实现动静库的加载和应用了。代码如下:

4.开发工具介绍

这个局部次要介绍了构建Metal二进制文件和构建动静库的具体工具和办法。以视频的模式可能会更好的体现,详情可见:Build GPU binaries with Metal (从22:51开始)

4.Debug GPU-side errors in Metal

这一章次要介绍的是GPU侧的bug,以后如果咱们的应用程序呈现了GPU侧的bug,他的谬误日志经常都不能让开发者很直观的定位到谬误的代码范畴和调用栈。所以在最新的Xcode中,加强了对于GPU侧的debug机制。能够像在代码侧发成的谬误一样岂但能定位到谬误起因,还有谬误的调用堆栈和各种信息都能够具体的查看到。让开发者能更好的修复代码造成的GPU侧的渲染谬误。

1.Enhanced Command Buffer Errors

这是以后的谬误日志上报,咱们能够看到GPU侧的谬误日志不像Api的谬误日志一样能够让开发者很快的定位到谬误起因和谬误的代码地位。

而最新的Metal debugging工具就加强了这方面的能力,让Shader的code也能够像Api代码一样提供谬误定位和分类能力。

咱们通过以下代码便能够启用增强版的commandbuffer谬误机制

谬误一共有五种状态:

咱们也能够通过以下代码来打印error:

开发者能够在开发时和测试时启用优化版的谬误机制

2.Shader Validation

如上图所示,这个性能能够在GPU侧产生渲染谬误时主动定位和catch到谬误并定位到代码,以及获取回溯栈帧。

咱们能够在Xcode中依照以下流程来开启这个性能:

1.开启Metal中的两个Validation选项

2.开启issue主动断点开关并配置类型和分类等选项

Video中用了一个demo来展现整个工作流,具体参见Debug GPU-side errors in Metal(11:25~14:45)大抵流程如下图所示:

这是一个Demo应用程序,很显著它在渲染上呈现了一些异样,然而因为是GPU侧的问题,所以开发者很难定位。然而通过上述的工作流开启Shader Validation之后。

Xcode会主动断点到产生异样的中央,并展现出异样信息,这样就能够极大的晋升开发者的谬误修复效率。

5.Gain insights into your Metal app with Xcode 12

这一章次要讲的是Xcode12给Metal App提供了更多调试和剖析的新工具。大抵如下图所示:

次要分为两个局部:

1.Metal Debugger

这个工具能够让开发者在App运行时,获取到想剖析和调试的任何一帧,而后再进入Xcode提供的各种剖析界面,总体状况,依赖状况,内存,带宽,GPU,Shader等各种具体的界面来对这一帧进行更加具体的剖析和调试。整个过程应用视频的形式可能会更加高效,所以这里不会进行具体的赘述和剖析。详情能够参见Gain insights into your Metal app with Xcode 12

2.Metal System Trace

整个工具跟之前提到过的Debugger相比,他的性能次要是让开发者能够随着工夫的推移来捕捉应用程序的各种信息和特色,能够让开发者很好的调试一些例如终端,帧失落,内存透露等问题。而Debugger次要是对某一帧进行调试和剖析。
他提供了一个叫做编码工夫线的工具,能够让开发者查看到GPU在利用运行中的运行各种命令缓冲的状况。而后提供了一个叫做着色器工夫线的工具,能够让开发者查看到各种着色器在代码运行期间运行的过程。而后还有GPU计数器的工具,这个工具咱们在前文进行了具体的剖析,次要是用于解决GPU的绘制性能问题的工具。而后最初一个工具就是内存调配跟踪工具,能够让开发者查看到利用程序运行过程中各种内存的调配和开释,能够帮忙开发者解决内存透露问题或者是升高利用内存占用。

技术启发与思考

WWDC 20对于Metal的Session中,比拟重要的就是官网提供了很多可供开发者进行GPU级别的调试工具以及性能剖析工具。给比拟成熟宏大而简单的工程突破性能瓶颈,提供更加优良的用户体验提供了一些思路。

闲鱼作为一个电商类App,随着性能和增多和以及工程的复杂化,在劫难逃的会遇到性能瓶颈,而闲鱼团队以后面对挑战的形式是从工程级别来进行优化。从Flutter的角度来看,WWDC 20 对于Metal的调试工具和性能剖析工具的欠缺,无疑提供了更多的优化思路。这为将来运行在iOS上的利用的调优和突破性能瓶颈带来了新的思路和可能性。

对于跨平台框架,Apple有自家的SwiftUI,这也是此次大会的重点项目。不过无论是Flutter,还是SwiftUI,大家最初对利用的性能瓶颈冲破和优化肯定是必由之路的,也就是深刻到GPU级别来进行开发和调试以及性能剖析。对于将来的客户端开发人员,了解GPU和进行GPU级别的编程必定是不可或缺的技能点之一。

( WWDC 2020精彩内容思否专栏:https://segmentfault.com/blog…  

本篇内容来自于阿里巴巴淘系技术部,无线开发工程师岑彧。
更多精彩内容可关注【淘系技术】公众号。)

【腾讯云】轻量 2核2G4M,首年65元

阿里云限时活动-云数据库 RDS MySQL  1核2G配置 1.88/月 速抢

本文由乐趣区整理发布,转载请注明出处,谢谢。

您可能还喜欢...

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据