午後わてんのブログ

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

WPF、Parallel.Invoke、並列実行は昨日より速く

昨日の続き
目的は昨日と同じで画像処理を考えて、RGB順に並んだbyte型配列から、RGBそれぞれの配列を作成、それぞれの最小値、最大値、平均値(double型)を求める
イメージ 3
 
 
結果
イメージ 2
一番上が昨日、一番下が今回最速で
昨日より2倍くらい速くできた
 
今回のアプリのダウンロード先
 
CPU使用率
イメージ 1
録画で20%くらい使っていて3コアCPUなので
100%使い切ってもアプリ単体だと最大でも80%
 
いくつか試した中で一番速くできた方法は
RGBごと別々の処理を書いて、それをParallelクラスのInvokeで同時実行
 
RGB配列からRの配列作成と最小値、最大値、平均値を求める
イメージ 4
これは昨日の普通に書いたTestAをRだけの処理にしただけ
 
GBのぶんも書いて
イメージ 5
Rとほとんど一緒
違うのは結果を入れる変数が違うのと
forの開始インデックスが違うだけ(491,508行目)
あとはこの3つをParallelクラスのInvokeで同時実行する
 
TestD
1行で書くと

f:id:gogowaten:20191213141001p:plain

改行入れるとこう?
イメージ 7
Invokeのカッコの中に同時実行させたい処理をカンマで区切って入れると同時実行されるみたい
Invoke(処理A, 処理B, 処理C, …)
Parallel.Invokeの使い方は
ここ見てなんとなくできるようになった
Parallel.Invoke素晴らしい
 
 
これで昨日より2倍くらい速くできたけど、RGB3つの処理がほとんど同じなのでムダな気がする、1つにできないかなと思ってできたのがこれ

f:id:gogowaten:20191213141028p:plain

なんか余計にめんどくさくなった気がする
引数にrefを付けないとうまく動かないのがめんどくさい
これをParallel.Invokeで実行する
TestC
イメージ 9
こっちは確実にめんどくさくなった
これで速くなればよかったんだけど
結果は
イメージ 2
1.26秒
速いんだけどTestDに比べたら少し遅くなった
 
 
イメージ 10
グラフで比較
イメージ 11
TestA~D、PはParallelのP、Oldは以前の方法
LINQを使ったB、BPが遅いのがわかる
 
B、BPを外して比較
イメージ 12
200万のときはCP、DPは僅差な感じだけど
500万になると差が開いた
それにしてもOldから比べるとずいぶん速くなった
 
今回のアプリ
イメージ 13
メモリの使用量が多すぎなので一部のボタンは無効化してある
チェック入れると有効になる
数値はピクセル数で実際に処理される配列の要素数
RGBそれぞれになるので、この3倍になる
 
 
メモリ使用量
イメージ 15
200万のときは220MBくらい使用
これくらいなら平気
 
500万だと
イメージ 14
500MB前後、これはちょっと…
これが1000万だと1GB以上になって
メモリ搭載量8GBのPCだときつい
8kの3300万…「それ以上いけない」
 
 
処理が終わったあとも何故かメモリを開放してくれない
イメージ 16
これは200万の処理が終わった直後
150MBも掴んだまま
 
処理終了2分後くらい
イメージ 17
開放したけど5分くらい経っても開放しないこともあった
 
いちおう
イメージ 18
すべての処理が終わったところで
配列のクリアとガベージコレクション
とか実行しているけど意味ないのかも
 
デバッグ時とリリースバージョン
イメージ 19
リリースバージョンのほうがだいぶ速くなる
昨日の記事はデバッグで計測、今日の比較はリリースバージョン
 
 
参照したところ
連載! とことん C#: 第 32 回 並列 (Parallel) で行こう 言語: C#
https://code.msdn.microsoft.com/windowsdesktop/32-Parallel-af4950ae
 
 
 
 
ギットハブ
 
 
関連記事
前回は昨日2018/11/30
LINQのMin、Max、Average使ってみたけど遅い、画像処理には向かない ( ソフトウェア ) - 午後わてんのブログ - Yahoo!ブログ
https://blogs.yahoo.co.jp/gogowaten/15774616.html