CPU가 하나인 세대에서 현재는 듀얼코어 쿼드코어등이 보편화 되는 세대가 됨에 따라 CPU를 충분히 활용하기 위한 프로그래밍 기법에 대한 요구가 증가.
Data Parallelism과 Task Parallelism으로 나누워지는데,
Data Parallelism는 대량의 데이터를 처리함에 있어 각 CPU에게 일을 주고 동시에 병렬로 처리
-> 일반적으로 쓰레드 당 처리 내용은 동일
Task Parallelism는 큰 Task를 분할하여 각 쓰레드들이 나눠서 다른 작업 Task들을 실행
다중 CPU에서 다중 쓰레드가 병렬로 데이터를 분할하여 처리하는 기능 제공
// 1. 순차적 실행
// 동일쓰레드가 0~999 출력
//
for (int i = 0; i < 1000; i++)
{
Console.WriteLine("{0}: {1}",
Thread.CurrentThread.ManagedThreadId, i);
}
Console.Read();
// 2. 병렬 처리
// 다중쓰레드가 병렬로 출력
//
Parallel.For(0, 1000, (i) => {
Console.WriteLine("{0}: {1}",
Thread.CurrentThread.ManagedThreadId, i);
});
대량의 데이터를 여러 쓰레드가 나눠서 처리하는 병렬 처리는 많은 경우에는 순차적으로 처리하는 것보다 빠를 가능성이 큼.
const int MAX = 10000000;
const int SHIFT = 3;
static void SequentialEncryt()
{
// 테스트 데이타 셋업
// 1000 만개의 스트링
string text = "I am a boy. My name is Tom.";
List<string> textList = new List<string>(MAX);
for (int i = 0; i < MAX; i++)
{
textList.Add(text);
}
// 순차 처리 (Test run: 8.7 초)
System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();
watch.Start();
for (int i = 0; i < MAX; i++)
{
char[] chArr = textList[i].ToCharArray();
// 모든 문자를 시저 암호화
for (int x = 0; x < chArr.Length; x++)
{
// 시저 암호
if (chArr[x] >= 'a' && chArr[x] <= 'z')
{
chArr[x] = (char)('a' + ((chArr[x] - 'a' + SHIFT) % 26));
}
else if (chArr[x] >= 'A' && chArr[x] <= 'Z')
{
chArr[x] = (char)('A' + ((chArr[x] - 'A' + SHIFT) % 26));
}
}
// 변경된 암호로 치환
textList[i] = new String(chArr);
};
watch.Stop();
Console.WriteLine(watch.Elapsed.ToString());
}
static void ParallelEncryt()
{
// 테스트 데이타 셋업
// 1000 만개의 스트링
string text = "I am a boy. My name is Tom.";
List<string> textList = new List<string>(MAX);
for (int i = 0; i < MAX; i++)
{
textList.Add(text);
}
// 병렬 처리 (Test run: 6.1 초)
System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();
watch.Start();
Parallel.For(0, MAX, i =>
{
char[] chArr = textList[i].ToCharArray();
// 모든 문자를 시저 암호화
for (int x = 0; x < chArr.Length; x++)
{
// 시저 암호
if (chArr[x] >= 'a' && chArr[x] <= 'z')
{
chArr[x] = (char)('a' + ((chArr[x] - 'a' + SHIFT) % 26));
}
else if (chArr[x] >= 'A' && chArr[x] <= 'Z')
{
chArr[x] = (char)('A' + ((chArr[x] - 'A' + SHIFT) % 26));
}
}
// 변경된 암호로 치환
textList[i] = new String(chArr);
});
watch.Stop();
Console.WriteLine(watch.Elapsed.ToString());
}
여러 작업들을 병렬로 처리하는 기능을 제공
static void RunTasks()
{
// 5개의 다른 Task들을 병렬로 실행
Parallel.Invoke(
() => { method1(); },
() => { method2(); },
() => { method3(); },
() => { method4(); },
() => { method5(); }
);
//...
}
제네릭이 아닌 컬렉션에 사용법
Parallel.ForEach(nonGenericCollection.Cast<object>(),
currentElement =>
{
});