Unity-多核优化1-C#JobSystem

梦想游戏人
目录:
Unity

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();
    }
}
Scroll Up