Unity DOTS Jobs下调用引用类型
2019-06-07 08:59
155 查看
版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/buxingynjian225/article/details/91125619
Unity DOTS架构JobSystem的扩展
前言
Unity 官方计划 未来 会全面转入ECS+ Jobs +Burst 的DOTS架构. 但事实上这三个子系统是相互彼此独立的.换句话说,你可以单独选择使用某部分,而不必全部使用.在这里将探讨Job系统背后的细节.官方文档 把Jobs系统描述 为一个只能使用值类型的多线程系统.背后又是如何实现的呢?用一句话归纳说:Jobs系统其实是用C++实现的一个线程池.因为是非委托的实现.所以C#的对象锁的概念将不再可用.这意味着全部的引用类型 在多线程同时读写的时候会因为相互干扰而破坏数据.Unity官方为回避这个问题,仅使用值类型,而抛弃了全部引用类型. 值类型因为只是源数据的一个副本,对其做的任何修改 是不会修改源数据的,利用这个特性,在空间上可以完美隔离多线程的资源竞争,并且提升性能.Jobs为仅支持值类型可用,特别实现一套类型安全检查,旨在排除引用类型的错误使用.但事实上如果在多线程执行期间只做引用类型读写操作的话并非会构成任何问题. 于是有人想过使用静态成员变量绕过该安全检查,以期望在Jobs系统中调用引用类型.
我使用UnsafeUtility的方法编写JobAction值类型包装Action委托,可以绕开这个安全检查达到同样的目的,这是Jobs系统可以执行引用类型上下文的第二条有效方法,并且更加灵活.(注意,使用完毕之后需要Dispose是否资源)
以下列出几种异步方法表格用于对比相互优势取舍:
Unity的异步方法
C#代码端Coroutine协程迭代器方法单线程上下文包装Thead 手动构建多线程指令Task/Async/AwaitTask委托线程池IJob/IJobParallelForJobs非委托线程池Unity异步方法优势对比:
Coroutine协程 | Thread线程 | Task多线程 | Jobs多线程 | Jobs多线程 中使用JobAction |
---|---|---|---|---|
主线程仅切换上下文,不使用多线程 | 手动创建销毁线程,切换效率低.拥有对象锁,可能因资源竞争等待而降低效率 | 线程池调度多线程,切换效率高,拥有对象锁,可能因资源竞争等待而降低效率 | 非托管代码线程池调度多线程,没有对象锁,无资源竞争等待,充分使用多线程,只能使用值类型数据, | 非托管代码线程池调度多线程,没有对象锁,无资源竞争等待,充分使用多线程.可以使用引用类型和值类型,同时读写引用类型数据会相互干扰导致数据错误. |
JobAction 实现
using Unity.Collections.LowLevel.Unsafe; using System; public unsafe struct VJobAction :IDisposable { [NativeDisableUnsafePtrRestriction] private void* m_Ptr; private ulong m_Handle; public VJobAction(Action aCallback) { var aArr = new Action[] { aCallback }; m_Ptr = UnsafeUtility.PinGCArrayAndGetDataAddress(aArr, out m_Handle); } public void Invoke() { Callback?.Invoke(); } /// <summary> /// 回调函数. /// </summary> public Action Callback { get { return UnsafeUtility.ReadArrayElement<Action>(m_Ptr, 0); } set { Dispose(); var aArr = new Action[] { value }; m_Ptr = UnsafeUtility.PinGCArrayAndGetDataAddress(aArr, out m_Handle); } } public void Dispose() { if (m_Handle != 0) { UnsafeUtility.ReleaseGCObject(m_Handle); m_Ptr = (byte*)0; m_Handle = 0; } } public static implicit operator Action (VJobAction aCallback) { return aCallback.Callback; } public static explicit operator VJobAction( Action aCallback) { return new VJobAction(aCallback); } }
相关文章推荐
- Unity 5.0 无法通过GUIText类型在脚本中调用画布中的text文字
- C++关于参数为const引用类型的函数调用参数成员函数的一个问题
- 蓝鸥Unity开发基础——值类型和引用类型
- C++函数调用何时用引用类型
- 函数的调用-基本数据类型/引用类型
- [cnblogs镜像]Unity脚本中可以引用的类型
- 反射技术动态调用方法中的引用类型参数传递 (转)
- 17.2015.08.04第十八节课 C#2 (数值类型及调用、引用类型及调用、装拆箱、常量、变量、数据类型转换、算术运算符、赋值运算符、关系运算符、逻辑运算符、字符串的常用方法)
- java基本数据类型和引用数据类型的调用传递的区别
- 关于实现引用类型数组去调用引用类的方法的问题的解决
- Unity脚本中可以引用的类型
- 对象的引用调用private类型函数的问题
- C# 值类型传参与引用类型传参 在多线程调用时的区别
- 被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法
- Unity 5.0 无法通过GUIText类型在脚本中调用画布中的Text文字
- C# 值类型传参与引用类型传参 在多线程调用时的区别
- .net反射调用值类型引用参数时的处理办法(转)
- ajax调用webservice返回DataTable "序列化类型为“System.Reflection.Module”的对象时检测到循环引用
- 基本类型和引用类型调用是的区别(Object.create)
- js的基础(平民理解的执行上下文/调用堆栈/内存栈/值类型/引用类型)