PART 5 · 강의 2/4

ParallelFor 패턴

데이터 병렬 처리로 반복 작업을 가속화합니다

01

ParallelFor 개념

불균형 작업을 위한 병렬 루프

ParallelFor는 불균형 작업에 대한 범용 병렬 for로, Task Graph를 사용하여 스레드 간 더 나은 작업 분배를 제공합니다.

사용 시기

  • 계산 시간이 매우 가변적인 작업
  • 이번 프레임에 결과가 필요한 경우
  • 몇 프레임 전의 결과를 사용할 수 없는 경우
  • 대량의 독립적인 데이터 처리
02

기본 사용법

ParallelFor 구현

⚡ ParallelFor 작업 분배
Thread 0
Thread 1
Thread 2
Thread 3

Task Graph가 Items[0..N]을 코어 수만큼 자동 분배

⭐ 기본 ParallelFor
코드 숨기기
#include "Async/ParallelFor.h" // 기본 사용 ParallelFor(Items.Num(), [&](int32 Index) { ProcessItem(Items[Index]); });
단일 스레드 임계값
코드 보기
// 100개 미만이면 단일 스레드로 실행 // (오버헤드가 이득보다 큼) ParallelFor(Items.Num(), [&](int32 Index) { ProcessItem(Items[Index]); }, Items.Num() < 100); // bForceSingleThread 조건
플래그 사용
코드 보기
// 불균형 작업에 최적화 ParallelFor(Items.Num(), [&](int32 Index) { ProcessItem(Items[Index]); }, EParallelForFlags::Unbalanced); // 사용 가능한 플래그: // - None: 기본 // - ForceSingleThread: 단일 스레드 강제 // - Unbalanced: 작업 시간이 불균형할 때 // - PumpRenderingThread: 렌더 스레드 펌핑
03

성능 비교

병렬 처리 효과

📊 10,000개 항목 처리 성능 비교
단일 스레드 for:
30ms
ParallelFor (8코어):
10ms (3배 향상!)
주의사항

ParallelFor 내에서 공유 데이터 수정 시 동기화가 필요합니다. 가능하면 각 인덱스가 독립적인 데이터만 처리하도록 설계하세요.

04

실전 예시

게임에서의 활용

⭐ NPC AI 업데이트 병렬화
코드 숨기기
void ANPCManager::UpdateAllNPCs(float DeltaTime) { // 각 NPC의 AI 계산을 병렬로 ParallelFor(NPCs.Num(), [&](int32 Index) { // 독립적인 계산만 수행 FNPCDecision Decision = NPCs[Index]->CalculateNextAction(); PendingDecisions[Index] = Decision; }); // Game Thread에서 결과 적용 for (int32 i = 0; i < NPCs.Num(); ++i) { NPCs[i]->ApplyDecision(PendingDecisions[i]); } }
핵심 패턴

ParallelFor에서는 계산만 수행하고, UObject 수정은 Game Thread에서 순차적으로 적용합니다.

SUMMARY

핵심 요약

  • ParallelFor: 대량 독립 데이터의 병렬 처리
  • 임계값 설정: 소량 데이터는 단일 스레드가 효율적
  • Unbalanced 플래그: 작업 시간이 불균형할 때
  • 성능: 코어 수에 비례하여 최대 N배 향상
  • 주의: 공유 데이터 접근 시 동기화 필요
다음 단계

다음 강의에서는 플랫폼별 최적화 전략을 다룹니다.

PRACTICE

도전 과제

배운 내용을 직접 실습해보세요

실습 1: ParallelFor 기초 실습

ParallelFor(NumElements, [](int32 Index){ ... })를 사용하여 10000개 Actor의 거리 계산을 병렬화하세요. 단일 스레드 for 루프 대비 실행 시간을 SCOPE_CYCLE_COUNTER로 비교합니다.

실습 2: 청크 사이즈 최적화

ParallelFor의 MinBatchSize 파라미터를 1, 10, 100, 1000으로 변경하며 성능을 측정하세요. 태스크 오버헤드와 부하 분산의 최적 균형점을 찾습니다.

심화 과제

FPlatformAtomics::InterlockedAdd()를 활용한 Lock-Free 카운터와 TAtomic<>를 사용하여 ParallelFor 내에서 안전하게 결과를 집계하는 시스템을 구현하세요. FCriticalSection 대비 성능 차이를 비교합니다.