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中是否有可变命名约定的规则,可以在开发时强制执行?

Visual Studio“任何 CPU”目标是啥意思?

Visual Studio 强制桌面 API

如何强制 Visual Studio 在 https 中运行网站

在 Visual Studio 和 VIM 中强制编码样式

BOOST_FOREACH宏强制方法退出Visual Studio命名空间