Job System概述

Job System概述


前言

最近查漏补缺,稍微学习一下Job System的理念。在此作下记录。


背景

目前大部分游戏和应用都只使用单核,Job System出现的目的就在于允许游戏尽可能使用可使用的CPU核,从而并行加速运行游戏。更具体地说,使用多核可以在不优化thread-time(CPU指令用于计算的时间)的情况下减少wall-time(一个任务从开始到结束的时间)。


优势

使用Job System来减少wall-time最简单的方法就是使用ParallelFor jobs。一个ParallelFor job被用于处理大量以相同方式处理的数据。

本质上,在Job System中,每个在队列中等待被处理的item都是通过job来进行处理的,每个job可以使用CPU多核并行地处理。

实际上,job的数量远小于要处理item的数量,每个job对应一个CPU核对应多个item。当某个job处理完它自己所有的item后,如果还有其他job没有处理完item,就会去监听其他job并且协助处理剩余的item。

Job System概述_第1张图片


如果系统中有非常多相似的item,那ParallelFor会非常地管用。即使系统中没有那么多相似的item,使用Job System的设计方式也能让系统由单一不可分割的整体分成多个可自行运作的小单元(即job),让每个CPU核拥有处理job的线程,并行地处理这些job。只要item之间不相互依赖,我们所需要做的就只有合理调度job处理这些item,让job无需等待,效率拉满!

Job System概述_第2张图片


理念

“要么早开始,要么晚完成”。

很多时候,使用Job System时提倡一种“Schedule early, complete late”的概念,翻译过来就是“要么早点调度job,要么晚点完成job”。这种“要么早开始,要么晚完成”的模式目的就是为了保证主线程无需等待job完成。当主线程需要job处理完成的结果时,可以直接获取结果,因为理论上该job应该已经处理完成了(最理想的情况)。

实际上我们需要给job足够的时间来处理item。对于每个job来说,我们可以不用考虑什么时候开始或完成,前提是我们保证job从开始到完成的时间足够。为了让job运行的时间足够,如果我们可以允许一帧延迟,甚至可以在下一帧来完成job。

每当我们在profiler中发现主线程在等待,我们就需要考虑主线程在等待的是什么,以及我们是否可以调度job让它运行地更早或者完成地更晚来避免主线程等待。


注意

Job System不是被设计用于长时间处理低优先级任务的,也不是被设计用于通过等待来避免抢占CPU资源的。所以说如果我们在使用Job System的时候出现了这样的问题,那么说明我们并没有合理地使用好Job System。

每个Job System的工作线程都会绑定一个CPU核(物理/虚拟)。所以一旦当线程开始处理job,job就会满核一直运行直到完成。


使用

C#提供了一种简单且安全的Job System。简单是C#提供了对应的接口可以快速job化代码;安全是C#在Job System的底层做了线程安全处理。

除此之外,Job System、ECS和Burst三者结合使用,可以极大化地提升运行性能。ECS是一种面向数据的框架,致力于通过将数据组织成cache-friendly以减少计算从而减少thread-time;而Burst则致力于通过优化代码从而减少thread-time。所有的这些策略都是为了解决大量计算所带来的性能问题。


后记

上面的内容是参考资料+自身理解所形成的记录,由于暂时缺乏自身的实践,所以很多实际使用上会出现的问题和坑没有遇到。


参考

https://blog.unity.com/technology/what-is-a-job-system

你可能感兴趣的:(Unity3D技术分享,多线程,unity,unity3d)