[C#] 40. Linqを利用した並列処理(Parallel)を使い方
こんにちは。明月です。
この投稿はC#でLinqを利用した並列処理(Parallel)を使い方に関する説明です。
以前の投稿で私がThreadに関して説明したことがあります。
link - [C#] 37. スレッド(Thread)を使い方、Thread.Sleep関数を使い方
スレッドというのはプログラム内でいろんな処理を同時に処理、つまり、同時に処理してシステムの性能を向上させる機能です。
でも、このスレッドは個数が無限的に増やすこともできないし、どのぐらいにスレッドが多くなると性能低下になるため、個数管理するThreadPoolが存在します。しかし、このThreadPoolはJoin機能が無くて、EventWaitHandleクラスで同期化する機能を別に作成しなければならない不便なこともあります。
Linq式ではこの問題を解決する並列処理を作成できます。
using System;
using System.Linq;
using System.Collections.Generic;
using System.Threading;
namespace Example
{
// 例クラス
class Node
{
// コンソールに出力콘する時に使うテキスト
public string Text { get; set; }
// 繰り返し回数
public int Count { get; set; }
// Sleepの時間チック
public int Tick { get; set; }
}
class Program
{
// 実行関数
static void Main(string[] args)
{
// Nodeクラスのリスト
var list = new List<Node>();
// リストにインスタンスを追加
list.Add(new Node { Text = "A", Count = 3, Tick = 1000 });
list.Add(new Node { Text = "B", Count = 5, Tick = 10 });
list.Add(new Node { Text = "C", Count = 2, Tick = 500 });
list.Add(new Node { Text = "D", Count = 7, Tick = 300 });
list.Add(new Node { Text = "E", Count = 4, Tick = 200 });
// リストにParallel設定
list.AsParallel()
// 並列処理個数設定(最大2개)
.WithDegreeOfParallelism(2)
// 並列処理実行
.ForAll(x =>
{
// 設定された繰り返しの回数程
for (int i = 0; i < x.Count; i++)
{
// コンソール出力
Console.WriteLine(x.Text + " = " + i);
// 設定されたSleep時間チック
Thread.Sleep(x.Tick);
}
// 完了、コンソールに出力
Console.WriteLine("Complete " + x.Text);
});
// 任意のキーを押してください
Console.WriteLine("Press Any key...");
Console.ReadLine();
}
}
}
上の例をみればNodeクラスのインスタンスをListに格納して、Linq式のAsParallel関数を呼び出すことなら並列処理になります。
WithDegreeOfParallelismの関数を通ってParallelのスレッドの最大個数を設定してForAllを通って実行します。
ForAllはラムダ式で設定してパラメータはListに設定されたNodeインスタンスを取得して実行します。
ここまで見るとThreadとThreadPoolの欠点がなくなる機能ではないかと思います。
Parallel機能をListだけ付けて使うことではなく、staticタイプのクラスで独立的に使うことができます。
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Example
{
class Program
{
// 実行関数
static void Main(string[] args)
{
// Parallel staticクラス
// 0から4まで
Parallel.For(0, 5, x =>
{
// 0から2まで繰り返し
for (int i = 0; i < 3; i++)
{
// コンソール出力
Console.WriteLine(x + " = " + i);
// スレッド待機
Thread.Sleep(1);
}
});
// 任意のキーを押してください
Console.WriteLine("Press Any key...");
Console.ReadLine();
}
}
}
Parallelクラスの並列処理は基本の形はFor関数です。
意味はforの初期式、条件式、増減式をParallelで設定することです。つまり、forを並列に処理することです。
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Generic;
namespace Example
{
// 例クラス
class Node
{
// コンソールに出力콘する時に使うテキスト
public string Text { get; set; }
// 繰り返し回数
public int Count { get; set; }
// Sleepの時間チック
public int Tick { get; set; }
}
class Program
{
// 実行関数
static void Main(string[] args)
{
// Nodeクラスのリスト
var list = new List<Node>();
// リストにインスタンスを追加
list.Add(new Node { Text = "A", Count = 3, Tick = 1000 });
list.Add(new Node { Text = "B", Count = 5, Tick = 10 });
list.Add(new Node { Text = "C", Count = 2, Tick = 500 });
list.Add(new Node { Text = "D", Count = 7, Tick = 300 });
list.Add(new Node { Text = "E", Count = 4, Tick = 200 });
// Parallel staticクラス
// listの個数程
Parallel.ForEach(list, x =>
{
// 設定された繰り返しの回数程
for (int i = 0; i < x.Count; i++)
{
// コンソール出力
Console.WriteLine(x.Text + " = " + i);
// 設定されたSleep時間チック
Thread.Sleep(x.Tick);
}
// 完了、コンソールに出力
Console.WriteLine("Complete " + x.Text);
});
// 任意のキーを押してください
Console.WriteLine("Press Any key...");
Console.ReadLine();
}
}
}
ParallelのForEachはforeach文を並列に処理する関数です。
形式はListタイプのデータを始めのパラメータに入れて、ラムダ式で各データを取得して並列処理になります。
using System;
using System.Threading.Tasks;
namespace Example
{
class Program
{
// 実行関数
static void Main(string[] args)
{
// Parallel staticクラス
// 4個のラムダ式を並列処理
Parallel.Invoke(() =>
{
Console.WriteLine("A");
}, () =>
{
Console.WriteLine("B");
}, () =>
{
Console.WriteLine("C");
}, () =>
{
Console.WriteLine("D");
});
// 任意のキーを押してください
Console.WriteLine("Press Any key...");
Console.ReadLine();
}
}
}
上のれ例は別に関係ないラムダ式を並列処理にしました。Invoke関数のパラメータはparamsの処理なので可変的にラムダ式を入れられます。
この投稿を作成しながら思いましたが、Linq式のAsParallel()の関数は自分もよく使える関数です。Parallelクラスは別に使ったらいい利点がなさそうです。
実は私も投稿を書く前には単純にAsParallelをstatic関数スタイルで表現する方法だと思ったのに、それではないですね。
性能上の利点もないし、スレッドを管理する関数やプロパティもないし、単純にfor文を並列に処理することですが、これを使うことよりThreadPoolを使う方がもっといいではないかと思います。
ここまでC#でLinqを利用した並列処理(Parallel)を使い方に関する説明でした。
ご不明なところや間違いところがあればコメントしてください。
- [C#] 47. Nugetを使い方(外部ライブラリ)とデータベース(MariaDB(Mysql))を使い方、そしてトランザクション(Transaction)2021/10/08 18:58:57
- [C#] 46. データベース(MSSQL)に接続する方法2021/10/07 18:39:58
- [C#] 45. ネットワークソケット通信(Socket)を使い方2021/10/06 19:06:25
- [C#] 44. ファイル(FileInfo)とディレクトリ(DirectoryInfo)を扱い2021/10/05 19:29:34
- [C#] 43. ストリーム(Stream)とバイナリ(byte[])、エンコード(Encoding)、そしてusingを使い方とIDisposableインターフェース2021/10/04 18:33:04
- [C#] 42. ファイルを扱い(IO)とファイルメタデータ(FileInfo)を使い方2021/10/01 20:10:21
- [C#] 41. Taskクラスとasync、awaitを使い方2021/10/01 18:59:14
- [C#] 40. Linqを利用した並列処理(Parallel)を使い方2020/05/13 17:37:13
- [C#] 39. lockキーワードとdeadlock(デッドロック)2019/07/24 00:57:35
- [C#] 38. ThreadPoolの使い方2019/07/23 00:05:40
- [C#] 37. スレッド(Thread)を使い方、Thread.Sleep関数を使い方2019/07/22 23:45:05
- [C#] 36. 拡張メソッドを使い方2019/07/22 23:30:17
- [C#] 35. 文字列クラス、StringとStringBuilderを使い方2019/07/22 23:15:42
- [C#] 34. 最上位クラス(Object クラス)2019/07/20 02:27:23
- [C#] 33. 匿名形式(Anonymous Types)を使い方2019/07/20 02:22:03
- check2024/04/10 19:03:53
- [Java] 64.Spring bootとReactを連結する方法(Buildする方法)2022/03/25 21:02:18
- [Javascript] Node.jsをインストールしてReactを使う方法2022/03/23 18:01:34
- [Java] 63. Spring bootでcronスケジューラとComponentアノテーション2022/03/16 18:57:30
- [Java] 62. Spring bootでWeb-Filterを設定する方法(Spring Security)2022/03/15 22:16:37
- [Java] JWT(Json Web Token)を発行、確認する方法2022/03/14 19:12:58
- [Java] 61. Spring bootでRedisデータベースを利用してセッションクラスタリング設定する方法2022/03/01 18:20:52
- [Java] 60. Spring bootでApacheの連結とロードバランシングを設定する方法2022/02/28 18:45:48
- [Java] 59. Spring bootのJPAでEntityManagerを使い方2022/02/25 18:27:48
- [Java] 58. EclipseでSpring bootのJPAを設定する方法2022/02/23 18:11:10
- [Java] 57. EclipseでSpring bootを設定する方法2022/02/22 19:04:49
- [Python] Redisデータベースに接続して使い方2022/02/21 18:23:49
- [Java] Redisデータベースを接続して使い方(Jedisライブラリ)2022/02/16 18:13:17
- [C#] Redisのデータベースを接続して使い方2022/02/15 18:46:09
- [CentOS] Redisデータベースをインストールする方法とコマンドを使い方2022/02/14 18:33:07