为啥 System.Math 有 Sin、Cos 等的外部方法?

Posted

技术标签:

【中文标题】为啥 System.Math 有 Sin、Cos 等的外部方法?【英文标题】:Why System.Math has extern methods for Sin, Cos, etc?为什么 System.Math 有 Sin、Cos 等的外部方法? 【发布时间】:2009-10-28 22:38:22 【问题描述】:
[MethodImpl(MethodImplOptions.InternalCall)]
public static extern double Sin(double a);

这是什么原因?

【问题讨论】:

【参考方案1】:

MethodImplOptions.InternalCall 表示该方法由公共语言运行时本地实现。这对数学运算很有意义,因为它们通常针对目标平台进行了大量优化。例如,在 x86 架构中,有一条指令可以计算正弦和余弦。托管实现不太可能直接利用此类指令。

【讨论】:

感谢 Mehrdad,您的本机是指 C++ 或 NGEN'ed C#,还是其他? @Joan:不,我不是指 NGENed。当调用这样的方法时,CLR 使用它自己的实现(很可能是 C++ 或程序集)。方法实现是 CLR 代码的一部分。 谢谢,我有 2 个问题可能有点不相关。 1、像Sin这样的方法是不是分别为这么多不同的平台写的?以及编译器和 CLR 如何确保在编译时和运行时实际上存在对它的内部调用。这会在 IL 中可见吗?还是这一切都在幕后魔术? 1.最有可能的是,他们已针对每种架构对其进行了优化。即使他们只是简单地在非托管 C 标准库中调用 sin,该调用也会由编译 CLR 代码库的编译器进行优化。 2. 属性在 IL 中当然是可见的,但是方法的 body 根本没有 IL。正如我所说,该方法是 CLR 的一部分,因此它对已实现的方法有深入的了解。当 JIT 编译器看到这样的方法时,会用自己的方法替换调用。 我认为,根据我从Rotor 源代码中看到的情况,Microsoft 的实现大部分是用C++ 实现的;当然它是不受管理的。【参考方案2】:

很可能是因为实现是优化的本机代码。

【讨论】:

【参考方案3】:

实现是在本机中完成的。这不只是Sin,也看看常见的字符串操作。

CLR 知道这些方法,并维护一个“调用表”。当它看到来自 Math.Sin 的调用时,它通过“查找”调用表将其重定向到本机实现。如果你想找到更多,在转子源中搜索ecall.cpp,或者直接去here(谷歌代码搜索)。

【讨论】:

以上是关于为啥 System.Math 有 Sin、Cos 等的外部方法?的主要内容,如果未能解决你的问题,请参考以下文章

MATLAB /simulink中, sin导数后为啥cos(0)不等于1? 结果如图所示:

为啥 sin() 不返回正确的值?

C语言中已知sin、cos的值怎么求角度?比如sina=0.2,那么a=?请求有经验的帮帮忙!

从 sin/cos 转换中恢复角度

三角函数全公式

c++ libstd同时计算sin和cos