MethodImplOptions.InternalCall
즉, 메소드는 실제로 C ++로 작성된 CLR로 구현됩니다. JIT (Just-In-Time) 컴파일러는 내부적으로 구현 된 메소드가있는 테이블을 참조하고 C ++ 함수에 대한 호출을 직접 컴파일합니다.
코드를 살펴 보려면 CLR의 소스 코드가 필요합니다. SSCLI20 배포판 에서 얻을 수 있습니다 . .NET 2.0 시간대를 중심으로 작성되었으며, 저수준 구현을 찾았습니다.Math.Pow()
은 CLR의 이후 버전에서 여전히 정확히 정확 .
조회 테이블은 clr / src / vm / ecall.cpp에 있습니다. 관련 섹션은 Math.Pow()
다음과 같습니다.
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()
"COMDouble"을 검색하면 clr / src / classlibnative / float / comfloat.cpp로 이동합니다. 코드를 아끼지 않고 직접 살펴보십시오. 기본적으로 코너 케이스를 확인한 다음 CRT 버전을 호출합니다.pow()
.
흥미로운 다른 구현 세부 사항은 테이블의 FCIntrinsic 매크로입니다. 그것은 지터가 기능을 내장 함수로 구현할 수 있다는 힌트입니다. 즉, 함수 호출을 부동 소수점 기계 코드 명령어로 대체하십시오. 에 해당하지 않는 경우 Pow()
에는 FPU 명령이 없습니다. 그러나 다른 간단한 작업에는 확실히 적용됩니다. 주목할 점은 이것이 C #의 부동 소수점 수학을 C ++의 동일한 코드보다 훨씬 빠르게 만들 수 있다는 것입니다. 을 이유를 .
그런데 CRT의 소스 코드는 전체 버전의 Visual Studio vc / crt / src 디렉토리가있는 경우에도 사용할 수 있습니다. 당신이 벽에 충돌거야 pow()
하지만를, 마이크로 소프트는 인텔에서 해당 코드를 구입했습니다. 인텔 엔지니어보다 더 나은 일을하는 것은 쉽지 않습니다. 고등학교 책의 정체성은 내가 시도했을 때 두 배 빠르지 만 :
public static double FasterPow(double x, double y) {
return Math.Exp(y * Math.Log(x));
}
그러나 3 개의 부동 소수점 연산에서 오류가 누적되고 Pow ()가 가진 이상한 도메인 문제를 처리하지 않기 때문에 진정한 대안은 아닙니다. 0 ^ 0과 같이 -Infinity는 모든 힘을 올렸습니다.
InternalCall
와 혼동하는 경우extern
( 충돌하는 것처럼 보임) 이 문제 에 대해 게시 한 질문 (및 결과 답변) 을 참조하십시오 .