我发现了以下问题:快打真的更快吗?
没有给出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
6487stdcall看起来更快!
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 这看起来确实是很棒的优化,但是它根本不尊重调用约定,所以测试是不公平的。
发布于 2011-03-29 22:17:27
__fastcall很久以前就被引进了。当时,Watcom C++在优化方面击败了微软,许多评审员将其基于寄存器的呼叫约定作为(可能的)原因之一。
微软的回应是添加了__fastcall,从那以后他们就一直保留着它--但我认为他们做的还不够多,以至于能够说“我们也有一个基于注册的呼叫约定……”他们的偏好(特别是自32位迁移以来)似乎是对__stdcall的偏爱。他们已经投入了大量的工作来改进他们的代码生成,但是(很明显)用__fastcall做的工作并不多。有了片上缓存,在寄存器中传递东西的收益就没有以前那么大了。
发布于 2011-03-29 22:07:02
你的微基准会产生不相关的结果。__fastcall在SSE指令中有特定的用途(请参阅XNAMath),clock()甚至不是一个用于基准测试的远程定时器,__fastcall也存在于多个平台,例如Itanium和其他一些平台,不仅仅是x86,此外,除了printf语句之外,您的整个程序还可以有效地被优化,从而使__fastcall或__stdcall的相对性能变得非常、非常无关紧要。
最后,你忘了意识到很多事情都是以传统的方式完成的主要原因--遗产。在编译器内联变得像今天这样具有侵略性和有效性之前,__fastcall很可能是非常重要的,而且没有编译器会像依赖它的程序那样删除__fastcall。这使__fastcall成为生活中的一个事实。
发布于 2011-03-29 21:56:08
几个原因
__fastcall节省了一些堆栈移动工作,但是在不修改堆栈的情况下,可以减少可在函数中使用的寄存器数量。在大多数情况下,如果__fastcall速度更快,这个函数就足够简单,在任何情况下都可以内联,这意味着它在实际软件中并不重要。(这是不经常使用__fastcall的主要原因之一)
附带注意:阿农的回答有什么问题?
https://stackoverflow.com/questions/5479362
复制相似问题