| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | ||
| 6 | 7 | 8 | 9 | 10 | 11 | 12 |
| 13 | 14 | 15 | 16 | 17 | 18 | 19 |
| 20 | 21 | 22 | 23 | 24 | 25 | 26 |
| 27 | 28 | 29 | 30 |
- GPU 병목
- 유니티
- HDRP
- 리눅스
- 리눅스 명령어
- 성능 최적화
- c#
- AssetBundle
- 에셋번들
- URP
- 메모리
- 멀티스레드
- rocky linux
- dots
- unity
- 정렬
- 렌더링파이프라인
- 디자인패턴
- SQL시험
- 프로세스
- 배칭
- ubuntu
- 픽셀 쉐이더
- 버텍스 쉐이더
- ecs
- 스레드
- 유니티 최적화
- SQLD
- SRP
- 쉐이더
- Today
- Total
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | ||
| 6 | 7 | 8 | 9 | 10 | 11 | 12 |
| 13 | 14 | 15 | 16 | 17 | 18 | 19 |
| 20 | 21 | 22 | 23 | 24 | 25 | 26 |
| 27 | 28 | 29 | 30 |
- GPU 병목
- 유니티
- HDRP
- 리눅스
- 리눅스 명령어
- 성능 최적화
- c#
- AssetBundle
- 에셋번들
- URP
- 메모리
- 멀티스레드
- rocky linux
- dots
- unity
- 정렬
- 렌더링파이프라인
- 디자인패턴
- SQL시험
- 프로세스
- 배칭
- ubuntu
- 픽셀 쉐이더
- 버텍스 쉐이더
- ecs
- 스레드
- 유니티 최적화
- SQLD
- SRP
- 쉐이더
- Today
- Total
Let's Girin!
[Unity] DOTS - Job 시스템 본문
1. 멀티스레드 환경에서의 C# 잡 시스템
🔹잡 시스템의 기본 개념
Unity에서 게임 로직은 주로 MonoBehaviour의 업데이트 함수에서 실행되는데, 이 업데이트 함수는 메인 스레드에서만 실행된다. 그러나 멀티코어 CPU 환경에서는 하나의 코어에서만 모든 작업을 처리하는 것이 비효율적이기 때문에, 여러 코어를 활용하려면 멀티스레딩을 사용해야 한다. C# 잡 시스템은 멀티스레드 환경에서 게임 로직을 더 효율적으로 실행하도록 설계된 기능이다.

