2016. 3.15..
石立 喬

OpenMPとVisual C++による並列処理(4)

――― 画像反転(ネガ化)とグレイ化の簡単な画像処理で、OpenMPの効果を確認する -----

 具体的な応用として、画像処理を取り上げ、OpenMPの効果を調べる。画像サイズを640 x 480と、やや大きめにして、処理の所要時間を増やし、同じ測定を100回繰り返して、Visual C++のデフォルトとOpenMPの付加とで、実行時間を比較した。

調査方法
 処理内容 ---- 反転(ネガ化)とグレイ化
 ビルド構成 --- DebugとRelease
の組み合わせに対して、
     1)マルチライン ---- RGB値を、別行で計算(処理)してから、RGBマクロに代入する
     2)インライン ------ RGBマクロの中に上述の計算式を直接入れる
で画像処理を100回繰り返し、その都度の実行時間を測定し表示する。これを、Visual C++のデフォルトと、OpenMPを付加した場合とについて調べる。

Win32アプリケーションを使用する準備
 今回は、画像を表示するために、Win32アプリケーション(Win32プロジェクト)を使用する。Win32アプリケーションの詳細については、「Visual Studio Community 2015の使い方(3)」他を参照されたい。
 Visual C++のテンプレートで作成されるWin32のコードに対して、手を加えた場所は、プログラム起動時や、画面再描画時に呼び出されるcase WM_PAINTで、ここから、ユーザが作成するUserProgram関数を呼び出すことにし、ほとんどのプログラムをUserProgramに記述する。UserProgram内では、各種ハンドルなどWin32で共通的に用いられるものを除き、ローカル変数にはハンガリアン記法を使用しない。
 UserProgram関数以外では、
 1)プログラムの最初の部分で、OpenMPを使用するための<omp.h>をインクルードする(図1)。
 2)UserProgram関数のプロトタイプを宣言する(図1)。
 3)ウィンドウの表題とサイズを設定する(図2)。
 4)WM_PAINTで、UserProgramを呼び出すようにする(図3)。
の準備が必要である。


図1 <omp.h>のインクルードとUserProgram関数の宣言



図2 ウィンドウのタイトルとサイズを設定する



図3 UserProgramを呼び出すように設定する


UserProgramの内容
 作成したUserProgramの内容を図4〜図5に示す。図は、反転処理をマルチラインで行う例で示してあるが、その他の場合も、簡単に変更できる。時間の測定方法は、OpenMPに用意されている関数を使用した。224行のstart_timeの設定と、235行のend_timeの設定の間に、被測定処理を記述し、所要の実行時間elapsed_timeを求める。
 従来、時間の測定には、std::chronoのsystem_clock::now()を使っていたが、OpenMPのomp_get_wtime()と良く一致することを確認したので、今後はこれを使用する。
 プログラムは以下から成っている。
 1)原画像を読み込む
 2)原画像を一次元ピクセルデータ配列pdataに変換する
 3)pdataから原画像を生成して表示する(確認用であり、OKであれば、以後不要)
 4)グラフ表示のためのペンとブラシを用意する(ペンとブラシは同色とし、画像を背景に入れた場合は黄色が見やすい)
 5)実行時間測定(trialループ)を100回繰り返す
   ・被測定処理を実行して実行時間を測定する
   ・測定結果をaccumulated_timeに足し込む
   ・第一回目(trial == 1)なら処理結果画像を表示する(確認用であり、OKであれば、以後不要)
   ・第一回目、または10の倍数回目であれば、測定結果を文字(数値)で表示する
   ・すべての回の測定結果をグラフで表示する
 6)accumulated_timeを100で割って、実行時間の平均を表示する


図4 UserProgramの前半、準備部分




図5 UserProgramの後半、測定実行と表示部分


反転処理の実行時間の測定
 反転処理に使用するループの内容を、表1に示す。表1上欄(マルチライン)では、原画像の一次元ピクセルデータpdataを読み取って、GetRValue関数などでRGB値に分解し、それぞれを255から減算して、反転処理後のRGB値を得る。これを別行のRGBマクロでCOLORREF型にして、処理後のピクセルデータpdata1に格納する。
 表1の下欄(インライン)は、前記の計算を、RGBマクロに直接入れて1行にしたものである。

 表1 反転処理に使用した被測定処理

マルチライン
 インライン 


 図6は結果として得られた画面の一例を示す。処理後の反転画像を背景に(確認のためで、OKなら表示させないことができる)、左に文字での表示、右に棒グラフでの表示がある。実行時間の最小値が揃っていて、78μsecである。第1回目の測定と、途中の一部で、大きい値が出ている。これが、平均実行時間を押し上げている。


図6 反転処理(マルチライン)の実行速度をRelease構成のOpenMPで求めた画面


