Unity NativeContainer

英文原文:
https://docs.unity3d.com/Manual/JobSystemNativeContainer.html

  安全系统复制数据过程的缺点是,它还隔离了每个副本中的Job结果。要克服这一限制,您需要将结果存储在一种名为NativeContainer的共享内存中。

什么是NativeContainer?

  NativeContainer是一种托管值类型,它为本机内存提供了相对安全的C#包装。它包含指向非托管分配的指针。当与Unity C# JobSystem一起使用时,NativeContainer允许Job访问与主线程共享的数据,而不是使用副本。

有哪些类型的NativeContainer可用?

  Unity附带一个名为NativeArray的NativeContainer。还可以使用NativeSlice操作NativeArray,以获取从特定位置到特定长度的NativeArray的子集。

注意实体组件系统(ECS)包扩展了Unity.Collects命名空间,以包括其他类型的NativeContainer:

  • NativeList - 可调整大小的NativeArray。
  • NativeHashMap - 键和值对。
  • NativeMultiHashMap - 每个键多个值。
  • NativeQueue-先进先出(FIFO)队列。

NativeContainer和安全系统

  安全系统内置于所有NativeContainer类型中。它跟踪正在读取和写入任何NativeContainer的内容。

  注意:NativeContainer类型的所有安全检查(如越界检查、释放检查和竞争条件检查)仅在Unity Editor和Play模式下可用。

  这个安全系统的一部分是DisposeSentinel和AtomicSafetyHandle。DisposeSentinel会检测内存泄漏,如果您没有正确释放内存,它会给您一个错误。触发内存泄漏错误发生在泄漏发生很久之后。

  使用AtomicSafetyHandle在代码中转移NativeContainer的所有权。例如,如果两个scheduled jobs写入同一个NativeArray,则安全系统会抛出异常,并显示一条清晰的错误消息,解释问题的原因和解决方法。当您安排违规作业时,安全系统会抛出此异常。

  在这种情况下,您可以计划具有依赖项的Job。第一个Job可以写入NativeContainer,一旦完成执行,下一个Job就可以安全地读写同一个NativeContainer。当从主线程访问数据时,读写限制也适用。安全系统确实允许多个Job并行读取相同的数据。

  默认情况下,当Job有权访问NativeContainer时,它同时具有读写访问权限。此配置可能会降低性能。C# Job系统不允许您调度对NativeContainer具有写访问权限的Job,同时调度另一个正在写入它的Job。

  如果作业不需要写入NativeContainer,请使用[ReadOnly]属性标记NativeContainer,如下所示:

[ReadOnly]
public NativeArray<int> input;

  在上面的示例中,您可以与对第一个NativeArray也具有只读访问权限的其他Job同时执行该Job。

注意:没有针对从Job内访问静态数据的保护。访问静态数据会绕过所有安全系统,可能会使Unity崩溃。有关更多信息,请参见C#作业系统提示和故障排除。

NativeContainer分配器

  创建NativeContainer时,必须指定所需的内存分配类型。分配类型取决于Job运行的时间长度。这样,您就可以调整分配,以便在每种情况下都能获得最佳性能。

  NativeContainer内存分配和释放有三种分配器类型。实例化NativeContainer时,需要指定适当的参数。

  • Allocator.Temp 的分配速度最快。它适用于寿命为一帧或更短的分配。不应使用TEMP将NativeContainer分配传递给Job。在从方法调用(如MonoBehaviour.Update或从本机代码到托管代码的任何其他回调)返回之前,还需要调用Dispose方法。

  • Allocator.TempJob的分配速度比Temp慢,但比Persistent快。它用于在四个帧的生命周期内进行分配,并且是线程安全的。如果您没有在四个帧内处理它,控制台将打印一个从本机代码生成的警告。大多数小型Job都使用此NativeContainer分配类型。

  • Allocator.Persistent是最慢的分配,但只要您需要,它可以持续多久,如果需要,也可以持续整个应用程序的生命周期。它是对malloc的直接调用的包装器。较长的Job可以使用此NativeContainer分配类型。在性能至关重要的情况下,不应使用持久性。

示例:

NativeArray<float> result = new NativeArray<float>(1, Allocator.TempJob);

注意:上例中的数字1表示NativeArray的大小。在本例中,它只有一个数组元素(因为它在Result中只存储一段数据)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值