유니티에서 제공하는 많은 메서드들은 메인 스레드(Main Thread)에서 실행되어야 합니다.
하지만, C#에서 제공하는 기능이나, 통신, 파일 로딩, 파싱 같은 것들은 병렬 프로그램으로 분리하여 처리 할 수 있습니다.
이 경우 병렬 프로그래밍 사용하면 됩니다.
1. 병렬 프로그래밍 (Parallel Programming)
멀티코어 컴퓨터에서 다수의 CPU를 효율적으로 이용하기 위해 병렬 처리(Parallel Processing)을 사용합니다.
한 개 이상의 CPU를 사용하여, 데이터 처리 성능을 높이기 방법이죠.
C#에서는 Data Parallelism와 Task Parallelism를 이용하여 병렬 처리를 합니다.
2. Data Parallelism
대량의 데이터를 처리함에 있어 각 CPU에게 일을 주고 동시에 병렬로 처리하는 방법입니다.
Parallel 클래스에서 메서드 For와 Foreach를 사용하여 병렬 처리를 합니다.
Parallel 클래스는 네임스페이스로 System.Threading.Tasks를 선언 해 주어야 합니다.
네임스페이스 |
using System.Threading.Tasks; |
Parallel 클래스 For 메서드 |
설명 |
For(Int32, Int32, Action<Int32,ParallelLoopState>) |
반복을 병렬로 실행할 수 있고 루프 상태를 모니터링 및 조작할 수 있는 for 루프를 실행합니다. |
For(Int32, Int32, Action<Int32>) |
반복이 병렬로 실행될 수 있는 for 루프를 실행합니다. |
For(Int32, Int32, ParallelOptions, Action<Int32,ParallelLoopState>) |
반복을 병렬로 실행할 수 있고 루프 옵션을 구성할 수 있으며 루프 상태를 모니터링 및 조작할 수 있는 for 작업을 루프를 실행합니다. |
For(Int32, Int32, ParallelOptions, Action<Int32>) |
반복을 병렬로 실행할 수 있고 루프 옵션을 구성할 수 있는 for 루프를 실행합니다. |
For(Int64, Int64, Action<Int64,ParallelLoopState>) |
64비트 인덱스를 사용하여 반복을 병렬로 실행할 수 있고 루프 상태를 모니터링 및 조작할 수 있는 for 루프를 실행합니다. |
For(Int64, Int64, Action<Int64>) |
64비트 인덱스를 사용하여 반복을 병렬로 실행할 수 있는 for 루프를 실행합니다. |
For(Int64, Int64, ParallelOptions, Action<Int64,ParallelLoopState>) |
64비트 인덱스를 사용하여 반복을 병렬로 실행할 수 있고 루프 옵션을 구성할 수 있으며 루프 상태를 모니터링 및 조작할 수 있는 for 루프를 실행합니다. |
For(Int64, Int64, ParallelOptions, Action<Int64>) |
64비트 인덱스를 사용하여 반복을 병렬로 실행할 수 있고 루프 옵션을 구성할 수 있는 for 루프를 실행합니다. |
For<TLocal>(Int32, Int32, Func<TLocal>, Func<Int32,ParallelLoopState,TLocal,TLocal>, Action<TLocal>) |
스레드 로컬 데이터를 사용하여 반복을 병렬로 실행할 수 있고 루프 상태를 모니터링 및 조작할 수 있는 for 루프를 실행합니다. |
For<TLocal>(Int32, Int32, ParallelOptions, Func<TLocal>, Func<Int32,ParallelLoopState,TLocal,TLocal>, Action<TLocal>) |
스레드 로컬 데이터를 사용하여 반복을 병렬로 실행할 수 있고 루프 옵션을 구성할 수 있으며 루프 상태를 모니터링 및 조작할 수 있는 for 루프를 실행합니다. |
For<TLocal>(Int64, Int64, Func<TLocal>, Func<Int64,ParallelLoopState,TLocal,TLocal>, Action<TLocal>) |
64비트 인덱스와 스레드 로컬 데이터를 사용하여 반복을 병렬로 실행할 수 있고 루프 상태를 모니터링 및 조작할 수 있는 for 루프를 실행합니다. |
For<TLocal>(Int64, Int64, ParallelOptions, Func<TLocal>, Func<Int64,ParallelLoopState,TLocal,TLocal>, Action<TLocal>) |
64비트 인덱스와 스레드 로컬 데이터를 사용하여 반복을 병렬로 실행할 수 있고 루프 옵션을 구성할 수 있으며 루프 상태를 모니터링 및 조작할 수 있는 for 루프를 실행합니다. |
using UnityEngine;
using System.Threading;
using System.Threading.Tasks;
public class ParallelForExample : MonoBehaviour
{
void Start()
{
Parallel.For(0, 1000, (i) => {
Debug.Log($"{Thread.CurrentThread.ManagedThreadId}: {i}");
});
}
}
Parallel 클래스 Foreach 메서드 |
설명 |
ForEach<TSource,TLocal>(IEnumerable<TSource>, Func<TLocal>, Func<TSource,ParallelLoopState,Int64,TLocal,TLocal>, Action<TLocal>) |
스레드 로컬 데이터를 사용하여 반복을 병렬로 실행할 수 있고 루프 상태를 모니터링 및 조작할 수 있는 foreach(Visual Basic의 경우 For Each) 작업을 IEnumerable에 대해 실행합니다. |
ForEach<TSource,TLocal>(IEnumerable<TSource>, Func<TLocal>, Func<TSource,ParallelLoopState,TLocal,TLocal>, Action<TLocal>) |
스레드 로컬 데이터를 사용하여 반복을 병렬로 실행할 수 있고 루프 상태를 모니터링 및 조작할 수 있는 foreach(Visual Basic의 경우 For Each) 작업을 IEnumerable에 대해 실행합니다. |
ForEach<TSource,TLocal>(IEnumerable<TSource>, ParallelOptions, Func<TLocal>, Func<TSource,ParallelLoopState,Int64,TLocal,TLocal>, Action<TLocal>) |
64비트 인덱스와 스레드 로컬 데이터를 사용하여 반복을 병렬로 실행할 수 있고 루프 옵션을 구성할 수 있으며 루프 상태를 모니터링 및 조작할 수 있는 foreach(Visual Basic의 경우 For Each) 작업을 IEnumerable에 대해 실행합니다. |
ForEach<TSource,TLocal>(IEnumerable<TSource>, ParallelOptions, Func<TLocal>, Func<TSource,ParallelLoopState,TLocal,TLocal>, Action<TLocal>) |
스레드 로컬 데이터를 사용하여 반복을 병렬로 실행할 수 있고 루프 옵션을 구성할 수 있으며 루프 상태를 모니터링 및 조작할 수 있는 foreach(Visual Basic의 경우 For Each) 작업을 IEnumerable에 대해 실행합니다. |
ForEach<TSource,TLocal>(OrderablePartitioner<TSource>, Func<TLocal>, Func<TSource,ParallelLoopState,Int64,TLocal,TLocal>, Action<TLocal>) |
스레드 로컬 데이터를 사용하여 반복을 병렬로 실행할 수 있고 루프 옵션을 구성할 수 있으며 루프 상태를 모니터링 및 조작할 수 있는 foreach(Visual Basic의 경우 For Each) 작업을 OrderablePartitioner<TSource>에 대해 실행합니다. |
ForEach<TSource,TLocal>(OrderablePartitioner<TSource>, ParallelOptions, Func<TLocal>, Func<TSource,ParallelLoopState,Int64,TLocal,TLocal>, Action<TLocal>) |
64비트 인덱스와 스레드 로컬 데이터를 사용하여 반복을 병렬로 실행할 수 있고 루프 옵션을 구성할 수 있으며 루프 상태를 모니터링 및 조작할 수 있는 foreach(Visual Basic의 경우 For Each) 작업을 OrderablePartitioner<TSource>에 대해 실행합니다. |
ForEach<TSource,TLocal>(Partitioner<TSource>, Func<TLocal>, Func<TSource,ParallelLoopState,TLocal,TLocal>, Action<TLocal>) |
스레드 로컬 데이터를 사용하여 반복을 병렬로 실행할 수 있고 루프 상태를 모니터링 및 조작할 수 있는 foreach(Visual Basic의 경우 For Each) 작업을 Partitioner에 대해 실행합니다. |
ForEach<TSource,TLocal>(Partitioner<TSource>, ParallelOptions, Func<TLocal>, Func<TSource,ParallelLoopState,TLocal,TLocal>, Action<TLocal>) |
스레드 로컬 데이터를 사용하여 반복을 병렬로 실행할 수 있고 루프 옵션을 구성할 수 있으며 루프 상태를 모니터링 및 조작할 수 있는 foreach(Visual Basic의 경우 For Each) 작업을 Partitioner에 대해 실행합니다. |
ForEach<TSource>(IEnumerable<TSource>, Action<TSource,ParallelLoopState,Int64>) |
64비트 인덱스를 사용하여 반복을 병렬로 실행할 수 있고 루프 상태를 모니터링 및 조작할 수 있는 foreach(Visual Basic의 경우 For Each) 작업을 IEnumerable에 대해 실행합니다. |
ForEach<TSource>(IEnumerable<TSource>, Action<TSource,ParallelLoopState>) |
반복을 병렬로 실행할 수 있고 루프 상태를 모니터링 및 조작할 수 있는 foreach(Visual Basic의 경우 For Each) 작업을 IEnumerable에 대해 실행합니다. |
ForEach<TSource>(IEnumerable<TSource>, Action<TSource>) |
반복이 병렬로 실행될 수 있는 foreach(Visual Basic의 경우 For Each) 작업을 IEnumerable 작업을 실행합니다. |
ForEach<TSource>(IEnumerable<TSource>, ParallelOptions, Action<TSource,ParallelLoopState,Int64>) |
64비트 인덱스를 사용하여 반복을 병렬로 실행할 수 있고 루프 옵션을 구성할 수 있으며 루프 상태를 모니터링 및 조작할 수 있는 foreach(Visual Basic의 경우 For Each) 작업을 IEnumerable에 대해 실행합니다. |
ForEach<TSource>(IEnumerable<TSource>, ParallelOptions, Action<TSource,ParallelLoopState>) |
반복을 병렬로 실행할 수 있고 루프 옵션을 구성할 수 있으며 루프 상태를 모니터링 및 조작할 수 있는 foreach(Visual Basic의 경우 For Each) 작업을 IEnumerable에 대해 실행합니다. |
ForEach<TSource>(IEnumerable<TSource>, ParallelOptions, Action<TSource>) |
반복을 병렬로 실행할 수 있고 루프 옵션을 구성할 수 있는 foreach(Visual Basic의 경우 For Each) 작업을 IEnumerable에 대해 실행합니다. |
ForEach<TSource>(OrderablePartitioner<TSource>, Action<TSource,ParallelLoopState,Int64>) |
반복을 병렬로 실행할 수 있고 루프 상태를 모니터링 및 조작할 수 있는 foreach(Visual Basic의 경우 For Each) 작업을 OrderablePartitioner<TSource>에 대해 실행합니다. |
ForEach<TSource>(OrderablePartitioner<TSource>, ParallelOptions, Action<TSource,ParallelLoopState,Int64>) |
반복을 병렬로 실행할 수 있고 루프 옵션을 구성할 수 있으며 루프 상태를 모니터링 및 조작할 수 있는 foreach(Visual Basic의 경우 For Each) 작업을 OrderablePartitioner<TSource>에 대해 실행합니다. |
ForEach<TSource>(Partitioner<TSource>, Action<TSource,ParallelLoopState>) |
반복을 병렬로 실행할 수 있고 루프 상태를 모니터링 및 조작할 수 있는 foreach(Visual Basic의 경우 For Each) 작업을 Partitioner에 대해 실행합니다. |
ForEach<TSource>(Partitioner<TSource>, Action<TSource>) |
반복이 병렬로 실행될 수 있는 foreach(Visual Basic의 경우 For Each) 작업을 Partitioner 작업을 실행합니다. |
ForEach<TSource>(Partitioner<TSource>, ParallelOptions, Action<TSource,ParallelLoopState>) |
반복을 병렬로 실행할 수 있고 루프 옵션을 구성할 수 있으며 루프 상태를 모니터링 및 조작할 수 있는 foreach(Visual Basic의 경우 For Each) 작업을 Partitioner에 대해 실행합니다. |
ForEach<TSource>(Partitioner<TSource>, ParallelOptions, Action<TSource>) |
반복을 병렬로 실행할 수 있고 루프 옵션을 구성할 수 있는 foreach(Visual Basic의 경우 For Each) 작업을 Partitioner에 대해 실행합니다. |
using System.Collections.Generic;
using UnityEngine;
using System.Threading;
using System.Threading.Tasks;
public class ParallelForEachExample : MonoBehaviour
{
void Start()
{
List<string> alphabets = new List<string>();
alphabets.Add("A");
alphabets.Add("B");
alphabets.Add("C");
alphabets.Add("D");
alphabets.Add("E");
alphabets.Add("F");
alphabets.Add("G");
Parallel.ForEach(alphabets, new ParallelOptions { MaxDegreeOfParallelism = 4 }, fruit =>
{
Debug.Log($"Alphabet: {fruit}, Thread Id= {Thread.CurrentThread.ManagedThreadId}");
}
); // 출력 : Alphabet: D, Thread Id= 26 ....
}
}
3. Task Parallelism
Task Parallelism는 큰 태스크(Task)를 분할하여 각 스레드들이 나눠서 다른 태스크들을 실행합니다.
Parallel 클래스 Invoke 메서드 |
설명 |
Invoke(Action[]) |
각각의 제공된 동작을 가능하면 병렬로 실행합니다. |
Invoke(ParallelOptions, Action[]) |
사용자가 작업을 취소하지 않는다면 제공된 각 작업을 가능한 한 병렬로 실행합니다. |
using UnityEngine;
using System.Threading.Tasks;
public class ParallelInvokeExample : MonoBehaviour
{
void Start()
{
Parallel.Invoke(() =>
{
Debug.Log("1");
},
() =>
{
Debug.Log("2");
},
() =>
{
Debug.Log("3");
});
}
}
'프로그램 > 유니티 C# 강좌' 카테고리의 다른 글
[유니티 C# 강좌] 22. 링크(LINQ, Language-Integrated Query) (1) | 2020.02.11 |
---|---|
[유니티 C# 강좌] 21. 제네릭 컬렉션(General Collection) (1) | 2020.02.09 |
[유니티 C# 강좌] 19. 비동기 프로그래밍(Asynchronous Programming) (0) | 2020.02.06 |
[유니티 C# 강좌] 18. 익명 형식, 익명 메서드, 람다식, Func 대리자, Action 대리자 (0) | 2020.02.05 |
[유니티 C# 강좌] 17. 이벤트(Event), 대리자 (델리게이트, Delegate) (0) | 2020.02.04 |