C# には並列処理を簡単に実装できるParallel
クラス(.NET Framework4.0から導入)が用意されています。
このクラスを活用することで、ループ処理やメソッドの並列実行が可能になり、マルチコアCPUの性能を最大限に活かせます。
本記事では、Parallel
クラスの基本的な使い方をサンプルコードを交えながら紹介していますので、ぜひ参考にしてみてください。
オススメの参考書
C#の使い方が丁寧に解説しており、「基礎からしっかりと学びたい」という初心者の方にオススメの一冊です。サンプルコードも記載してあり、各章の最後に復習問題があるので理解度を確認しながら読み進めることができます。新しい C# のバージョンにも対応している書籍です。
Parallelクラスとは?
Parallel
クラスは、.NETのSystem.Threading.Tasks
名前空間に属しており、コレクションやデータソースのループ処理を並列に実行する機能を提供します。
ループ内部の処理は順番に実行する代わりに、1つ1つのループを同時に実行することを可能にするため、全体の実行時間を減らすことがでパフォーマンスを向上させることができます。
並列処理を実行するためのメソッドとして、以下があります。
- Parallel.For メソッド
- Parallel.ForEach メソッド
また、ループではない複数の処理を並列に実行するには、Invoke
メソッドを使います。
- Parallel.Invoke メソッド
Parallelクラスの使い方
Parallel
クラスのFor
メソッド、ForEach
メソッドおよびInvoke
メソッドについて、それぞれ使い方を説明します。
Parallel.Forメソッド
Parallel.For
を使うと、指定した範囲のループを並列で実行できます。
使い方としては以下の感じです。
// Forメソッド
Parallel.For(開始インデックス, 終了インデックス, インデックス =>
{
// ループ内の処理
});
このメソッドを使って、”あいうえお”が1文字ずつが格納されたリストをデバッグ出力するサンプルが以下のコードです。
// リスト
List<string> list = new List<string>()
{
"あ", "い", "う", "え", "お"
};
// 並列処理を実行する
Parallel.For(0, list.Count, i =>
{
Debug.WriteLine(list[i]);
});
実行結果は以下の通りです。
え
お
う
あ
い
このように指定した数だけループを並列で実行します。並列で実行するため、出力される文字は”あ”→”い”→”う”→”え”→”お”の順に出力されず、実行毎に結果が毎回変わります。
Parallel.ForEachメソッド
Parallel.ForEach
を使うと、コレクションの要素毎の処理を並列で実行できます。
使い方としては以下の感じようなです。
// ForEachメソッド
Parallel.ForEach(コレクション, 要素 =>
{
// ループ内の処理
});
このメソッドを使って、”あいうえお”が1文字ずつが格納されたリストをデバッグ出力するサンプルが以下のコードです。
// リスト
List<string> list = new List<string>()
{
"あ", "い", "う", "え", "お"
};
// 並列処理を実行する
Parallel.ForEach(list, str =>
{
Debug.WriteLine(str);
});
実行結果は以下の通りです。
あ
う
お
え
い
For
メソッドとは異なり、コレクション内の全ての要素を並列で処理を実行します。配列やリスト、IEnumerable<T>
などに対して扱うことができます。
Parallel.Invokeメソッド
Parallel.Invoke
を使うと、複数のメソッドを並列に実行できます。
使い方としては以下の感じようなです。
// Invokeメソッド
Parallel.Invoke(
() => 処理A,
() => 処理B,
() => 処理C
);
このメソッドを使って、”あいうえお”が1文字ずつが格納されたリストをデバッグ出力するサンプルが以下のコードです。
// リスト
List<string> list = new List<string>()
{
"あ", "い", "う", "え", "お"
};
// 並列処理を実行する
Parallel.Invoke(
() => Debug.WriteLine(list[0]),
() => Debug.WriteLine(list[1]),
() => Debug.WriteLine(list[2]),
() => Debug.WriteLine(list[3]),
() => Debug.WriteLine(list[4])
);
実行結果は以下の通りです。
う
あ
え
い
お
各メソッドが並列に処理が実行されます。For
メソッドとForEach
メソッドと同じように出力される結果はバラバラです。
Parallelクラスを使う際の注意点
Parallelクラスを使うにあたって、いくつかの注意点があります。
- 並列する処理は独立している必要がある。
- 並列する処理は制限する必要がある。
複数の処理の間に依存関係がある場合、処理は独立していないことになり、並列化できません。
また、一度に並列で処理する数が多すぎるとオーバーヘッドが発生する可能性があり、ParallelOptions
を使用し、最大並列数を制限することが推奨されます。
// リスト
List<string> list = new List<string>()
{
"あ", "い", "う", "え", "お"
};
// 並列処理オプションの設定
var option = new ParallelOptions();
option.MaxDegreeOfParallelism = 4;
// 並列処理を実行する
// 並列処理を実行する
Parallel.ForEach(list, option, str =>
{
Debug.WriteLine(str);
});
まとめ
この記事ではParallelクラスで提供される3つのメソッドの使い方を紹介しました。
- Parallel.For メソッド
数値範囲のループを並列で処理する - Parallel.ForEach メソッド
コレクションを並列で処理する - Parallel.Invoke メソッド
複数のメソッドを並列で実行する
C# の並列処理を簡単に実装できるので、ぜひ扱えるようになっておきましょう。
以上、最後まで読んでいただきありがとうございました。