데이터 복사의 안전 시스템 프로세스에 대한 단점은 잡의 결과가 각 복사본 내에 격리된다는 것입니다. 이러한 제한을 극복하려면 결과를 NativeContainer라고 불리는 공유 메모리 타입에 저장해야 합니다.
NativeContainer
는 네이티브 메모리에 안전한 C# 래퍼를 제공하는 관리되는 값 타입입니다. 여기에는 관리되지 않는 할당에 대한 포인터가 들어 있습니다. Unity C# 잡 시스템과 함께 NativeContainer
를 사용하면 잡이 복사본으로 작업하는 것이 아니라 메인 스레드와 공유되는 데이터에 액세스할 수 있습니다.
Unity는 NativeArray라고 불리는 NativeContainer
와 함께 제공됩니다. 또한 NativeSlice로 NativeArray
를 조작하여 특정 포지션에서 NativeArray
의 하위 집합을 특정 길이로 가져올 수도 있습니다.
참고: 엔티티 컴포넌트 시스템(ECS) 패키지는 다른 타입의 NativeContainer
를 포함하도록 Unity.Collections
네임스페이스를 확장합니다.
NativeList
- 크기 변경이 가능한 NativeArray
입니다.NativeHashMap
- 키 및 값 쌍입니다.NativeMultiHashMap
- 키당 여러 개의 값입니다.NativeQueue
- 선입선출(FIFO) 대기열입니다.안전 시스템은 모든 NativeContainer
타입에 내장되어 있으며, NativeContainer
에 대한 읽기/쓰기 작업을 추적합니다.
참고: NativeContainer
타입에 대한 모든 안전 검사(예: 한도 검사, 할당 취소 검사, 경쟁 상태 검사)는 Unity Editor 및 Play mode 에서 이용할 수 있습니다.
안전 시스템에는 DisposeSentinel과 AtomicSafetyHandle도 포함되어 있습니다. DisposeSentinel
은 메모리 누수를 검사한 후 메모리를 잘못 할당한 경우 오류를 표시합니다. 메모리 누수 오류에 대한 트리거는 누수 후 오랜 시간이 지난 다음에 일어납니다.
AtomicSafetyHandle
을 사용하면 코드로 NativeContainer
의 소유권을 이전할 수 있습니다. 예를 들어, 두 개의 예약된 잡이 동일한 NativeArray
에 작성하면 안전 시스템에서 예외가 발생하고 문제에 대한 이유 및 해결 방법을 설명하는 오류 메시지를 표시합니다. 문제가 되는 잡을 예약하면 안전 시스템에서 예외가 발생합니다.
이 경우 종속성을 사용하여 잡을 예약할 수 있습니다. 첫 번째 잡은 NativeContainer
에 작성하고, 실행이 완료되면 다음 잡이 동일한 NativeContainer
에 안전하게 작성하고 읽을 수 있습니다. 이러한 읽기/쓰기 제한은 메인 스레드에서 데이터에 액세스할 때도 적용됩니다. 안전 시스템을 사용하면 여러 작업이 동일한 데이터에서 병렬로 읽을 수 있습니다.
기본적으로 잡이 NativeContainer
에 대한 액세스 권한을 가진 경우 읽기와 쓰기 모두를 수행할 수 있습니다. 이러한 설정은 성능 저하를 야기할 수 있습니다. C# 잡 시스템은 NativeContainer
에 작성 중인 잡이 있을 때는 다른 잡에 쓰기 권한을 허용하지 않습니다.
잡이 NativeContainer
에 작성할 필요가 없다면 [ReadOnly]
속성을 사용하여 다음과 같이 NativeContainer
를 표시합니다.
[ReadOnly]
public NativeArray<int> input;
위 예에서는 첫 번째 NativeArray
에 대한 읽기 전용 액세스 권한이 있는 다른 잡과 동시에 잡을 실행할 수 있습니다.
참고: 잡 내에서 정적 데이터에 대한 액세스는 보호되지 않습니다. 정적 데이터에 액세스하면 모든 안전 시스템을 우회하므로 Unity에 크래시가 발생할 수 있습니다. 자세한 내용은 C# 잡 시스템 팁 및 문제 해결을 참조하십시오.
NativeContainer
를 만들 때는 필요한 메모리 할당 타입을 지정해야 합니다. 할당 타입은 잡 실행 시간에 따라 다릅니다. 이렇게 하면 할당을 맞춤 설정하여 각 상황에서 최고의 성능을 끌어낼 수 있습니다.
NativeContainer
메모리 할당 및 릴리스에는 세 가지의 할당자 타입을 이용할 수 있습니다. NativeContainer
를 인스턴스화할 때 적절한 타입을 지정해야 합니다.
NativeContainer
할당을 잡에 전달하기 위해 Temp
를 사용할 수는 없습니다.Temp
보다 할당 속도가 더 느리지만 Persistent
보다는 속도가 더 빠릅니다. 4프레임 내의 스레드 세이프 할당에 사용합니다. 중요: 이러한 타입의 할당은 반드시 4프레임 내에서 Dispose
메서드를 호출해야 합니다. 그렇지 않으면 콘솔은 네이티브 코드에서 생성된 경고를 출력합니다. 대부분의 소규모 잡은 이러한 NativeContainer
할당 타입을 사용합니다.NativeContainer
할당 타입을 사용할 수 있습니다. 성능이 중요한 상황에서는 Persistent
를 사용하면 안 됩니다.예제:
NativeArray<float> result = new NativeArray<float>(1, Allocator.TempJob);
참고: 위 예제에서 숫자 1은 NativeArray
의 크기를 나타냅니다. 이 경우에는 하나의 배열 요소만 보유하고 있습니다(하나의 데이터 조각만 result
에 저장하기 때문).