【问题标题】:Is fastcall really faster?fastcall真的更快吗?
【发布时间】:2011-01-12 10:04:36
【问题描述】:

fastcall 调用约定真的比 cdecl 等其他调用约定快吗? 是否有任何基准可以显示调用约定如何影响性能?

【问题讨论】:

标签: c++ performance calling-convention fastcall


【解决方案1】:

调用约定(至少在 x86 上)并没有真正对速度产生太大影响。在 Windows 中,_stdcall 被设为默认值,因为它为非平凡的程序产生了切实的结果,因为与_cdecl 相比,它通常会导致更小的代码大小。 _fastcall 不是默认值,因为它所产生的差异远没有那么明显。您在通过寄存器传递参数中弥补的内容在效率较低的函数体中丢失(如 Anon 之前提到的)。如果被调用的函数立即需要将所有内容溢出到内存中以进行自己的计算,则通过传入寄存器不会获得任何收益。

但是,我们可以整天发表理论想法——对您的代码进行基准测试以获得正确答案。 _fastcall 在某些情况下会更快,而在其他情况下会更慢。

【讨论】:

    【解决方案2】:

    在现代 x86 上 - 不。在 L1 缓存和内联之间没有 fastcall 的位置。

    【讨论】:

    • 如果一个函数是内联的,它既不是 fastcall 也不是 cdecl 也不是任何其他调用约定。
    • 没错。从 L1 获取是寄存器上的 1 个周期 - 在大多数情况下,它低于噪声水平,甚至很难可靠地对其进行基准测试。无论如何,应该内联几个循环调用是重要区别的函数。
    • 我必须同意这一点 - 任何简单到可以从 fastcall 中受益的函数都会从内联中受益更多。
    • 除了内联并不总是可行的。想想由两个不同方实现的代码中的回调......
    【解决方案3】:

    这取决于平台。例如,对于 Xenon PowerPC,它可能是一个数量级的差异,因为在堆栈上传递数据时会出现加载命中存储问题。我凭经验将 cdecl 函数的开销计时为大约 45 个周期,而 fastcall 的开销约为 4 个。

    对于无序的 x86(Intel 和 AMD),影响可能要小得多,因为无论如何寄存器都被隐藏和重命名。

    答案确实是您需要在您关心的特定平台上自行对其进行基准测试。

    【讨论】:

      【解决方案4】:

      fastcall 调用约定真的比 cdecl 等其他调用约定快吗?

      我相信微软在 x86 和 x64 上实现fastcall 涉及在寄存器中而不是堆栈中传递前两个参数。

      由于它通常会节省至少四次内存访问,是的,它通常更快。但是,如果所涉及的函数是 register-starved 并且因此很可能将它们写入堆栈上的本地,则不太可能显着增加。

      【讨论】:

      • 在 x64 中只有一种调用约定
      • @phuclv 究竟有一种调用约定?在 Windows x86_64 mingw-w64 C++11 上,__attribute__((fastcall)) 编译并生成 fastcall 兼容函数。此外,架构不能标准化调用约定,因为它们是编译器功能。
      • @VladislavToncharov 当然我特别提到了 64 位窗口上的调用约定,因为这个问题是关于“微软的实现”。调用约定由平台定义,而不是编译器。在没有外部组件的情况下进行交互时,Windows 上的 GCC 仍然必须遵循 Windows 的约定
      猜你喜欢
      • 2012-06-25
      • 1970-01-01
      • 2011-05-06
      • 2014-03-08
      • 1970-01-01
      • 2011-09-28
      • 1970-01-01
      • 2018-11-08
      • 1970-01-01
      相关资源
      最近更新 更多