背景
下面是一个用 C++ 编写的数值软件的关键循环,主要通过其中一个成员比较两个对象:
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% 的运行时开销。我不得不质疑:
问题
为什么编译器会产生不同的汇编代码?
为什么生产的装配速度较慢?
编辑: 通过实施@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:precise /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