【发布时间】:2011-03-29 21:49:34
【问题描述】:
我发现了以下问题:Is fastcall really faster?
没有给出 x86 的明确答案,所以我决定创建基准。
代码如下:
#include <time.h>
int __fastcall func(int i)
{
return i + 5;
}
int _stdcall func2(int i)
{
return i + 5;
}
int _tmain(int argc, _TCHAR* argv[])
{
int iter = 100;
int x = 0;
clock_t t = clock();
for (int j = 0; j <= iter;j++)
for (int i = 0; i <= 1000000;i++)
x = func(x & 0xFF);
printf("%d\n", clock() - t);
t = clock();
for (int j = 0; j <= iter;j++)
for (int i = 0; i <= 1000000;i++)
x = func2(x & 0xFF);
printf("%d\n", clock() - t);
printf("%d", x);
return 0;
}
如果在 MSVC 10 中没有优化结果是:
4671
4414
使用最大优化fastcall 有时会更快,但我猜这是多任务处理的噪音。这是平均结果(iter = 5000)
6638
6487
stdcall 看起来更快!
以下是 GCC 的结果:http://ideone.com/hHcfP
同样,fastcall 输了比赛。
这是fastcall情况下的部分反汇编:
011917EF pop ecx
011917F0 mov dword ptr [ebp-8],ecx
return i + 5;
011917F3 mov eax,dword ptr [i]
011917F6 add eax,5
这是给stdcall:
return i + 5;
0119184E mov eax,dword ptr [i]
01191851 add eax,5
i 是通过ECX 传递的,而不是堆栈,而是保存在正文中的堆栈中!所以所有的效果都被忽略了!这个简单的函数可以只使用寄存器来计算!它们之间并没有真正的区别。
谁能解释fastcall 的原因是什么?为什么它不提供加速?
编辑:经过优化,这两个函数都是内联的。当我关闭内联时,它们都被编译为:
00B71000 add eax,5
00B71003 ret
这看起来确实是一个很好的优化,但它根本不尊重调用约定,所以测试是不公平的。
【问题讨论】:
-
呵呵,不要指望内联代码尊重调用约定。这是公平的,不打电话是内联的重点。
-
大多数编译器都有
don't inline flag -
@Hans Passant 我关闭了内联,编译器仍然不遵守约定
-
Andrey,你可以尝试通过以下方式调用你的函数: template
__declspec(noinline) F NOIL( F f ) { return f; } 例如。 x = NOIL(func)(x & 0xFF);那么,如果您使用完全优化进行编译,fastcall 会更快! (可能是因为他们叫fastall) -
2019 年的结果可能不会在这里。请参阅下面的帖子。
标签: c++ optimization