我在FP踏进的C库的超越数学函数的组件,MSVC:严格模式。 他们似乎都遵循相同的模式,下面是发生了什么sin
。
首先是来自一个名为“disp_pentium4.inc”文件中的调度程序。 它检查如果变量___use_sse2_mathfcns
已被设置; 如果是这样,来电__sin_pentium4
,否则调用__sin_default
。
__sin_pentium4
(在“sin_pentium4.asm”)开始由参数从的x87 FPU转移到XMM0注册,进行使用SSE2指令的计算中,并且将结果早在FPU。
__sin_default
(在“sin.asm”)保持x87堆栈上可变和简单地调用fsin
。
因此,在这两种情况下,操作数推x87堆栈上和它返回为好,使之透明的来电,但如果___use_sse2_mathfcns
定义,在SSE2而不是的x87实际执行的操作。
这种行为是对我来说很有趣,因为的x87超越函数是臭名昭著的具有取决于实施的行为稍有不同,而SSE2的给定代码块要经常给重现的结果。
有没有一种方法来确定肯定的,无论是在编译或运行时,该SSE2代码路径将被使用? 我不精通写作组装,因此,如果这涉及编写任何组件,代码示例将不胜感激。
我发现通过math.h中的缜密侦查答案 这是通过一个称为方法控制_set_SSE2_enable
。 这是记录一个公共符号在这里 :
启用或禁用使用SIMD流技术扩展2(SSE2)在CRT数学例程指令。 (因为SSE2默认情况下启用此功能不可用在x64架构。)
这使得aforementionned ___use_sse2_mathfcns标志被设置为所提供的值,从而有效地使能或禁止使用_pentium4 SSE2例程。
说明文档中提到这只会影响某些超越函数,但是看一下拆卸,这似乎影响到他们的每一个人。
编辑:步入每个函数显示,他们都可以在SSE2,除了以下:
开方是最大的罪犯,但它的琐碎使用内部函数在SSE2来实现。 对于其他人,有可能除了使用第三方库没有简单的解决办法,但我可能可以不用。
为什么不使用自己的库,而不是C运行的? 这将提供一致性的多台电脑甚至更有力的保证(大概是C运行时提供了一个DLL,可能在时间上略有变化)。
我会建议CRlibm 。 如果您已经针对SSE2,只要你不打算改变FPU的舍入模式,你是在理想的条件下使用它,你不会找到一个更准确的实现。
简短的回答是,你不能告诉你的代码的某些东西的图书馆将做,除非你还涉及库实现的具体细节。 这会使代码完全不可移植的 - 即使是两个不同的构建相同的编译器可能会改变图书馆的内部。
当然,如果便携性不是问题,然后使用extern <type> ___use_sse2_mathfcns;
并检查它是否真正显然会工作。
我预计,如果该处理器具有SSE2和你使用的是现代的足够图书馆,它将使用SSE2尽可能。 但是要说可以肯定的是一个不同的问题。
如果这是你的关键代码,然后实现自己的超越函数,并使用这些 - 这是保证相同的结果的唯一途径。 或者,使用一些合适的联汇编器(或超越)代码来计算所选sin
, cos
等的值,并比较这些与sin()
和cos()
函数库提供。