MethodImplOptions.InternalCall
Das bedeutet, dass die Methode tatsächlich in der in C ++ geschriebenen CLR implementiert ist. Der Just-in-Time-Compiler konsultiert eine Tabelle mit intern implementierten Methoden und kompiliert den Aufruf der C ++ - Funktion direkt.
Für einen Blick auf den Code ist der Quellcode für die CLR erforderlich. Sie können dies von der SSCLI20-Distribution erhalten . Es wurde um den .NET 2.0-Zeitrahmen herum geschrieben. Ich habe festgestellt, dass die Implementierungen auf niedriger Ebene Math.Pow()
für spätere Versionen der CLR immer noch weitgehend genau sind.
Die Nachschlagetabelle befindet sich in clr / src / vm / ecall.cpp. Der Abschnitt, der für relevant ist, Math.Pow()
sieht folgendermaßen aus:
FCFuncStart(gMathFuncs)
FCIntrinsic("Sin", COMDouble::Sin, CORINFO_INTRINSIC_Sin)
FCIntrinsic("Cos", COMDouble::Cos, CORINFO_INTRINSIC_Cos)
FCIntrinsic("Sqrt", COMDouble::Sqrt, CORINFO_INTRINSIC_Sqrt)
FCIntrinsic("Round", COMDouble::Round, CORINFO_INTRINSIC_Round)
FCIntrinsicSig("Abs", &gsig_SM_Flt_RetFlt, COMDouble::AbsFlt, CORINFO_INTRINSIC_Abs)
FCIntrinsicSig("Abs", &gsig_SM_Dbl_RetDbl, COMDouble::AbsDbl, CORINFO_INTRINSIC_Abs)
FCFuncElement("Exp", COMDouble::Exp)
FCFuncElement("Pow", COMDouble::Pow)
// etc..
FCFuncEnd()
Wenn Sie nach "COMDouble" suchen, gelangen Sie zu clr / src / classlibnative / float / comfloat.cpp. Ich werde Ihnen den Code ersparen, sehen Sie selbst. Grundsätzlich wird nach Eckfällen gesucht und dann die CRT-Version von aufgerufen pow()
.
Das einzige andere interessante Implementierungsdetail ist das FCIntrinsic-Makro in der Tabelle. Dies ist ein Hinweis darauf, dass der Jitter die Funktion möglicherweise als intrinsisch implementiert. Mit anderen Worten, ersetzen Sie den Funktionsaufruf durch eine Gleitkomma-Maschinencode-Anweisung. Was nicht der Fall ist Pow()
, gibt es keine FPU-Anweisung dafür. Aber sicherlich für die anderen einfachen Operationen. Bemerkenswert ist, dass dies die Gleitkomma-Mathematik in C # wesentlich schneller machen kann als der gleiche Code in C ++. Überprüfen Sie diese Antwort auf den Grund dafür.
Der Quellcode für die CRT ist übrigens auch verfügbar, wenn Sie über die Vollversion des Verzeichnisses Visual Studio vc / crt / src verfügen. Sie werden jedoch an die Wand gehen pow()
, Microsoft hat diesen Code von Intel gekauft. Es ist unwahrscheinlich, einen besseren Job als die Intel-Ingenieure zu machen. Obwohl die Identität meines Highschool-Buches doppelt so schnell war, als ich es versuchte:
public static double FasterPow(double x, double y) {
return Math.Exp(y * Math.Log(x));
}
Aber kein echter Ersatz, da es Fehler aus 3 Gleitkommaoperationen akkumuliert und sich nicht mit den verrückten Domänenproblemen befasst, die Pow () hat. Wie 0 ^ 0 und -Infinity, die zu einer beliebigen Potenz erhoben werden.
InternalCall
mit einemextern
Modifikator verwechselt sind (da diese widersprüchlich zu sein scheinen ), lesen Sie bitte die Frage (und die daraus resultierenden Antworten) , die ich zu genau dieser Sache gepostet habe.