Unity-多核优化1-C#JobSystem
JobSystem在旧版本中只是在C++ native层,供unity内部使用,unity2018中把这个功能开放给了managed层 c#使用,
再加上burst编译器,能够在C#层更容易编写出多线程的代码。
官方指引文档 https://docs.unity3d.com/Manual/JobSystem.html
1.通过拷贝和只读等手段,避免竞争。
2.提出NativeContainer 来解决多线程数据交互解决方案。
A ParallelFor job dividing batches across cores
JobSystem的一些注意事项:https://docs.unity3d.com/Manual/JobSystemTroubleshooting.html
1.Do not access static data from a job
2.Flush scheduled batches
由于发起调度是在主线程,比如在循环里面大量发起schedule 那么已经被schedule的job就要等待循环结束后才能执行,从这方面来说如果主线程有大量计算的话,反而加大了延迟 可用 JobHandle.ScheduleBatchedJobs,来立刻执行,而不用等到Complete调用才执行。
3.Don’t try to update NativeContainer contents
4.Call JobHandle.Complete to regain ownership
5.Use Schedule and Complete in the main thread
6.Use Schedule and Complete at the right time
7.Mark NativeContainer types as read-only
8.Do not allocate managed memory in jobs
JobSystem 提升性能示例
开启jobsystem 帧数稳定在60FPS左右(CPU使用率68%) 关闭的话帧数在20FPS(CPU使用率 13%) 左右
using System.Collections; using System.Collections.Generic; using UnityEngine; using Unity.Jobs; using Unity.Jobs.LowLevel.Unsafe; using Unity.Collections; using Unity.Transforms; using UnityEngine.Jobs; public struct Job3 : IJobParallelForTransform { // public NativeArray<int> result;//ref // public Job3()//NativeArray<int> result) //{ // this.result = result; //} public void Execute(int index, TransformAccess transform) { //calc operation { var rot = Quaternion.LookRotation(Vector3.forward); for (int i = 0; i < 256; i++) { rot = Quaternion.LookRotation(Vector3.forward); } transform.rotation = Quaternion.LookRotation(Vector3.forward); transform.position = Vector3.one; } // Debug.LogError(System.Threading.Thread.CurrentThread.ManagedThreadId + " " + index); } } public class Test1 : MonoBehaviour { public List<GameObject> _list = new List<GameObject>(); public GameObject prototype; TransformAccessArray result; void t3() { //use job system var j1 = new Job3(); var handle = j1.Schedule(result); //wait for job done handle.Complete(); //do in main thread /* foreach (var p in _list) { p.transform.position += Vector3.one; p.transform.rotation = Quaternion.LookRotation(Vector3.forward); var rot = Quaternion.LookRotation(Vector3.forward); for (int i = 0; i < 256; i++) { rot = Quaternion.LookRotation(Vector3.forward); } }*/ } void Start() { const int len = 1024; TransformAccessArray.Allocate(len, len, out result); for (int i = 0; i < len; i++) { _list.Add(GameObject.Instantiate<GameObject>(prototype)); result.Add(_list[i].transform); } } void Update() { t3(); } }