Visual Studio 中的强制 CPU 体系结构
Posted
技术标签:
【中文标题】Visual Studio 中的强制 CPU 体系结构【英文标题】:Enforced CPU architecture in Visual Studio 【发布时间】:2015-08-31 12:56:53 【问题描述】:在 Visual Studio(我使用的是 2010)中,您可以使用例如指定 CPU 架构 /arch:SSE2.
查看生成的汇编代码以进行简单的 sin(x) 计算,它确实使用 SSE,但编译器还插入了带有 fallback 的运行时检查在 CPU 不支持 SSE 的情况下使用 x87 指令。此运行时检查可能会非常频繁地执行并降低性能。
是否有任何标志或设置可以省略此运行时检查并让程序因“非法指令”而崩溃?
【问题讨论】:
如果使用/Oi
选项集(使用内在函数)进行编译会发生什么。更多关于该选项的信息:msdn.microsoft.com/en-us/library/f99tchzc.aspx
谢谢,但它仍然执行运行时检查。被检查的全局变量名为 ___use_sse2_mathfcns。我试着用谷歌搜索它,但不幸的是,点击率很少。
可能是因为 sin() 是 CRT 的一部分,所以项目的编译选项不会影响它。我想即使您设置了/arch:IA32
,您也会看到 SSE 实现。
@stgatilov 这是我建议使用内在函数的原因之一。如果内在存在,则不需要 CRT 中的内置。是的,您会在 IA32 代码中看到 SSE 检查。为每个代码生成选项组合构建一个 CRT 是不切实际的,因此他们改为进行运行时检查是有意义的。
【参考方案1】:
正如 stgatilov 所怀疑的,sin
的实现是 C 运行时库的一部分,不受 /arch
选项的直接影响。但是,您可以使用几个选项来强制使用特定的实现。
如果您使用带有/arch:SSE2
标志的/fp:fast
选项,则将使用特定于SSE 的C 运行时库函数。使用/fp:fast
的缺点是生成的浮点代码对整个翻译单元的一致性较差,而不仅仅是对sin
的调用。
另一个更有针对性的替代方案是/Qfast_transcendentals
,这将导致编译器始终内联x87 fsin
指令。这有使sin
不太符合的缺点,但只有sin
和任何其他具有您可能正在使用的x87 等效指令的超越函数。 fsin
指令的一个显着限制是它仅适用于 -2^63 到 +2^63 范围内的源操作数。
我应该指出,SSE2 CPU 支持的“运行时检查”对性能的影响微乎其微。这只是一个比较和分支。由于比较总是以相同的方式解决分支总是被正确预测,因此只需要几个周期。与计算正弦的成本相比,这不算什么。
最后,另一种可能的解决方案是升级您的编译器。默认情况下,Visual Studio 2015 在使用 /arch:SSE2
(这也是默认设置)时调用 sin
的特定于 SSE2 的实现。
【讨论】:
你打败了我。我使用的是 VS2015,我得到了不同的行为。加载了我拥有 VS2010 的虚拟机,我可以确认您在该环境中观察到的内容(以及 OP 看到的内容)。在我的 VS2015 上,我也能够使用/fp:precise
并简单地启用内在函数 (/Od),它生成了对 __libm_sse2_sin_precise
的 SSE2 特定调用(与 VS2010 相比行为不同)
我的理解是 x87 fsin
指令比使用 SSE2 从泰勒级数计算 sin
慢
@MichaelPetch 可能是,我从未测试过实际性能,只是 SSE2 运行时检查是否仍然存在。希望最初的发布者能够检查一下,在不影响结果的情况下,哪种替代方案实际上可以为他带来最佳表现。
谢谢,很高兴确认VS2015解决了问题,我会考虑升级。虽然分支预测确实会喜欢这种运行时检查,但也有对全局变量的内存访问。这种访问将对性能产生更显着的影响,尤其是在我使用大量 RAM 并遭受大量缓存未命中的情况下。以上是关于Visual Studio 中的强制 CPU 体系结构的主要内容,如果未能解决你的问题,请参考以下文章
Visual Studio中是否有可变命名约定的规则,可以在开发时强制执行?