잡 예약 시에는 하나의 잡만 수행할 수 있습니다. 하지만 여러 오브젝트에서 동일한 작업을 수행해야 하는 경우가 있습니다. 이렇게 하려면 IJobParallelFor에서 상속하는 ParallelFor 잡 유형을 사용합니다.
ParallelFor 잡은 데이터 소스로 작동하는 데이터의 NativeArray를 사용합니다. ParallelFor 잡은 여러 CPU 코어에서 실행됩니다. 코어당 하나의 잡이 있으며 각각 워크로드의 하위 세트를 처리합니다.
IJobParallelFor는 IJob처럼 동작하지만, 단일 Execute 메서드 대신 데이터 소스의 항목당 한 번씩 Execute 메서드를 호출합니다. 또한 Execute 메서드에는 정수 파라미터 인덱스도 있습니다. 이 인덱스를 사용하여 잡 구현 내에서 데이터 소스의 단일 요소에 액세스하고 작업할 수 있습니다.
다음은 ParallelFor 잡 정의의 예입니다.
struct IncrementByDeltaTimeJob: IJobParallelFor
{
public NativeArray<float> values;
public float deltaTime;
public void Execute (int index)
{
float temp = values[index];
temp += deltaTime;
values[index] = temp;
}
}
ParallelFor 잡을 예약하려면 분할할 NativeArray 데이터 소스의 길이를 지정해야 합니다. 잡 시스템은 구조체에 여러 개가 있는 경우 어떤 NativeArray를 데이터 소스로 사용할지 알지 못합니다. 길이에 따라 잡 시스템에 예상되는 Execute 메서드 수를 알려 줍니다.
Unity의 네이티브 코드에서는 ParallelFor 잡 예약이 더 복잡합니다. Unity가 ParallelFor 잡을 예약할 때 잡 시스템은 작업을 배치로 나누어 코어 간에 배포합니다. 각 배치에는 Execute 메서드의 하위 집합이 포함되어 있습니다. 그런 다음 잡 시스템은 CPU 코어당 Unity의 네이티브 잡 시스템에서 하나의 잡을 예약하고 해당 네이티브 잡을 배치에 전달하여 완료합니다.
네이티브 잡이 다른 잡보다 먼저 배치를 완료하면 나머지 네이티브 잡에서 남은 배치를 가져와 처리합니다. 네이티브 잡의 남은 배치의 절반만 한 번에 가져와 처리하여 캐시 지역성을 보장합니다.
프로세스를 최적화하려면 배치 수를 지정해야 합니다. 배치 개수는 가져올 잡의 수와 스레드 간 작업 재배포의 세밀도를 제어합니다. 1 같이 배치 수가 적으면 스레드 간에 작업이 균등하게 분배됩니다. 하지만 약간의 오버헤드가 발생하기 때문에 배치 수를 늘리는 것이 좋은 경우도 있습니다. 1부터 시작하여 성능이 거의 향상되지 않을 때까지 배치 수를 늘리는 것이 좋은 방법입니다.
다음은 ParallelFor 잡 예약의 예입니다.
잡 코드:
// Job adding two floating point values together
public struct MyParallelJob : IJobParallelFor
{
[ReadOnly]
public NativeArray<float> a;
[ReadOnly]
public NativeArray<float> b;
public NativeArray<float> result;
public void Execute(int i)
{
result[i] = a[i] + b[i];
}
}
메인 스레드 코드:
NativeArray<float> a = new NativeArray<float>(2, Allocator.TempJob);
NativeArray<float> b = new NativeArray<float>(2, Allocator.TempJob);
NativeArray<float> result = new NativeArray<float>(2, Allocator.TempJob);
a[0] = 1.1;
b[0] = 2.2;
a[1] = 3.3;
b[1] = 4.4;
MyParallelJob jobData = new MyParallelJob();
jobData.a = a;
jobData.b = b;
jobData.result = result;
// Schedule the job with one Execute per index in the results array and only 1 item per processing batch
JobHandle handle = jobData.Schedule(result.Length, 1);
// Wait for the job to complete
handle.Complete();
// Free the memory allocated by the arrays
a.Dispose();
b.Dispose();
result.Dispose();
ParallelForTransform 잡은 트랜스폼에서 작동하도록 특별히 설계된 또 다른 종류의 ParallelFor 잡입니다. 잡에서 트랜스폼 작업을 효율적으로 작업할 때 유용합니다.