Unity Engine

Unity Job System - 종속성

Aostols 2022. 5. 11. 09:09
반응형

Unity 에서는 멀티 스레딩을 지원 하기 위해서 Job System을 제공 하고 있습니다.

https://docs.unity3d.com/kr/2018.4/Manual/JobSystem.html

 

C# 잡 시스템 - Unity 매뉴얼

Unity C# 잡 시스템(Job System)을 사용해 Unity 엔진과 상호작용하는 간단하고 안전한 멀티스레드 코드를 작성하여 게임 성능을 개선할 수 있습니다.

docs.unity3d.com

 

간단히 단일 스레드보다 멀티 스레드를 사용하는 방식이 성능상 이점이 있기 때문에 사용할 수 있는 환경이라면 사용 하는 것이 성능적으로 이득을 얻을 수 있습니다.

다만 매뉴얼을 살펴보게 되면 스레드간 데이터 이동이 자유롭지는 않습니다.

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