Version: 6000.3
语言: 中文
线程安全类型
实现自定义本机容器

NativeContainer 简介

NativeContainer是本机内存的线程安全 C# 包装器。NativeContainer对象还允许作业访问与主线程共享的数据,而不是使用副本。

NativeContainers 的类型

Unity.Collections命名空间包含以下内置NativeContainer对象:

  • NativeArray:向托管代码公开本机内存缓冲区的非托管数组
  • NativeSlice:获取NativeArray从特定位置到一定长度。

注意:Collections 包包含额外的NativeContainers.有关其他类型的完整列表,请参阅有关集合类型的集合文档

读写访问权限

默认情况下,当作业有权访问NativeContainer实例,它同时具有读取和写入访问权限。此配置可能会降低性能。这是因为作业系统不允许您计划对NativeContainer实例与写入它的另一个作业同时。

但是,如果作业不需要写入NativeContainer实例中,您可以标记NativeContainer使用[ReadOnly]属性,如下所示:

[ReadOnly]
public NativeArray<int> input;

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

内存分配器

当您创建NativeContainer实例中,必须指定所需的内存分配类型。您使用的分配类型取决于您希望将本机容器保留多长时间。通过这种方式,您可以定制分配,以便在每种情况下获得最佳性能。

有三种分配器类型NativeContainer内存分配和释放。在实例化NativeContainer实例:

  • Allocator.Temp:最快的分配。将其用于生命周期为一帧或更短的分配。您不能使用Temp将分配传递给NativeContainer实例存储在作业的成员字段中。
  • Allocator.TempJob:分配速度慢于Temp但比Persistent.在四帧的生命周期内将其用于线程安全分配。重要提示:您必须Dispose此分配类型,否则控制台会打印从本机代码生成的警告。大多数小型作业都使用此分配类型。
  • Allocator.Persistent:最慢的分配,但可以持续到您需要的时间,并在必要时持续整个应用程序的生命周期。它是直接调用malloc.较长的作业可以使用此 NativeContainer 分配类型。不要使用Persistent性能至关重要的地方。

例如:

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

注意:上面示例中的数字 1 表示 NativeArray 的大小。在这种情况下,它只有一个数组元素,因为它只在其结果中存储一条数据。

NativeContainer 安全系统

安全系统内置于所有NativeContainer实例。它跟踪读取或写入任何内容NativeContainer实例,并使用该信息来执行有关使用NativeContainers 使它们在多个作业和线程中以确定性的方式行事。

例如,如果两个独立的计划作业写入同一NativeArray,这是不安全的,因为您无法预测哪个作业首先执行。这意味着您将不知道哪些作业将覆盖来自另一个作业的数据。当您计划第二个作业时,安全系统会抛出一个异常,并显示一条明确的错误消息,解释为什么以及如何解决问题。

如果要调度两个写入同一的作业NativeContainer实例中,您可以计划具有依赖项的作业。第一个作业写入NativeContainer,一旦它完成执行,下一个作业就会安全地读取和写入相同的作业NativeContainer.引入依赖关系可保证作业始终以一致的顺序执行,并且NativeContainer是确定性的。

安全系统允许多个作业并行读取相同的数据。

这些读写限制也适用于从主线程访问数据时。例如,如果尝试在写入 NativeContainer 的作业完成之前读取 NativeContainer 的内容,则安全系统会引发错误。同样,如果尝试写入 NativeContainer,而仍有读取或写入的挂起作业,则安全系统也会引发错误。

此外,由于 NativeContainers 没有实现ref return,则不能直接更改NativeContainer.例如nativeArray[0]++;和写作一样var temp = nativeArray[0]; temp++;它不会更新nativeArray.

相反,您必须将数据从索引复制到本地临时副本中,修改该副本,然后将其保存回来。例如:

MyStruct temp = myNativeArray[i];
temp.memberVariable = 0;
myNativeArray[i] = temp;

其他资源

线程安全类型
实现自定义本机容器