Niestety, wybrałeś zły przykład. Kompilator JIT x86 nie wstawia metod, które zwracają zmienną. Nie jestem w 100% pewien, dlaczego, myślę, że ma to na celu uniknięcie powtarzających się problemów, gdy zmiennoprzecinkowe są konwertowane na 80-bitową wartość zmiennoprzecinkową w FPU. Dokładność wewnętrzna wynosi 80 bitów, ale te dodatkowe bity są odcinane, gdy 80-bitowa wartość zostanie obcięta z powrotem do 32-bitowej wartości, gdy zostanie przepłukana z powrotem do pamięci. Zbyt długie utrzymywanie wartości w jednostkach FPU zapobiega występowaniu tego obcinania i zmienia wynik obliczeń.
przypadku wymiany pływaka przez podwójne i skompilować ten kod:
static void Main(string[] args) {
Console.WriteLine(Cube(2.0));
}
Wtedy to kod maszynowy jest generowany, gdy optymalizator JIT jest włączone:
00000000 push ebp ; setup stack frame
00000001 mov ebp,esp
00000003 call 6DA2BEF0 ; Console.get_Out()
00000008 fld qword ptr ds:[010914B0h] ; ST0 = 8.0
0000000e sub esp,8 ; setup argument for WriteLine
00000011 fstp qword ptr [esp]
00000014 mov ecx,eax ; call Console.Out.WriteLine
00000016 mov eax,dword ptr [ecx]
00000018 call dword ptr [eax+000000D0h]
0000001e pop ebp ; done
0000001f ret
Nie tylko inline funkcji, był w stanie ocenić wyrażenia w czasie kompilacji. I bezpośrednio przekazuje wynik, wywołując Console.WriteLine (8.0). Całkiem dobrze, huh?
Użyj podwójnie, nie pływaj.
Interesujące ... ponieważ pracuję w XNA, gdzie * wszystko * jest zmiennoprzecinkowe! Nieco dotyczy ... –
* "Kompilator JIT x86 nie wbudowuje metod, które zwracają zmienną wartość." * - Czy jesteś tego absolutnie pewien? Przeszukałem wysokie i niskie wyniki i nie mogę znaleźć żadnych odniesień do tego. Najlepszą rzeczą, jaką znalazłem, była ta strona w Connect: https://connect.microsoft.com/VisualStudio/feedback/details/536781/unexpected-jit-inlining-behavior, która wydaje się sugerować, że funkcje zwracające float * do *, w rzeczywistości, inline. I ten (stary) artykuł sugeruje, że zasady dotyczące przymusu (a więc mogą być inne w praktyce) są takie same dla elementów pływających i podwójnych: http://blogs.msdn.com/b/davidnotario/archive/2005/08/08/449092. aspx –
@Andrew: reguły wprowadzania nie są udokumentowane, a jedynie w niektórych postach na blogu. Ważne, ponieważ muszą być w stanie to zmienić, aby poprawić fluktuacje bez łamania założeń wynikających z udokumentowanego zachowania. Mogę tylko udokumentować to, co widzę, jak robi się mój jitter x86. I zdecydowanie nie wprowadza wersji float tych metod. Czy widzisz inne zachowanie? –