CPU VS GPU
CPU VS GPU
关于绘图和动画有两种处理的方式:CPU(中央处理器)和GPU(图形处理器)。在现代iOS设备中,都有可以运行不同软件的可编程芯片,但是由于历史原因,我们可以说CPU所做的工作都在软件层面,而GPU在硬件层面。
总的来说,我们可以用软件(使用CPU)做任何事情,但是对于图像处理,通常用硬件会更快,因为GPU使用图像对高度并行浮点运算做了优化。由于某些原因,我们想尽可能把屏幕渲染的工作交给硬件去处理。问题在于GPU并没有无限制处理性能,而且一旦资源用完的话,性能就会开始下降了(即使CPU并没有完全占用)
大多数动画性能优化都是关于智能利用GPU和CPU,使得它们都不会超出负荷。于是我们首先需要知道Core Animation是如何在这两个处理器之间分配工作的。
动画的舞台
Core Animation处在iOS的核心地位:应用内和应用间都会用到它。一个简单的动画可能同步显示多个app的内容,例如当在iPad上多个程序之间使用手势切换,会使得多个程序同时显示在屏幕上。在一个特定的应用中用代码实现它是没有意义的,因为在iOS中不可能实现这种效果(App都是被沙箱管理,不能访问别的视图)。
动画和屏幕上组合的图层实际上被一个单独的进程管理,而不是你的应用程序。这个进程就是所谓的渲染服务。在iOS5和之前的版本是SpringBoard进程(同时管理着iOS的主屏)。在iOS6之后的版本中叫做BackBoard。
当运行一段动画时候,这个过程会被四个分离的阶段被打破:
- 布局 - 这是准备你的视图/图层的层级关系,以及设置图层属性(位置,背景色,边框等等)的阶段。
- 显示 - 这是图层的寄宿图片被绘制的阶段。绘制有可能涉及你的-drawRect:和-drawLayer:inContext:方法的调用路径。
- 准备 - 这是Core Animation准备发送动画数据到渲染服务的阶段。这同时也是Core Animation将要执行一些别的事务例如解码动画过程中将要显示的图片的时间点。
- 提交 - 这是最后的阶段,Core Animation打包所有图层和动画属性,然后通过IPC(内部处理通信)发送到渲染服务进行显示。
但是这些仅仅阶段仅仅发生在你的应用程序之内,在动画在屏幕上显示之前仍然有更多的工作。一旦打包的图层和动画到达渲染服务进程,他们会被反序列化来形成另一个叫做渲染树的图层树(在第一章“图层树”中提到过)。使用这个树状结构,渲染服务对动画的每一帧做出如下工作:
- 对所有的图层属性计算中间值,设置OpenGL几何形状(纹理化的三角形)来执行渲染
- 在屏幕上渲染可见的三角形
所以一共有六个阶段;最后两个阶段在动画过程中不停地重复。前五个阶段都在软件层面处理(通过CPU),只有最后一个被GPU执行。而且,你真正只能控制前两个阶段:布局和显示。Core Animation框架在内部处理剩下的事务,你也控制不了它。
这并不是个问题,因为在布局和显示阶段,你可以决定哪些由CPU执行,哪些交给GPU去做。那么改如何判断呢?
GPU相关的操作
GPU为一个具体的任务做了优化:它用来采集图片和形状(三角形),运行变换,应用纹理和混合然后把它们输送到屏幕上。现代iOS设备上可编程的GPU在这些操作的执行上又很大的灵活性,但是Core Animation并没有暴露出直接的接口。除非你想绕开Core Animation并编写你自己的OpenGL着色器,从根本上解决硬件加速的问题,那么剩下的所有都还是需要在CPU的软件层面上完成。
宽泛的说,大多数CALayer的属性都是用GPU来绘制。比如如果你设置图层背景或者边框的颜色,那么这些可以通过着色的三角板实时绘制出来。如果对一个contents属性设置一张图片,然后裁剪它 - 它就会被纹理的三角形绘制出来,而不需要软件层面做任何绘制。
但是有一些事情会降低(基于GPU)图层绘制,比如:
- 太多的几何结构 - 这发生在需要太多的三角板来做变换,以应对处理器的栅格化的时候。现代iOS设备的图形芯片可以处理几百万个三角板,所以在Core Animation中几何结构并不是GPU的瓶颈所在。但由于图层在显示之前通过IPC发送到渲染服务器的时候(图层实际上是由很多小物体组成的特别重量级的对象),太多的图层就会引起CPU的瓶颈。这就限制了一次展示的图层个数(见本章后续“CPU相关操作”)。
- 重绘 - 主要由重叠的半透明图层引起。GPU的填充比率(用颜色填充像素的比率)是有限的,所以需要避免重绘(每一帧用相同的像素填充多次)的发生。在现代iOS设备上,GPU都会应对重绘;即使是iPhone 3GS都可以处理高达2.5的重绘比率,并任然保持60帧率的渲染(这意味着你可以绘制一个半的整屏的冗余信息,而不影响性能),并且新设备可以处理更多。
- 离屏绘制 - 这发生在当不能直接在屏幕上绘制,并且必须绘制到离屏图片的上下文中的时候。离屏绘制发生在基于CPU或者是GPU的渲染,或者是为离屏图片分配额外内存,以及切换绘制上下文,这些都会降低GPU性能。对于特定图层效果的使用,比如圆角,图层遮罩,阴影或者是图层光栅化都会强制Core Animation提前渲染图层的离屏绘制。但这不意味着你需要避免使用这些效果,只是要明白这会带来性能的负面影响。
- 过大的图片 - 如果视图绘制超出GPU支持的2048x2048或者4096x4096尺寸的纹理,就必须要用CPU在图层每次显示之前对图片预处理,同样也会降低性能。
CPU相关的操作
大多数工作在Core Animation的CPU都发生在动画开始之前。这意味着它不会影响到帧率,所以很好,但是他会延迟动画开始的时间,让你的界面看起来会比较迟钝。
以下CPU的操作都会延迟动画的开始时间:
- 布局计算 - 如果你的视图层级过于复杂,当视图呈现或者修改的时候,计算图层帧率就会消耗一部分时间。特别是使用iOS6的自动布局机制尤为明显,它应该是比老版的自动调整逻辑加强了CPU的工作。
- 视图懒加载 - iOS只会当视图控制器的视图显示到屏幕上时才会加载它。这对内存使用和程序启动时间很有好处,但是当呈现到屏幕上之前,按下按钮导致的许多工作都会不能被及时响应。比如控制器从数据库中获取数据,或者视图从一个nib文件中加载,或者涉及IO的图片显示(见后续“IO相关操作”),都会比CPU正常操作慢得多。
- Core Graphics绘制 - 如果对视图实现了-drawRect:方法,或者CALayerDelegate的-drawLayer:inContext:方法,那么在绘制任何东西之前都会产生一个巨大的性能开销。为了支持对图层内容的任意绘制,Core Animation必须创建一个内存中等大小的寄宿图片。然后一旦绘制结束之后,必须把图片数据通过IPC传到渲染服务器。在此基础上,Core Graphics绘制就会变得十分缓慢,所以在一个对性能十分挑剔的场景下这样做十分不好。
- 解压图片 - PNG或者JPEG压缩之后的图片文件会比同质量的位图小得多。但是在图片绘制到屏幕上之前,必须把它扩展成完整的未解压的尺寸(通常等同于图片宽 x 长 x 4个字节)。为了节省内存,iOS通常直到真正绘制的时候才去解码图片(14章“图片IO”会更详细讨论)。根据你加载图片的方式,第一次对图层内容赋值的时候(直接或者间接使用UIImageView)或者把它绘制到Core Graphics中,都需要对它解压,这样的话,对于一个较大的图片,都会占用一定的时间。
当图层被成功打包,发送到渲染服务器之后,CPU仍然要做如下工作:为了显示屏幕上的图层,Core Animation必须对渲染树种的每个可见图层通过OpenGL循环转换成纹理三角板。由于GPU并不知晓Core Animation图层的任何结构,所以必须要由CPU做这些事情。这里CPU涉及的工作和图层个数成正比,所以如果在你的层级关系中有太多的图层,就会导致CPU没一帧的渲染,即使这些事情不是你的应用程序可控的。
IO相关操作
还有一项没涉及的就是IO相关工作。上下文中的IO(输入/输出)指的是例如闪存或者网络接口的硬件访问。一些动画可能需要从山村(甚至是远程URL)来加载。一个典型的例子就是两个视图控制器之间的过渡效果,这就需要从一个nib文件或者是它的内容中懒加载,或者一个旋转的图片,可能在内存中尺寸太大,需要动态滚动来加载。
1
IO比内存访问更慢,所以如果动画涉及到IO,就是一个大问题。总的来说,这就需要使用聪敏但尴尬的技术,也就是多线程,缓存和投机加载(提前加载当前不需要的资源,但是之后可能需要用到)。这些技术将会在第14章中讨论。
https://blog.csdn.net/jasonjwl/article/details/52337274
CPU VS GPU的更多相关文章
- 浅谈CPU和GPU的区别
导读: CPU和GPU之所以大不相同,是由于其设计目标的不同,它们分别针对了两种不同的应用场景.CPU需要很强的通用性来处理各种不同的数据类型,而GPU面对的则是类型高度统一的.相互无依赖的大规模数据 ...
- CPU和GPU性能对比
计算20000次10000点的fft,分别使用CPU和GPU,得 the running time of cpu is : 2.3696s the running time of gpu is : 0 ...
- CPU和GPU实现julia
CPU和GPU实现julia 主要目的是通过对比,学习研究如何编写CUDA程序.julia的算法还是有一定难度的,但不是重点.由于GPU实现了也是做图像识别程序,所以缺省的就是和O ...
- 图像重采样(CPU和GPU)
1 前言 之前在写影像融合算法的时候,免不了要实现将多光谱影像重采样到全色大小.当时为了不影响融合算法整体开发进度,其中重采样功能用的是GDAL开源库中的Warp接口实现的. 后来发现GDAL War ...
- CPU和GPU的区别
个人认为CPU和GPU各有自己的适应领域.CPU(Central Processing Unit)计算核心较少,通常是双核.四核.八核,但是拥有大量的共享缓存.预测.乱序执行等优化,可以做逻辑非常复杂 ...
- CPU和GPU的差别
详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt317 首先需要解释CPU和GPU这两个缩写分别代表什么.CPU即中央处理器, ...
- Shader 入门笔记(二) CPU和GPU之间的通信
渲染流水线的起点是CPU,即应用阶段. 1)把数据加载到显存中 2)设置渲染状态,通俗说这些状态定义了场景中的网格是怎样被渲染的. 3)调用DrawCall,一个命令,CPU通知GPU.(这个命令仅仅 ...
- Caffe源码理解2:SyncedMemory CPU和GPU间的数据同步
目录 写在前面 成员变量的含义及作用 构造与析构 内存同步管理 参考 博客:blog.shinelee.me | 博客园 | CSDN 写在前面 在Caffe源码理解1中介绍了Blob类,其中的数据成 ...
- (七) Keras 绘制网络结构和cpu,gpu切换
视频学习来源 https://www.bilibili.com/video/av40787141?from=search&seid=17003307842787199553 笔记 首先安装py ...
- Shader 入门笔记(二) CPU和GPU之间的通信,渲染流水线
渲染流水线 1)应用阶段(CPU处理) 首先,准备好场景数据(摄像机位置,视锥体,模型和光源等) 接着,做粗粒度剔除工作. 最后,设置好每个模型的渲染状态(使用的材质,纹理,shader等) 这一阶段 ...
随机推荐
- 应用二:Vue之ElementUI Form表单校验
(注:本文适用于有一定Vue基础或开发经验的读者,文章就知识点的讲解不一定全面,但却是开发过程中很实用的) 表单校验是前端开发过程中最常用到的功能之一,根据个人的工作经验总结在此对表单校验功能的基 ...
- 如何选择优动漫PAINT版本?是个人版还是EX版
优动漫PAINT也就是我们常说的clip studio paint(CSP)的中文版本,它是一款功能强大的动漫绘图软件,适用于个人和专业团队创作,分为个人版和EX版.搭载了绘制漫画和插画所需的所有功能 ...
- word2016如何英汉互译
1.如果是一篇英文文档且是pdf格式,可以用word2016打开直接转化成了word,就算不是会员也可以的,在此附上16版的光盘安装包,可以百度自行下载 (链接:https://pan.baidu.c ...
- 如何避免命令 rm -rf 的悲剧
一.root高管用户为例,其他用户类同. https://www.cnblogs.com/eos666/articles/10389179.html [root@jenkins /]# vim /ro ...
- 封装自己的jquery框架
jQuery is a fast small JavaScript library 如何封装自己的jQuery <script> // 这里使用沙箱模式,可以防止全局污染 (functio ...
- AOJ 2224 Save your cats( 最小生成树 )
链接:传送门 题意:有个女巫把猫全部抓走放在一个由 n 个木桩(xi,yi),m 个篱笆(起点终点木桩的编号)围成的法术领域内,我们必须用圣水才能将篱笆打开,然而圣水非常贵,所以我们尽量想降低花费来解 ...
- 【Codeforces 276C】Little Girl and Maximum Sum
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 最后的和. 其实可以看成是 ∑bi*ai 的形式. 这里的bi这个系数表示的是有多少个区间覆盖了ai这个元素. 既然这样的话. 那么 ...
- 洛谷——P1115 最大子段和
https://www.luogu.org/problem/show?pid=1115#sub 题目描述 给出一段序列,选出其中连续且非空的一段使得这段和最大. 输入输出格式 输入格式: 输入文件ma ...
- POJ 2133
类似于DP一样做,但这题有个大坑,自己看DIS吧.... #include <iostream> #include <cstdio> #include <cstring& ...
- Android中XML解析,保存的三种方法
简单介绍 在Android开发中,关于XML解析有三种方式,各自是: SAX 基于事件的解析器.解析速度快.占用内存少.非常适合在Android移动设备中使用. DOM 在内存中以树形结构存放,因此检 ...