Unreal : ParallelFor
Unreal 병렬For문
소스코드 : \Engine\Source\Runtime\Core\Public\Async\ParallelFor.h
코드에서 보면 GraphTask로 쓰레드를 만든다.
TGraphTask<FParallelForTask>::CreateTask().ConstructAndDispatchWhenReady(Data, AnyThreadTasks - 1);
- GraphTask는 종종 GameThread를 사용하기도 한다.
- 따라서 모든 Task가 멀티 쓰레드로 돌아가지 않을 수도 있음.
- 이는 곧 ParallelFor문의 Num Parameter가 많아도 성능이 크게 향상되지 않을 수도 있다.
- 실제로 ParallelFor문을 간단한 작업 용도로 사용하는 것을 권장하며, 큰 ThreadTask는 FRunnable을 상속받아 따로 쓰레드를 돌리는게 좋다.
그렇다면 어떻게 사용하는게 좋을까?
- 난 이것을 100개 가까이 되는 datatable을 파싱하기 위해 사용하였다.
1. 먼저 FPlatformProcess::SupportsMultithreading()
으로 멀티쓰레드가 지원하는 디바이스 인지 체크
2. FPlatformMisc::NumberOfWorkerThreadsToSpawn()
으로 현재 사용가능한 쓰레드 갯수를 얻어온다.
3. 이제 쓰레드갯수에 따라 Task를 나눈다.
예를들어, 100개의 datatable이 있다고 가정, worker thread가 8개라면? floor(100 / 8) = 13, 13개씩 나누어 파싱하는 구조로 하였다.
bool bSupportMultithread = FPlatformProcess::SupportsMultithreading();
const int taskNum = FPlatformMisc::NumberOfWorkerThreadsToSpawn();
const int divideEnd = FMath::FloorToInt(InTasks.Num() / taskNum);
ParallelFor(taskNum, [&](int InIndex)
{
int startAt = InIndex * divideEnd;
if (startAt >= InTasks.Num())
{
return;
}
int endAt = startAt + divideEnd;
// lask task
if (InIndex == (taskNum - 1))
{
endAt = InTasks.Num();
}
for (int i = startAt; i < endAt; ++i)
{
UDataTable* dataTable = Cast<UDataTable>(dataTables[i]);
if (dataTable)
{
// parsing code
}
}
}, !bSupportMultithread);