Version: Unity 6.0 (6000.0)
언어 : 한국어
Thread safe types
커스텀 네이티브 컨테이너 구현

스레드 세이프 유형

잡 시스템은 버스트 컴파일러와 함께 사용할 때 가장 잘 작동합니다. 버스트는 관리되는 오브젝트를 지원하지 않으므로 관리되지 않는 유형을 사용하여 잡의 데이터에 액세스해야 합니다. 이 작업은 블리터블 유형을 사용하거나 네이티브 메모리에 대한 스레드 세이프 C# 래퍼인 Unity의 빌트인 NativeContainer 오브젝트를 사용하여 수행할 수 있습니다. 또한 NativeContainer 오브젝트를 사용하면 잡이 복사본으로 작업하는 대신 메인 스레드와 공유되는 데이터에 액세스할 수 있습니다.

NativeContainers 유형

Unity.Collections 네임스페이스에는 다음과 같은 빌트인 NativeContainer 오브젝트가 포함되어 있습니다.

  • NativeArray: 네이티브 메모리의 버퍼를 관리되는 코드에 노출하는 관리되지 않는 배열
  • NativeSlice: 특정 위치에서 특정 길이로 NativeArray의 하위 집합 가져오기

참고: Collections 패키지에는 추가 NativeContainer가 포함되어 있습니다. 추가 유형의 전체 리스트는 컬렉션 유형에 대한 컬렉션 기술 자료를 참조하십시오.

읽기 및 쓰기 액세스

기본적으로 잡이 NativeContainer 인스턴스에 액세스할 수 있는 경우 읽기 및 쓰기 권한이 있습니다. 이러한 설정으로 인해 성능이 저하될 수 있습니다. 이는 잡 시스템이 NativeContainer 인스턴스에 쓰기 액세스 권한이 있는 잡을 해당 인스턴스에 쓰고 있는 다른 잡과 동시에 예약할 수 없기 때문입니다.

하지만 잡이 NativeContainer 인스턴스에 작성하지 않아도 된다면 [ReadOnly] 속성을 사용하여 다음과 같이 NativeContainer를 표시할 수 있습니다.

[ReadOnly]
public NativeArray<int> input;

위 예에서는 첫 번째 NativeArray에 대한 읽기 전용 액세스 권한이 있는 다른 잡과 동시에 잡을 실행할 수 있습니다.

메모리 할당자

NativeContainer 인스턴스를 생성할 때 필요한 메모리 할당 유형을 지정해야 합니다. 사용하는 할당 유형은 네이티브 컨테이너를 유지할 수 있는 기간에 따라 다릅니다. 이렇게 하면 할당을 커스터마이즈하여 각 상황에서 최상의 성능을 얻을 수 있습니다.

NativeContainer 메모리 할당 및 릴리스를 위한 세 가지 할당자 유형이 있습니다. NativeContainer 인스턴스를 인스턴스화할 때 적절한 할당자를 지정해야 합니다.

  • Allocator.Temp: 가장 빠른 할당입니다. 수명이 1프레임 이하인 할당에 사용합니다. 잡의 멤버 필드에 저장된 NativeContainer 인스턴스에 할당을 전달하기 위해 Temp를 사용할 수 없습니다.
  • Allocator.TempJob: Temp보다 느리지만 Persistent보다 빠른 할당입니다. 4프레임의 수명 내에서 스레드 세이프 할당에 사용합니다. 중요: 4프레임 이내에 이 할당 유형을 Dispose해야 합니다. 그렇지 않으면 콘솔이 네이티브 코드에서 생성된 경고를 출력합니다. 대부분의 소규모 잡은 이 할당 유형을 사용합니다.
  • Allocator.Persistent: 할당 속도가 가장 느리지만, 필요할 경우 애플리케이션의 수명 기간 동안 필요한 만큼 오래 사용할 수 있습니다. malloc에 대한 직접 통화를 위한 래퍼입니다. 더 긴 잡은 이 NativeContainer 할당 유형을 사용할 수 있습니다. 성능이 필수적인 경우에는 Persistent를 사용하지 마십시오.

예시:

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

참고: 위 예시의 숫자 1은 NativeArray의 크기를 나타냅니다. 이 경우 결과에 하나의 데이터 조각만 저장하므로 배열 요소가 하나뿐입니다.

NativeContainer 안전 시스템

모든 NativeContainer 인스턴스에 내장된 보안 시스템입니다. 이 시스템은 어떤 NativeContainer 인스턴스에 읽거나 쓰는 것을 추적하고, 해당 정보를 사용하여 여러 잡과 스레드에서 결정적인 방식으로 행동하는 NativeContainer의 사용에 대한 특정 규칙을 적용합니다.

예를 들어 두 개의 독립적으로 예약된 잡이 동일한 NativeArray에 쓰면 어떤 잡이 먼저 실행되는지 예측할 수 없기 때문에 안전하지 않습니다. 즉, 어느 잡이 다른 잡의 데이터를 덮어쓰는지 알 수 없습니다. 이 보안 시스템은 두 번째 잡을 예약할 때 문제가 해결되는 이유와 방법을 설명하는 명확한 오류 메시지가 포함된 예외를 발생시킵니다.

동일한 NativeContainer 인스턴스에 쓰는 두 개의 잡을 예약하려면 종속성으로 잡을 예약합니다. 첫 번째 잡은 NativeContainer에 쓰며, 실행이 끝나면 다음 잡은 같은 NativeContainer에 안전하게 읽고 쓰게 됩니다. 종속성을 도입하면 잡이 항상 일관된 순서로 실행되고 NativeContainer의 결과 데이터가 결정론적임을 보장할 수 있습니다.

안전 시스템을 통해 여러 잡이 동일한 데이터에서 동시에 읽을 수 있습니다.

메인 스레드에서 데이터에 액세스하는 경우에도 이러한 읽기 및 쓰기 제한이 적용됩니다. 예를 들어 NativeContainer에 쓰는 작업이 완료되기 전에 NativeContainer의 콘텐츠를 읽으려고 하면 안전 시스템에서 오류가 발생합니다. 마찬가지로 읽거나 쓰는 잡이 보류 중인 상태에서 NativeContainer에 쓰기를 시도하면 안전 시스템에서도 오류가 발생합니다.

또한 NativeContainer는 ref return을 구현하지 않으므로 NativeContainer의 내용을 직접 변경할 수 없습니다. 예를 들어 nativeArray[0]++;nativeArray에서 값을 업데이트하지 않는 var temp = nativeArray[0]; temp++;를 작성하는 것과 같습니다.

대신에 인덱스의 데이터를 로컬 임시 복사본으로 복사하고 해당 복사본을 수정한 후 다시 저장해야 합니다. 예시:

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

추가 리소스

Thread safe types
커스텀 네이티브 컨테이너 구현