質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

解決済

3回答

1928閲覧

TPL(Task Palallel Library)について、英語の説明がわかりません

kazuya_

総合スコア78

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

0グッド

1クリップ

投稿2017/05/14 03:09

下記の意味がよくわかりません。

Using the TPL to create another thread to execute a CPU-bound operation while the originating thread has to
wait for it won’t help you with increasing performance.

下記のように訳してみましたが、よくわかりません。
オリジナルスレッドが待たなければならない間にCPU-BOUNDを実行する別スレッドを作成するためにTPLを
使用することは、パフォーマンスを上げることにならない。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

Using the TPL to create another thread to execute a CPU-bound operation while the originating thread has to

wait for it won’t help you with increasing performance.

その速度が CPU に依存するような処理を実行する別のスレッドを作り、元々のスレッドがそれを待たなくてはならないような場合、TPL をつかってもパフォーマンスは上がりません。

投稿2017/05/14 03:42

Zuishin

総合スコア28660

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kazuya_

2017/05/14 13:05

ご回答ありがとうございます。具体的にコード例を教えていただければありがたいです。
guest

0

ベストアンサー

例えば重たい数式の計算だったり、メモリ上にロードされた全データのスキャンだったりみたいなのを非同期にラップしても、並列化した時精々最大でコア数分の軽量化にしかならない。それどころかスレッドをそれ以上作るとコンテキストスイッチ分動作速度が遅くなる。

また、メソッドの処理が極めて短い場合、1万の要素を並列化処理で4コアだから4スレッドたてて処理…ってやるにしても、その処理が1万回起動されるとスレッドの作成コストのせいで短くならなかったり。
(2500個の要素4つの配列に分けて実行すれば別だが、割り込みによって2500個同時にデータの処理が終わるわけではないのは想像がつくよね。つまりムズイってことだ!)
だから、IEnumerable<T>を単純にAsParallel()して、各メソッドに要素突っ込むぜ、コア全部使うぜ、これで最速だろ!なんて思っても、大体の場合早くならない。場合によっては遅くなる。

例えば、下記のコードはDoSomethingがCPU-BOUNDだと簡単には早くならない。

C#

1foreach (var item in items.AsParallel()) 2{ 3 DoSomething(item); 4}

CPUを消費する処理はそう単純に並列化によるパフォーマンス改善を受けられない。

非同期関数を作成する場合、もっとも効果が高いのはCPUを消費しない処理だ。
そういう、CPU-BOUNDではない処理ってなんだろうか。
それは例えば、データダウンロードとかのことだ。
データのダウンロードでは伝送コストの方がよっぽど高くて、ほとんどCPUは待機状態になる。
TCP/IPではデータ伝送のスループットがCPU計算よりずっと遅いからね。
そういったものは並列化に向いてる。
複数ファイル同時にダウンロードできるぐらいの性能がLANポートには十分あるし、シングルコアでも並列化することで高速化できる。


君のためにどうでもいいコードを書いてみた。
十分にCPU計算処理が重たい場合、コア数分は高速化する。
しかし、短いCPU計算の場合、速度は劣化する。

C#

