为什么需要NativeArray来获取Unity作业系统的返回值?

Jee*_*Jee 5 c# parallel-processing jobs unity-container unity-game-engine

使用下面的代码块作为参考,一次更新可提供以下结果:

intReturn = 0

inputArrayReturn = 1

internalArrayReturn = 1

这里对我来说唯一有意义的值是internalArrayReturn.

为什么不intReturn等于1?即使在执行过程中应该将 1 添加到结构中,但到底发生了什么导致该结构的值没有改变?如果这只是 NativeArray 和 int 之间的根本区别,有人可以解释一下或给我指出一个参考资料来帮助我更好地理解这一点吗?

另外,为什么不inputArrayReturn等于0? NativeArray是一个结构体,所以当该行执行时它不应该被视为值的副本而不是引用吗testArray = testArrayResults?如果是这种情况,则 theninputArrayReturn将保持等于 0,而不是更新为 中包含的相同值testJob.testArray

using UnityEngine;
using Unity.Jobs;
using Unity.Collections;

public class ParallelTesting : MonoBehaviour
{
    void Update()
    {
        NativeArray<int> testArrayResults = new NativeArray<int>(1, Allocator.TempJob);

        TestJob testJob = new TestJob
        {
            testInt = 0,
            testArray = testArrayResults
        };

        JobHandle testJobHandle = testJob.Schedule();
        testJobHandle.Complete();

        int intReturn = testJob.testInt;
        int inputArrayReturn = testArrayResults[0];
        int internalArrayReturn = testJob.testArray[0];

        testArrayResults.Dispose();
    }

    public struct TestJob : IJob
    {
        public int testInt;
        public NativeArray<int> testArray;

        public void Execute()
        {
            testInt += 1;
            testArray[0] = testInt;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

der*_*ugo 4

没有专家,但我想说的NativeArray是专门设计用于线程保存,基本上是 Unity 主线程和作业系统/运行程序之间的共享内存。

是的NativeArray,它是一个结构体,但实际上,如果您查看源代码,它基本上只是一个包装器,其中包含指向内存中实际本机缓冲区的指针。

    public unsafe struct NativeArray<T> : IDisposable, IEnumerable<T>, IEquatable<NativeArray<T>> where T : struct
    {
        [NativeDisableUnsafePtrRestriction]
        internal void*                    m_Buffer;
        internal int                      m_Length;

        internal int                      m_MinIndex;
        internal int                      m_MaxIndex;
        
        ...
Run Code Online (Sandbox Code Playgroud)

这就是为什么两者

int inputArrayReturn = testArrayResults[0];
int internalArrayReturn = testJob.testArray[0];
  
Run Code Online (Sandbox Code Playgroud)

通过相同的指针访问相同的外部存储器,因此返回相同且正确的值。

然而, “正常”int不一定是线程安全的,因为它没有分配外部内存(请参阅堆和堆栈),并且您的 Unity 主线程不知道作业在不同的线程/核心上时在内部更改了它的值。