c# - Math.Atan2 和 FPATAN

标签 c# .net x86 trigonometry

我正在用 C# 编写一些数学代码,强制它在发布时针对 x86 进行编译、优化,并且我正在查看 windbg 中的反汇编。它通常非常好,经常写出比我更好的汇编(并不是说我很擅长汇编,但就是这样)。

但是,我注意到这个函数:

static void TemporaryWork()
{
    double x = 4;
    double y = 3;
    double z = Math.Atan2(x, y);
}

正在生成此反汇编:

001f0078 55              push    ebp
001f0079 8bec            mov     ebp,esp
001f007b dd05a0001f00    fld     qword ptr ds:[1F00A0h]
001f0081 83ec08          sub     esp,8
001f0084 dd1c24          fstp    qword ptr [esp]
001f0087 dd05a8001f00    fld     qword ptr ds:[1F00A8h]
001f008d 83ec08          sub     esp,8
001f0090 dd1c24          fstp    qword ptr [esp]
001f0093 e86e9ba66f      call    clr!GetHashFromBlob+0x94e09 (6fc59c06) (System.Math.Atan2(Double, Double), mdToken: 06000de7)
001f0098 ddd8            fstp    st(0)
001f009a 5d              pop     ebp
001f009b c3              ret

即使您不是 x86 高手,您也会注意到其中的一些奇怪之处:有一个对 System.Math.Atan2 的调用。就像在函数调用中一样。

但实际上有一个 x86 操作码可以做到这一点:FPATAN

为什么 JITer 在有实际的汇编指令执行操作时调用函数?我认为 System.Math 基本上是 native 汇编指令的包装器。那里的大部分操作都有直接汇编操作码。但事实显然并非如此?

有没有人知道为什么 JITer 不能/不能执行这种相当明显的优化?

最佳答案

可以从this answer追查原因, 它显示了这些数学函数是如何被抖动映射的。

这会将您带到 clr/src/classlibnative/float/comfloat.cpp,ComDouble::Atan2() 函数。这解释了原因:

   // the intrinsic for Atan2 does not produce Nan for Atan2(+-inf,+-inf)
   if (IS_DBL_INFINITY(x) && IS_DBL_INFINITY(y)) {
       return(x / y);      // create a NaN
   }
   return (double) atan2(x, y);

因此,这是修复不符合 CLI 的 FPU 行为的解决方法。

关于c# - Math.Atan2 和 FPATAN,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16129014/

相关文章:

c# - 为什么我的表在 ASP.NET 中没有内容?

c - InterlockedExchange() 类型函数/内部函数的 MSDN 文档不一致?

C#图表显示所有标签

未提供 C# XML 序列化 int 标记值

c# - asp.net mvc 5 DropDownList nullable int default option not null

x86 - 如何像 SSE movlps/movhps 一样将 AVX/AVX2(YMM) 寄存器中的较低或较高值存储到内存中?

performance - "fast"到底是怎样的现代CPU?

c# - 索引时出现错误的请求错误

c# - LINQ 查询到 Group 并获得 Sum

c# - Newtonsoft.json JSON.NET