1namespace ParallelSample 2{ 3 using System; 4 using System.Diagnostics; 5 using System.Linq; 6 using System.Threading.Tasks; 7 8 class Program 9 { 10 const int num = 100; 11 12 static void Main(string[] args) 13 { 14 if (args.Length != 1) return; 15 16 var start = long.Parse(args[0]); 17 18 var single = new Stopwatch(); 19 var result_s = new bool[num]; 20 single.Start(); 21 foreach (var i in Enumerable.Range(0, num)) 22 { 23 long value = start + i * 2; 24 result_s[i] = IsPrime(value); 25 } 26 single.Stop(); 27 28 Console.WriteLine($"シングルスレッド : {single.ElapsedMilliseconds}ms"); 29 30 var parallel = new Stopwatch(); 31 var result_p = new bool[num]; 32 parallel.Start(); 33 Parallel.ForEach(Enumerable.Range(0, num), i => 34 { 35 long value = start + i * 2; 36 result_p[i] = IsPrime(value); 37 }); 38 39 parallel.Stop(); 40 Console.WriteLine($"マルチスレッド : {parallel.ElapsedMilliseconds}ms"); 41 } 42 43 // 全ての値で割ってみて、素数か判定するのを原始的に行うメソッド 44 static bool IsPrime(long n) 45 { 46 for (long i = 2; i < n; i++) 47 { 48 if (n % i == 0) return false; 49 } 50 return true; 51 } 52 } 53}

結果は、i5-3470S@2.90GHzのPCで以下のようになった。

> ParallelSample 10001 シングルスレッド : 2ms マルチスレッド : 19ms > ParallelSample 100001 シングルスレッド : 11ms マルチスレッド : 21ms > ParallelSample 10000001 シングルスレッド : 595ms マルチスレッド : 207ms

原始的に素数判定を行っているため、素数の判定開始数値が大きくなると飛躍的にCPU処理時間が増える。
このため、計算量がスレッド開始のコストを上回る計算量になって初めてマルチスレッドはコア数分の時間短縮を受けられる。
しかし、通常私たちが使う計算式はそんなに長時間CPUを占有しないので、スレッド開始のコストが並列化のメリットを上回ってしまう。
例えば、重たい処理の一つにマップ探索アルゴリズムなどがあげられるが、これにしたって最適化されていれば単純に並列化しただけではパフォーマンス増加に繋がらない可能性は十分にあり得る。(メモリも沢山使うしね)

仮にI/Oバウンドな処理を行っていたとしても、並列数を引き上げ過ぎると「待機の確認」に時間がかかりすぎてしまい、速度は低下することもあるし、並列化は扱いが難しいものだ。
常に計測が必要ってことを覚えておいてもらえれば、とりあえずはいいんじゃないかな。

投稿2017/05/17 06:33

編集2017/05/17 07:34
haru666

総合スコア1591

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kazuya_

2017/05/17 12:48

ご回答ありがとうございました。 AsPallelは、複数コアを使用するので、内部で複数スレッドが生成されているんですよね。Taskで処理をした場合は、複数Taskが、複数スレッドで、複数コア使用になるんですかね。
haru666

2017/05/17 12:58

AsParallelはPLINQだったね、まあ似たようなものだけど 内部で複数スレッドが生成されて管理されているんだけど、それをスレッドプールっていう。 そのスレッドプールを上手く利用するのに使用される作業単位がタスクだ。 ただどんなにうまく管理されていてもタスクを順次処理するのにかかるコストは安くはないんだ。 同時実行してるタスクがあれば、基本的に複数のスレッドが忙しく働き、結果として全部のコアが稼働中になるだろうね。 そのあたりは++C++でも読んでね! http://ufcpp.net/study/csharp/misc_task.html
haru666

2017/05/17 13:01

全コア使って普通の計算より遅い、または同じぐらいっていうのは、コストが良いとはいえないよね。基本的にはCPU依存の処理を並列化するっていうのは、無駄に世話しなくCPUを使ってることになりがち。PCからしてみれば嫌がらせみたいなもんだろね。
guest

0

こんにちは。

めっちゃ意訳すると、下記と思います。

CPUをぶん回すようなスレッドを実行し、その実行終了を元のスレッドが待つ時、TPLは役に立たない

シングル・コアのマシン、もしくは、複数のスレッドを同時に待てないようなライブラリの場合、成立すると思います。
TPLについて私は把握していませんが、TPLがそのような正直役に立たないライブラリなのか、その文の筆者がマルチ・コアのことを知らないのかのどちらかのように感じます。
あ、ごめんなさい。もう一つ、私の英語力不足でちゃんと読めていない可能性もあります。(落とし穴があるような英文ではないとは思いますが...)

投稿2017/05/14 10:06

Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kazuya_

2017/05/14 13:05

ご回答ありがとうございます。具体的にコード例を教えていただければありがたいです。
Chironian

2017/05/14 14:31

英語の意味が分からないが質問だったのでは? 突然コード例の話が出ても何のことなのか理解できないです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問