反転処理の実行時間の測定結果
 図6に例示した棒グラフを見やすくして、各種測定結果を以下に示す。棒グラフは、VC++のデフォルトでの測定結果を青色で、OpenMP使用時を赤色で重ねて表示している。Debug構成は、Release構成よりも実行時間が長いので、縦の長さを1/2に縮小してある。
◎Debug構成
 図7はマルチラインの場合の比較で、OpenMPにより実行時間が約50%に短縮している。図8はインラインの場合で、実行時間の絶対値では、VC++のデフォルトもOpenMPも、インラインの方がやや短く、OpenMPによる短縮率は同じ50%である。


図7 マルチラインの場合、OpenMPによる短縮率は約50%



図8 インラインはマルチラインよりやや速い、OpenMPによる短縮率は約50%で同じ


◎Release構成
 図9はマルチラインの場合の比較で、OpenMPを使用すると、実行時間が約35%に短縮している。図10はインラインの場合で、マルチラインと全く同じ結果である。Release構成では、マルチラインとインラインの差はない。


図9 Release構成でのマルチラインの結果



図10 Release構成でのインラインの結果、マルチラインと同じ


グレイ化処理の実行時間の測定
 画像をグレイ化(グレイスケール化)するには、一般にNTSCの規格の、
     d = 0.229 * r + 0.587 * g + 0.114 * b
を用いる。しかし、Release構成のOpenMP使用で、簡易的な
     d = (2 * r + 4 * g + b) / 7
と比較したところ、NTSC規格の70%の時間で済むことが分かったので、これを使用した。簡易方式は、4倍、2倍の単純な乗算のためか、7で割る処理があるにもかかわらず、高速であった。
 表2に、使用したプログラムを示す。

 表2 グレイ化処理に使用した被測定処理

マルチライン
 インライン 


グレイ化処理の実行時間の測定結果
 ここでも、Debug構成の場合は縦の長さを1/2に縮小してあるので、注意されたい。
◎Debug構成
 図11はマルチラインの場合の比較で、OpenMPを使用すると、実行時間が約48%に短縮している。図12はインラインの場合で、実行速度の絶対値では、VC++のデフォルトが約2.3倍に、OpenMPも約1.4倍に増大していて、インラインは使用すべきでない。


図11 マルチラインの結果、OpenMPによる短縮率は約48%



図12 インラインの結果、マルチラインより遅い、OpenMPによる短縮率は約30%


◎Release構成
 図13はマルチラインの場合の比較で、OpenMPを使用すると、実行時間が約49%に短縮している。図14はインラインの場合で、マルチラインとほとんど同じ結果である。


図13 マルチラインの結果、OpenMPによる短縮率は約49%



図14 インラインの結果、マルチラインとほとんど同じ


全ての回の結果を表示した棒グラフで分かったこと
 以上で紹介した棒グラフは、比較的安定したものを選んであるが、実際には、プログラムの実行ごとに大きく変動し、非常に突出して大きな実行時間が発生した回や、安定した一定レベルより大きく、しかもほぼ一定な実行時間が10回以上継続するような場合があった。その一例を図に示す。


図15 1回目が非常に大きかったり、途中で大きい値が続いたりすることもある


結 論
 画像処理の中でも、最も簡単な画像反転(ネガ化)とグレイ化について、OpenMP使用の効果を調べた。原画像のピクセル値をRGBに分解し、一定の計算の後にRGBマクロで再びピクセル値に変換するにあたって、計算とRGBマクロ使用とを別ラインで行うマルチライン方式と、RGBマクロの中に計算式を入れるインライン方式で比較した。ビルドはDebug構成とRelease構成の双方について行った。
 反転処理については、Release構成の場合、マルチラインもインラインも、実行時間は同じで、OpenMPによる短縮率は35%であった。マルチラインの方が、処理内容が分かり易いので、マルチラインを使用すべきである。Debug構成は遅いので、薦められない。
 グレイ化処理についても、Release構成の場合、マルチラインもインラインも同じで、OpenMPによる短縮率は49%であった。Debug構成はRelease構成より遅く、特にVC++の場合は、インラインがマルチラインの2倍以上になった。
 結論として、ここで調べた条件に限れば、画像反転、グレイ化のいずれの場合も、Release構成でマルチライン方式を用い、OpenMPを用いるのが良い。Visual C++のみの場合の半分以下の時間で済む。
 今回の調査で、プログラムの実行ごとに、結果が大きく異なるこを体験した。特に、OpenMP使用の1回目のバラツキが激しく、同じ処理を繰り返さない一般の用途に対しては、単なる参考に過ぎない結果かもしれない。











「Visual C++の勉強部屋」(目次)