CPU&GPU

CPU 和 GPU的区别

CPU精通复杂任务和串行计算,控制逻辑复杂

GPU精通简单任务和并行计算,数据吞吐量大

像渲染相关的工作常常交给GPU是因为一个屏幕动辄几百万个像素,需要的是简单任务的大量计算。

​ CPU和GPU的架构(示意图):

img

  图片来自nVidia CUDA文档。其中绿色的是计算单元,橙红色的是存储单元,橙黄色的是控制单元。

硬件渲染(硬件加速)

Android通过hardwareAccelerated=”true”开启硬件渲染,(API >= 14 默认开启)

软件渲染

  1. 软件渲染会使 invalidate() 方法需要从最上层开始都要进行重绘

硬件渲染

  1. 硬件渲染会收集被invalidate()标记为dirty的视图(View.isDirty()),之后只对这些dirty的区域进行重绘

  2. 硬件渲染将一些复杂的绘制操作从主线程(UI Thread)转移到渲染线程( Render Thread )中进行,减少 UI 线程的工作量,具体为:

    同步Display List;canvas 的命令转换为 OpenGL ;Gpu处理数据;layer合成;光栅化;swap buffer; (简单来讲就是)

    image-20250123155708178

RV的Prefetch机制

简单而言,prefetch机制是在 DisplayList构建并sync到renderThread之后。此时UI Thread完成了它的工作,处于空闲状态。

rv通过在此时于此帧中的UI Thread进行preFetch下一个ViewHolder的Create和Bind操作。

而针对RV嵌套RV(都是LinearLayoutManager)的情况,默认预取数量是2,可以通过LinearLayoutManager.setInitialPrefetchItemCount设置横向RV的预取数量。

preFetch会被限制在下一帧(deadline)到来之前完成,

如果完成了,则将ViewHolder对象缓存到mCacheViews,

如果未完成但已经获取到了ViewHolder,则将ViewHolder移到mRecyclerViewPool中。

预抓取的工作必须在下一个垂直同步信号发出之前,也即下一帧开始绘制之前完成

img

但这里有一个问题。

当UI线程提前完成工作,并将一个帧传递给RenderThread渲染之后,就会进入所谓的「休眠状态」,出现了大量的空闲时间,直至下一帧开始绘制之前。如图所示:

img

一方面,这些UI线程上的空闲时间并没有被利用起来,相当于珍贵的线程资源被白白浪费掉;

另一方面,新的列表项进入屏幕时,又需要在UI线程的输入阶段(Input)就完成视图创建与数据绑定的工作,这会推迟UI线程及RenderThread上的其他工作,如果这些被推迟的工作无法在下一帧开始绘制之前完成,就有可能造成界面上的丢帧卡顿。

GapWorker正是选择在此时间窗口内安排预拉取的工作,也即把创建和绑定的耗时操作,移到UI线程的空闲时间内完成,与原先的RenderThread并行执行

img

Author

white crow

Posted on

2025-01-23

Updated on

2025-01-24

Licensed under