午後わてんのブログ

ベランダ菜園とWindows用アプリ作成(WPFとC#)

Parallelクラスを使ってもっと速く減色

昨日処理時間短縮の続き
Parallelクラスを使ってもっと速く
 
Parallelを使ってforを書くとそのループは並列処理される!
なのでCPUコア数に比例して速度が上がるはず
 
お店でいうと
レジが1個だったのがたくさん増えた感じ
従業員(CPU)に余裕があれば可動するレジも増えて
客(処理)の待ち時間が減る
 
普通のforだとこうで
for (int x = 0; x < w; ++x)
{
処理
}
xが0のときの処理 → xが1のときの処理 → xが2のときの処理 → …
 
Parallelのforを使うと
Parallel.For(0, w, x =>
{
処理
});
xが0のときの処理 → xがnのときの処理 → …
xが1のときの処理 → xがnのときの処理 → …
xが2のときの処理 → xがnのときの処理 → …
っていくつか同時に行うのがParallel、並列処理
CPUに余裕がある限りたくさん並列処理されるのかも
並列数の上限を指定することもできるみたい
 
 
減色処理ではあちこちにforを使っているところがあるので
いくつか組み合わせて試してみた
イメージ 1
変換ボタン増えた内容は
変換1 普通に変換
変換2 変換一覧表を使って変換
変換3 変換一覧表+意味のないParallel
変換4 変換一覧表+xループの中を別メソッドにしてParallel
変換5 変換一覧表+変換4から、xループ自体を別メソッドにしてyループもParallel
変換6 変換一覧表+変換4から、yループもParallel
変換7 yループだけParallel
変換8 xループだけParallel
変換9 x,y両方のループをParallel
変換10 変換一覧表をParallel、それ以外は普通
変換11 x,y両方のループと変換一覧表もParallel
変換10-2 変換10より変換一覧表のParallelを細かく
 
x、yのループってのは
画像の横がx縦がyの位置でそれぞれのループ
for (int y = 0; y < h; ++y)
{
for (int x = 0; x < w; ++x)
{
処理
}
}
だいたいこうなっていて、yのなかにxのループが入っている
 
計測結果
イメージ 2
画像の大きさは2048x1536ピクセル、パレットの色数は4
この条件で一番速かったのは2.232秒の変換7はyループだけParallelにしたもの
でもParallelを使ったものはどれも2秒台でほとんど差がない、計測も1回なので誤差もある
 
変換一覧表作成に
Parallelを使った変換10は5.205
使っていない変換2は4.909
これは何回試してもParallelのほうが遅い
 
変換4,5,6は変換一覧表を使うParallelで
変換7,8,9は変換一覧表を使わないParallel
これで7,8,9のほうが速いのは少し悔しいねえ、せっかく一覧表作ったのに…
 
二重になっているx,yのループも片方だけParallelと両方Parallelの違いが7,8,9の差なんだけど、誤差程度の差なので片方だけでよかったみたい
 
x,y,変換一覧表すべてをParallelにした変換11がいまいち速くないのも変換一覧表を使っているせいかなあ
 
変換一覧表を使ったほうが誤差程度だけど遅くなるのは残念だけど前回の2倍速くなった
 
 
パレットの色数16色
19.016 変換1 普通に変換
6.137 変換2 変換一覧表を使って変換
18.296 変換3 変換一覧表+意味のないParallel
3.799 変換4 変換一覧表+xループの中を別メソッドにしてParallel
3.708 変換5 変換一覧表+変換4から、xループ自体を別メソッドにしてyループもParallel
3.618 変換6 変換一覧表+変換4から、yループもParallel
6.461 変換7 yループだけParallel
6.716 変換8 xループだけParallel
6.494 変換9 x,y両方のループをParallel
5.622 変換10 変換一覧表をParallel、それ以外は普通
3.198 変換11 x,y両方のループと変換一覧表もParallel
5.617 変換10-2 変換10より変換一覧表のParallelを細かく
 
これはすべてを使い切った変換11が最速!
普通に変換より
19.016/3.198≒5.95倍速くなって
変換一覧表だけを使ったものより
6.137/3.198≒1.92倍速くなった
 
 
4色と16色で比較
4色 16色
6.342 19.016 変換1 変換
4.909 6.137 変換2 一覧表
16.92 18.296 変換3
2.563 3.799 変換4 一覧表+Parallel変換
2.430 3.708 変換5 一覧表+Parallel変換
2.473 3.618 変換6 一覧表+Parallel変換
2.232 6.461 変換7 Parallel変換
2.297 6.716 変換8 Parallel変換
2.230 6.494 変換9 Parallel変換
5.205 5.622 変換10 Parallel一覧表+変換
2.704 3.198 変換11 Parallel一覧表+Parallel変換
5.219 5.617 変換10-2 Parallel一覧表2+変換
 
変換4~6と7~9がパレットの色数で逆転しているのは一覧表が効いているねえ
 
 
ParallelなしのCPU使用率
イメージ 3
Parallelを使わないとアプリ単体で35.7%しか使われない
PhenomⅡX3 720は3CoreCPUなので
3Core使い切った状態が100%なので
35.7%ってことは1Coreしか使われていないのがわかる
これはもったいない
 
Parallel使用時のCPU使用率
イメージ 4
アプリ単体で82.1%まで上がった!
他のアプリも少しは使っているので全体では100%近く行ったのかも
変換11はすぐ終わるからうまく撮れないので
 
 
イメージ 5
変換8実行でほぼ100%使っているの確認できた
 

 

 
気になったのが変換7と9は処理中にパソコンの動きが遅くなる、マウスカーソルがカクカクになるくらい遅くなる
他の処理では全くカクカクならない
 
変換7~9はほとんど同じ処理で、違うところはyループをParallelにしているかどうか
for (int y = 0; y < h; ++y)
{
for (int x = 0; x < w; ++x)
{
処理
}
}
 
7はyだけParallel化、8はxだけParallel化、9はx,yともにParallel化
ってことはParallelのforの中にforがあると無理し過ぎな状態になるのかも
Parallelクラスには並列処理数を制限するのがあって
ParallelOptions options = new ParallelOptions();
options.MaxDegreeOfParallelism = Environment.ProcessorCount;
MaxDegreeOfParallelismに上限数を指定すればいいみたい
ここでは使っているパソコンのCPUのコア数を返してくれる
Environment.ProcessorCount
を使って指定した
これを変換7のところに書いて試したんだけどカクカクは直らず
しかも上限を1に指定してもCPUを100%使い切っていた、無視されている?
 
 
 
処理速度が上がって気分いいんだけど、Parallelのことはよくわかっていない
なんとなくできている感じ
 
いままでのforを単純にParallelに書き換えて実行したら

f:id:gogowaten:20191212121821p:plain

797行目がforからParallel.Forに書き換えたところ
それ以外は元のままで実行したら

f:id:gogowaten:20191212121835p:plain

なんかエラーでた
bitmapColorには画像に使われている色のどれかが入っているはずなんだけど
画像にはない色が入ってしまっているってことかなあ
よくわからん
ググった先のお手本を見るとParallel.Forの中はシンプルに書いてあるので
真似してxループの部分を別メソッドにしてみる
 

f:id:gogowaten:20191212121846p:plain

xループの中を別メソッドにしてParallelconverter
これをxループの中から呼び出すことにしたら
エラーでなくなった、けどよくわからん
排他処理ってのが関係するのかなあ
 
 
今回ので変換処理時間はこれでいいかな、満足
Parallelすごい
並列処理ってもっと難しいものだと思っていた、実際難しいんだろうけど僕みたいにわかっていない人でも、Parallelクラスを使えばそれなりの結果が出るのがすごい
 
 
参照したところ
ループをParallelクラスで並列処理にするには?[C#VB]:.NET TIPS - @IT
http://www.atmarkit.co.jp/ait/articles/1706/21/news021.html
C# 大量並行処理する Parallel.For,Parallel.ForEach でハングアップする対策。 並行スレッド数制限。:にえの居酒屋 - ブロマガ
http://ch.nicovideo.jp/nie/blomaga/ar730749
並列処理ライブラリ - C# によるプログラミング入門 | ++C++; // 未確認飛行 C
http://ufcpp.net/study/csharp/lib_parallel.html
 
 
コード全部はGitHub
アプリダウンロードはヤフーボックス
 
関連記事
2018/05/09、パラレルの他にポインタも使うと速くなる
BitmapSourceでの画像処理速度、unsafe、ポインタ、ビルドモード ( ソフトウェア ) - 午後わてんのブログ - Yahoo!ブログ
https://blogs.yahoo.co.jp/gogowaten/15497771.html
 
2018/03/14
減色変換一覧表を使って処理時間を短縮してみた ( ソフトウェア ) - 午後わてんのブログ - Yahoo!ブログ
https://blogs.yahoo.co.jp/gogowaten/15412874.html