バックグラウンド
C++ で記述された数値計算ソフトウェアの次の重要なループは、基本的に 2 つのオブジェクトをそのメンバーの 1 つによって比較します。
for(int j=n;--j>0;)
asd[j%16]=a.e<b.e;
a
およびb
クラスは次のASD
とおりです。
struct ASD {
float e;
...
};
この比較を軽量メンバー関数に入れることの影響を調査していました。
bool test(const ASD& y)const {
return e<y.e;
}
そしてそれを次のように使用します:
for(int j=n;--j>0;)
asd[j%16]=a.test(b);
コンパイラはこの関数をインライン化していますが、アセンブリ コードが異なり、10% を超えるランタイム オーバーヘッドが発生するという問題があります。私は質問する必要があります:
質問
コンパイラが異なるアセンブリ コードを生成するのはなぜですか?
生成されたアセンブリが遅いのはなぜですか?
編集: 2 番目の質問は、@KamyarSouri の提案 (j%16) を実装することで回答されました。アセンブリ コードはほぼ同じに見えます ( http://pastebin.com/diff.php?i=yqXedtPmを参照)。唯一の違いは、18、33、48 行目です。
000646F9 movzx edx,dl
素材
- テストコード: http://pastebin.com/03s3Kvry
- /Ox /Ob2 /Ot /arch:SSE2 を使用した MSVC10 のアセンブリ出力:
- コンパイラのインライン バージョン: http://pastebin.com/yqXedtPm
- 手動インライン バージョン: http://pastebin.com/pYSXL77f
- 違いhttp://pastebin.com/diff.php?i=yqXedtPm
このグラフは、私のコードの 50 回のテスト実行に対する FLOP/s (倍率まで) を示しています。
プロットを生成する gnuplot スクリプト: http://pastebin.com/8amNqya7
コンパイラ オプション:
/Zi /W3 /WX- /MP /Ox /Ob2 /Oi /Ot /Oy /GL /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /Gm- / EHsc /MT /GS- /Gy /arch:SSE2 /fp:正確 /Zc:wchar_t /Zc:forScope /Gd /analyze-
リンカー オプション: /INCREMENTAL:NO "kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "comdlg32.lib" "advapi32.lib" "shell32.lib" "ole32.lib" "oleaut32. lib" "uuid.lib" "odbc32.lib" "odbccp32.lib" /ALLOWISOLATION /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /SUBSYSTEM:CONSOLE /OPT:REF /OPT:ICF /LTCG /TLBID :1 /DYNAMICBASE /NXCOMPAT /MACHINE:X86 /ERRORREPORT:QUEUE