- 워커 스레드: 잡 시스템은 플랫폼의 CPU 코어 수에 맞춰 워커 스레드를 생성한다. 예를 들어, 8개의 CPU 코어가 있다면, 1개의 메인 스레드 외에 7개의 워커 스레드가 생성된다.
- 잡: 각 워커 스레드는 '잡'이라는 단위의 작업을 실행한다. 잡은 대기열에서 실행할 작업을 가져와 실행하며, 작업을 끝낼 때까지 다른 작업을 처리하지 않는다.
- 중단 없는 실행: 잡은 실행이 시작되면, 완료될 때까지 중단 없이 실행된다. 이는 작업의 일관성을 유지하고, 작업 중간에 상태 변경이 발생하지 않도록 보장한다.
🔹멀티스레딩과 동기
C# 잡 시스템은 멀티스레딩 환경에서 동기화와 동시성을 처리하는데 중요한 역할을 한다. 게임 로직을 여러 스레드에서 실행하는 경우, 데이터가 동시에 접근되거나 수정되는 일이 발생할 수 있는데, 이를 방지하려면 여러 가지 방법을 사용해야 한다.
- 동기화: 여러 스레드가 동시에 실행되면서 발생할 수 있는 데이터 손상을 방지하려면, 잡 시스템은 스레드 간 안전성 검사 및 동기화 처리를 제공한다.
- 경쟁 상태 방지: 두 개 이상의 스레드가 동일한 데이터를 동시에 수정하려는 상황을 경쟁 상태라고 한다. C# 잡 시스템은 이러한 경쟁 상태를 예방하기 위해, 잡 간의 데이터 격리 및 안전성 검사 기능을 제공한다.
2. 잡 스케줄링 및 완료
C# 잡 시스템에서 잡은 메인 스레드에서만 스케줄링할 수 있다. 즉, 다른 스레드나 잡이 새로운 잡을 스케줄하는 것은 불가능하다. 이를 통해 잡 시스템은 복잡한 멀티스레드 환경에서도 안정성을 유지한다.
🔹Complete() 메서드
잡이 실행되고 나서, 메인 스레드는 Complete() 메서드를 사용하여 해당 잡이 완료될 때까지 기다릴 수 있다. 이 메서드는 메인 스레드에서만 호출할 수 있으며, 호출된 후에는 해당 잡이 완료될 때까지 대기한다.
- 메인 스레드에서 호출: Complete() 메서드는 오직 메인 스레드에서만 호출될 수 있다. 메인 스레드가 호출한 후, 해당 잡은 완료될 때까지 대기한다.
- 데이터 안전성 보장: Complete() 메서드가 반환되면, 해당 잡에서 사용된 데이터는 메인 스레드에서 안전하게 액세스할 수 있다. 이렇게 함으로써 다른 스레드와의 데이터 충돌을 예방하고, 데이터의 일관성을 유지할 수 있다.
* Job 구조체 정의
// IJob 인터페이스를 구현하여 잡 정의.
using Unity.Collections;
using Unity.Jobs;
[BurstCompile]
public struct MyCalculationJob : IJob
{
// NativeArray: 워커 스레드와 안전하게 공유되는 데이터.
public NativeArray<float> results;
public float multiplier;
public void Execute()
{
// 워커 스레드에서 실행되는 로직.
for (int i = 0; i < results.Length; i++)
{
results[i] = results[i] * multiplier;
}
}
}
* 메인 스레드에서 잡 스케줄링
public class JobSchedulerExample : MonoBehaviour
{
private void Update()
{
// NativeArray 생성 (Allocator.TempJob: 잡 실행 동안만 유지).
var results = new NativeArray<float>(1000, Allocator.TempJob);
// 초기값 설정.
for (int i = 0; i < results.Length; i++)
results[i] = i;
// 잡 인스턴스 생성 — 메인 스레드에서만 가능.
var job = new MyCalculationJob
{
results = results,
multiplier = 2.5f
};
// Schedule(): 잡을 대기열에 등록하고 JobHandle을 반환.
JobHandle handle = job.Schedule();
// Complete() 호출 전까지 메인 스레드는 다른 작업 가능.
DoOtherWork();
// Complete(): 잡이 끝날 때까지 메인 스레드 대기.
handle.Complete();
// Complete() 반환 후 — 데이터 안전하게 읽기 가능.
float firstResult = results[0];
Debug.Log($"결과: {firstResult}");
// NativeArray는 반드시 수동으로 해제.
results.Dispose();
}
private void DoOtherWork()
{
// 잡 실행 중 메인 스레드가 처리할 수 있는 작업들.
Debug.Log("잡 실행 중 — 메인 스레드는 자유롭게 동작 가능 !!");
}
}
* 잡 의존성 연결
// 여러 잡을 순서대로 실행: JobA 완료 → JobB 실행.
JobHandle handleA = jobA.Schedule();
// handleA를 dependency로 전달 → JobA가 끝난 뒤 JobB 시작.
JobHandle handleB = jobB.Schedule(handleA);
// 여러 잡을 한 번에 기다릴 때.
JobHandle combined = JobHandle.CombineDependencies(handleA, handleB);
combined.Complete();
// 모든 잡이 완료된 후 데이터 접근 가능.
dataArray.Dispose();
3. 안전성 검사 및 종속성 관리
멀티스레드 환경에서 가장 중요한 문제는 스레드 간 안전성을 보장하는 것이다. 특히 여러 스레드가 동일한 데이터를 수정할 때 충돌이 발생할 수 있다. C# 잡 시스템은 이러한 문제를 방지하는 안전성 검사 기능을 제공한다.
🔹데이터 격리
잡 시스템은 데이터 격리를 보장하여, 각 잡이 자신만의 데이터를 사용하게 한다. 이를 통해 다른 잡이나 메인 스레드에서 데이터를 변경하는 것을 방지한다.
🔹경쟁 상태 방지
동일한 데이터에 여러 잡이 동시에 접근하려고 할 때, 경쟁 상태가 발생할 수 있다. 예를 들어, 두 개의 잡이 동일한 배열에 데이터를 쓸 때 충돌이 발생할 수 있다. 이를 방지하기 위해 C# 잡 시스템은 경쟁 상태 검사와 동기화를 자동으로 처리한다.
🔹잡 간의 종속성 관리
잡 간의 종속성도 매우 중요하다. 잡이 다른 잡에 의존하는 경우, 의존 관계를 명확하게 정의하여 충돌을 방지할 수 있다.
- 잡 종속성: 예를 들어, A 잡이 완료되어야만 B 잡이 실행될 수 있도록 할 수 있다. 이를 통해 A 잡과 B 잡이 동일한 데이터에 접근하는 경우 충돌을 방지할 수 있다.
🔹잡 간 안전성 예시
A 잡과 B 잡이 동일한 배열을 공유하는 경우, B 잡은 A 잡이 완료될 때까지 실행되지 않도록 설정할 수 있다. 이를 통해 두 잡이 동시에 실행되면서 데이터를 수정하는 상황을 방지할 수 있다.
4. 주의사항 : I/O 작업에 대한 제약
C# 잡 시스템은 CPU 작업을 최적화하기 위한 도구로 설계되었다. 입출력(I/O) 작업은 CPU 작업과는 다르게 처리해야 한다. 예를 들어 파일 읽기/쓰기나 네트워크 통신 같은 작업은 I/O 작업에 해당하며, 이러한 작업은 메인 스레드에서 비동기 API를 사용하여 처리해야 한다.
- I/O 작업을 잡에서 처리하지 말 것: I/O 작업을 잡에서 수행하면, CPU 코어를 최적화하려는 목적에 맞지 않으며, I/O 작업이 차단(blocking)되면 전체 CPU 성능이 저하될 수 있다.
** 결론
- C# 잡 시스템은 멀티스레드 환경에서 게임 로직을 효율적으로 실행하고, CPU 코어를 최적화하는 데 매우 유용한 도구이다. 이 시스템을 사용하면 멀티코어 환경에서 더 나은 성능을 발휘할 수 있으며, 잡 간의 종속성 및 안전성을 관리하여 데이터 충돌을 방지할 수 있다.
- C# 잡 시스템을 사용한 멀티스레딩 프로그래밍을 통해 복잡한 동시성 문제를 효율적으로 처리할 수 있으며, 게임 개발에서 성능을 극대화할 수 있다.
◈ 유니티 공식 문서를 참고하여 작성하였습니다◈
'Unity' 카테고리의 다른 글
| [Unity] DOTS - Entities (0) | 2026.06.27 |
|---|---|
| [Unity] DOTS - Collections 및 Mathematics (0) | 2026.06.26 |
| [Unity] DOTS - Burst Compiler (0) | 2026.06.25 |
| [Unity ] DOTS - DOTS가 필요한 이유 (0) | 2026.06.23 |
| [Unity] DOTS - 메모리 및 CPU 캐시 (0) | 2026.06.22 |