コードの高速(最適化)検討手法に関して | 入門者フォーラム | フォーラム

iSUS に投稿されている記事の内容や、IA プラットフォーム上でのソフトウェア開発に関するトピックを開発者同士でディスカッションできる場としてフォーラムを公開しています。

運営ルールはフォーラムの利用案内をご覧ください。
フォーラムの使い方はこちら

 
フォーラムに投稿するにはログインが必要ですログイン

コードの高速(最適化)検討手法に関して

メンバー投稿

8:32 PM
2015年7月24日


yoshihingis

投稿数 54

1

 実際にコード作成で体験している事で、周囲に聞いても「同じような経験はあるけど、原因はよく分からない」という感じなので、質問させて頂きます。

 数千行の画像処理のコードを「将来、縦横2倍のピクセル数の画像を処理するので、単純に考えると処理時間は4倍になるので高速化したい」という要望があったとします。

 数千行の中の、あるサブルーチン(関数)が、数十行ながら、処理負荷が重く、Vtuneで見ても、MKLのクロックカウント関数で時間計測しても250msecほどで、結構なホットスポットだと分かりました。
 関数内部は、乗算や除算が多数あり、それをFor LOOPで回しているので、時間がかかっているようです。
 数千行のコードだとコンパイルに結構時間がかかるし、そこの関数だけの画像処理結果の一致性も確認しなければいけないので、引数などは全く同じにして、そこの関数をだけ切り出して、短いmain関数を追加して、検討しやすくしました。

 とここまでは良いのですが、切り出して短いコードで処理時間を測定してみると、250msecあった処理速度が、150msecと短くなっています。
 数千行のコード時に、そこの関数の入出力データを吐き出させておいて、それを切り出した短いコードの検証にも使用しているので、比較してみると、切り出して作成した短いコードの結果と完全一致しているので、なにかコードを切り出す時に、間違えた訳ではなさそうです。

 全く同じサブルーチンコードなのに、数千行のコードの場合と、短いコードで処理時間が変わったとなると、コンパイラが異なるバイナリを吐き出しているということになります。
 (アセンブラ等を確認すればそれは分かりますが・・)

 周囲に聞いても、「コンパイラが数千行のコード全体を見てコンパイルした場合と、局所的な短いコードを見てコンパイルした場合では、コンパイラの最適化が異なるからじゃないの?」という位の回答しか貰えません。

 実際、数千行のコードと、短いコードで、コンパイラの最適化が違う、または別の理由で異なるバイナリを吐き出す。といった事はあるのでしょうか?(もちろんコンパイラの最適化のオプションは同一設定が前提です。)

 もしコンパイラが最適化を変えてしまうのでしたら、コンパイル時間を短くして、効率よくコードの高速を行うために、ホットスポットの関数だけを切り出して短いコードで、数千行のコードと同じようなバイナリを吐き出させるような事は可能でしょうか?

 それとも元から、ホットスポットの関数だけを切り出して、短いコードで処理速度の高速化を検討するといた手法自体がナンセンスなのでしょうか?

 きわめて初歩的な質問ですが、ご教授いただければ、幸いです。

3:17 AM
2015年7月29日


iSUS編集部 – 菅原

投稿数 206

2

yoshihingis 様

お問い合わせありがとうございます。
元の数千行のソースが単一ソースか、複数ソースか不明ですが、対象となる関数を切り出して評価した際に、元の状態とパフォーマンスが異なるにはいくつかの要因が考えられるかと思います。

(1)インライン展開の有無。ループの階層が深い場所からの関数呼び出しはインライン展開されないことがあります。

(2)対象となる関数の呼び出す側の引数の渡し方によっては、関数のベクトル化をコンパイラーが判断できないことがあります。

(3)もとの大きなバイナリーでは、対象関数と呼び出し側が同じページ内に配置されず。状況によってはITLBのページウォークが発生する可能性があります。

総合的に考えると、今回遭遇されたパフォーマンスの違いは、ベクトル化による要因が大きいと考えられますが、大きなコードでは(2)の要因により、ベクトル化された対象関数とスカラー版の対象関数の両方が生成され、呼び出し側の引数の構成によって両者が呼ばれている可能性は無いでしょうか?
コンパイラーレポート (/Qopt-report-phase:vec, ipo)で対象関数がマルチバージョニングされていないか確認ください。
また、iSUSカンファレンスの「セミナー資料」で公開されている、「OpenMP* による並列化とベクトル化のためのパフォーマンス・エッセンシャル」の「OpenMP 4.0 によるベクトル化」のページ37以降で説明されている omp declare simd でこのような状況に対処する手法が紹介されています。

ホットスポットを切り出して高速化を行うことは決してナンセンスだとは思いませんが、コンパイラーはソースコードから開発者の意図までをすべて理解することはできないため、明示的にコンパイラーに知らせることが必要かと思います。

そのため、インテルコンパイラーでは、declare simd や omp declare simd といった新しい機能がサポートされています。

1:30 PM
2015年8月1日


yoshihingis

投稿数 54

3

 菅原様、ご回答ありがとうございます。現在、夏期休暇中なので来週、業務再開となったら、またご指摘頂いた点を確認して、結果などご報告させて頂きます。
 なお、数千行の元コードは複数ファイルです。
 コード作成者が私自身でなく他人が作成したものだけに、コンパイラ以前に、私自身がコード作成者の意図を読み取れない部分も有ります。
 コード作成者自身が、コードの高速化を、インテルツールなどを使用して行うほうが効率が良いはずなのですが、なかなか、そういう体制にならないのが悩みところです。