Unity3D :线程安全类型

推荐:将NSDT场景编辑器加入你的3D工具链
3D工具集:NSDT简石数字孪生

线程安全类型

作业系统在与突发编译器一起使用时效果最佳。由于 Burst 不支持托管对象,因此需要使用非托管类型来访问作业中的数据。您可以使用可 blitable 类型执行此操作,也可以使用 Unity 的内置 NativeContainer 对象,这些对象是用于本机内存的线程安全 C# 包装器。 对象还允许作业访问与主线程共享的数据,而不是使用副本。NativeContainer

本机容器的类型

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

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

注意:集合包包含其他 s。有关其他类型的完整列表,请参阅有关集合类型的集合文档。NativeContainer

读写访问权限

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

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

[ReadOnly]
public NativeArray<int> input;

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

内存分配器

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

内存分配和释放有三种分配器类型。实例化实例时,必须指定适当的实例:NativeContainerNativeContainer

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

例如:

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

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

原生集装箱安全系统

安全系统内置于所有实例中。它跟踪读取或写入任何实例的内容,并使用该信息对 s 的使用强制执行某些规则,使它们在多个作业和线程中以确定性的方式运行。NativeContainerNativeContainerNativeContainer

例如,如果两个独立的计划作业写入同一个 ,这是不安全的,因为您无法预测哪个作业首先执行。这意味着您将不知道哪个作业将覆盖另一个作业的数据。当您计划第二个作业时,安全系统会抛出一个带有明确错误消息的异常,说明解决问题的原因和方法。NativeArray

如果要计划写入同一实例的两个作业,可以使用依赖项计划这些作业。第一个作业写入 ,一旦完成执行,下一个作业将安全地读取和写入相同的 。引入依赖关系可保证作业始终以一致的顺序执行,并且 中生成的数据是确定性的。NativeContainerNativeContainerNativeContainerNativeContainer

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

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

此外,由于 NativeContainers 不实现 ref 返回,因此您无法直接更改 .例如, 与不更新 中的值的写入相同。NativeContainernativeArray[0]++;var temp = nativeArray[0]; temp++;nativeArray

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

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

3D建模学习工作室整理翻译,转载请注明出处!

上一篇:Unity3D :什么是多线程? (mvrlink.com)

下一篇:Unity3D :实现自定义本机容器 (mvrlink.com)

NSDT场景编辑器 | NSDT 数字孪生 | GLTF在线编辑器 | 3D模型在线转换 | UnrealSynth虚幻合成数据生成器 | 3D模型自动纹理化工具
2023 power by nsdt©鄂ICP备2023000829号