Unity 에서는 멀티 스레딩을 지원 하기 위해서 Job System을 제공 하고 있습니다.
https://docs.unity3d.com/kr/2018.4/Manual/JobSystem.html
간단히 단일 스레드보다 멀티 스레드를 사용하는 방식이 성능상 이점이 있기 때문에 사용할 수 있는 환경이라면 사용 하는 것이 성능적으로 이득을 얻을 수 있습니다.
다만 매뉴얼을 살펴보게 되면 스레드간 데이터 이동이 자유롭지는 않습니다.
NativeContaienr를 활용하여 데이터를 이동하고 클래스는 이동 할 수 없기 때문에 값들만 이동할 수 있습니다.
따라서 결국 메인 스레드에서 대부분의 작업을 처리하고 단순하지만 여러번 있는 류의 작업을 Job System으로 뺄 수 있습니다.
public struct TestJob1 : IJob
{
public float a;
public float b;
public NativeArray<float> result;
public void Execute()
{
float sum = 0;
for(int i=0; i<1000; ++i)
{
sum += a;
sum *= b;
sum /= b;
}
result[0] = sum;
Debug.Log("TestJob1 : " + result[0]);
}
}
public struct TestJob2 : IJob
{
public float a;
public float b;
public NativeArray<float> result;
public void Execute()
{
result[0] = a + b;
Debug.Log("TestJob2 : " + result[0]);
}
}
Job 2개를 만들어 줍니다.
Job 1번이 Job 2번보다 많은 계산을 하게 됩니다.
상식적으로 생각한다면 Job 1번이 Job2번보다 늦게 결과가 나와야 합니다.
NativeArray<float> result1 = new NativeArray<float>(1, Allocator.TempJob);
NativeArray<float> result2 = new NativeArray<float>(1, Allocator.TempJob);
TestJob1 job1 = new TestJob1();
job1.a = 10;
job1.b = 10;
job1.result = result1;
TestJob2 job2 = new TestJob2();
job2.a = 10;
job2.b = 10;
job2.result = result2;
JobHandle handle1 = job1.Schedule();
JobHandle handle2 = job2.Schedule();
handle1.Complete();
handle2.Complete();
result1.Dispose();
result2.Dispose();
테스트용 코드 입니다.
생각했던 것 대로 1번이 2번 보다 늦게 결과가 나오고 있습니다.
여기서 Job2번이 Job1번의 결과를 사용하게 된다면 문제가 발생 하게 됩니다.
Job2번이 Job1번보다 늦게 시작했지만 1번 결과가 나오기 전에 2번이 종료 되 버리는 상황이 올 수 있어서 올바른 결과를 얻을 수 없습니다.
그것을 위해서 종속성 처리를 해주게 됩니다.
job2.result = result1;
약간의 수정으로 job2.result 를 result1로 할당 변경해 줍니다.
Job1과 Job2가 같은 NativeArray를 참조하게 된 것입니다.
InvalidOperationException: The previously scheduled job TestJob1 writes to the Unity.Collections.NativeArray`1[System.Single] TestJob1.result. You are trying to schedule a new job TestJob2, which writes to the same Unity.Collections.NativeArray`1[System.Single] (via TestJob2.result). To guarantee safety, you must include TestJob1 as a dependency of the newly scheduled job.
위의 코드를 그대로 실행하게 되면 위와 같은 에러가 발생하게 됩니다.
그래서 종속성을 추가해 주기 위해서 코드를 다음과 같이 넣어 줍니다.
JobHandle handle2 = job2.Schedule(handle1);
Job2를 실행할때 Job1의 핸들러를 매개변수로 넣어 줍니다.
전체적인 실행의 속도는 약간 늦어 질 수 있으나 명확하게 Job의 순서가 정해지고 하나의 NativeArray에 담긴 값을 여러 Job에서 사용 할 수 있습니다.
'Unity Engine' 카테고리의 다른 글
Behavior Tree - Node Canvas (2) (0) | 2022.07.02 |
---|---|
Behavior Tree - Node Canvas (1) (0) | 2022.06.29 |
Unity - RaycastCommand, IJobParallelFor (0) | 2022.06.21 |
Custom Inspector - ReorderableList(2) (0) | 2022.06.20 |
Custom Inspector - ReorderableList(1) (0) | 2022.06.15 |