【问题标题】:How can I tell if the function's intrinsic version is used from the disassembly?如何从反汇编中判断是否使用了函数的内在版本?
【发布时间】:2010-10-29 14:32:33
【问题描述】:

我正在尝试在 VS2010 中优化我的锻炼应用程序。 基本上我在核心循环中有几个 sqrt、pow 和 memset。 更具体地说,这就是我所做的:

// in a cpp file ...
#include <cmath>

#pragma intrinsic(sqrt, pow, memset)
void Simulator::calculate() 
{
  for( int i=0; i<NUM; i++ )
  {
    ...
    float len = std::sqrt(lenSq);
    distrib[0] = std::pow(baseVal, expVal);
    ...
    clearQuad(i); // invokes memset
  }
}

构建后,反汇编显示,例如,sqrt 调用仍编译为“call _CIsqrt(0x####)”,无论是否启用 /Oi 标志,都没有任何变化。

谁能解释一下如何启用内部版本以及如何通过反汇编代码验证它? (我还在项目设置中启用了 /O2。)

谢谢

编辑: 通过添加 /fp:fast 解决了问题。以 sqrt 为例,内部版本使用单个“fsqrt”来替换标准版本“call __CIsqrt()”。可悲的是,就我而言,内在版本慢了 5%。

非常感谢 Zan Lynx 和 mch。

【问题讨论】:

    标签: c++ visual-studio optimization pragma


    【解决方案1】:

    使用 C++ std 命名空间可能会导致编译器不使用内在函数。尝试从您的sqrtpowmemset 调用中删除std::

    #pragma intrinsic 的 MSDN 库文档提供了一个测试内在函数是否真正被使用的示例:使用 -FAs 标志编译并查看生成的 .asm 文件。

    查看调试器中的反汇编,正如您似乎已经在做的那样,也应该显示内在而不是call

    【讨论】:

    • 1)我删除了 std:: 并且仍然得到相同的结果。 2)如果编译器提供了sqrt,pow和memset,我是否必须在开头包含
    • 我认为 cl 对 CRT 函数始终有效,无论您是否包含它们的标题都是相当宽容的。可能没关系,但这是 x86 还是 x64?你试过在命令行上手动编译文件吗?
    • 代码架构是 x86。我还没有尝试手动编译命令行。此外,我刚刚在没有#include 的情况下对其进行了测试:编译失败。输出显示 sqrt 需要一个定义。
    • 编辑: /fp:fast 选项解决了这个问题。 +1 投票支持您的帮助。无论如何,我什至不需要写“#pragma intrinsic(sqrt, pow, memset)”这一行来启用内在函数?更令人惊讶的是,在我的例子中,内在版本实际上比 std::sqrt 慢一点。
    • 嗯,我虽然 /fp:fast 包含在 /O2 中。据我了解,如果您使用 /Oi,则不需要#pragma intrinsic。
    【解决方案2】:

    您正在编译为机器代码而不是 .NET CLR。对吧?

    如果您编译为 .NET,则代码在通过 JIT 运行之前不会被优化。到那时,.NET 就有了自己的内在函数和其他将要发生的事情。

    如果您要编译为本机机器码,您可能想要使用/arch option/fp:fast option

    【讨论】:

      猜你喜欢
      • 2017-08-06
      • 2018-04-13
      • 1970-01-01
      • 2018-11-22
      • 1970-01-01
      • 1970-01-01
      • 2023-03-31
      • 2022-12-12
      • 1970-01-01
      相关资源
      最近更新 更多