본문 바로가기

프로그램/유니티 C# 강좌

[유니티 C# 강좌] 20. 병렬 프로그래밍 (Parallel Programming)

728x90
반응형

유니티에서 제공하는 많은 메서드들은 메인 스레드(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"); 
        }); 
    } 
}

 

728x90
반응형