2010-07-31 7 views
6

Me gustaría saber si .NET JITter alineará recursivamente funciones pequeñas llamadas desde otras funciones pequeñas.¿El .NET JIT integra una pequeña función que llama a otra función pequeña?

Sólo por ejemplo:

public static float Square(float value) 
{ 
    return value * value; 
} 

public static float Cube(float value) 
{ 
    return Square(value) * value; 
} 

Si llamo Cube de alguna parte, ¿verdad en línea todo el camino, o voy a terminar con una llamada a la función Square?

Y, en caso afirmativo, ¿con qué profundidad recurrirá para hacer la alineación? (Supongamos que estoy lo suficientemente loco como para implementar una función Quartic o Quintic de la misma manera.)

Respuesta

10

Desafortunadamente, ha elegido un mal ejemplo. El compilador x86 JIT no incorpora métodos que devuelven float. No estoy 100% seguro de por qué, creo que lo hace para evitar consistentemente problemas cuando el flotador se convierte a un valor de coma flotante de 80 bits en la FPU. La precisión interna es de 80 bits, pero esos bits adicionales se cortan cuando el valor de 80 bits se trunca de nuevo a un valor de 32 bits cuando se vacía de nuevo a la memoria. Mantener el valor en la FPU demasiado tiempo impide que ocurra este truncamiento y cambia el resultado del cálculo.

Si reemplaza flotador doble y compilar este código:

static void Main(string[] args) { 
    Console.WriteLine(Cube(2.0)); 
} 

A continuación, se genera el código máquina cuando está activado el optimizador JIT:

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 

No sólo inline las funciones, fue capaz de evaluar las expresiones en tiempo de compilación. Y pasa directamente el resultado llamando a Console.WriteLine (8.0). Bastante bien ¿eh?

Use doble, no flotante.

+1

Interesante ... porque estoy trabajando en XNA donde * todo * es una carroza! Ligeramente concerniente a ... –

+0

* "El compilador JIT x86 no incorpora métodos que devuelven float." * - ¿Estás absolutamente seguro de esto? He buscado alto y bajo y no puedo encontrar ninguna referencia para respaldar esto. Lo mejor que encontré fue esta página en Connect: https://connect.microsoft.com/VisualStudio/feedback/details/536781/unexpected-jit-inlining-behavior que parece implicar que las funciones devuelven float * do *, de hecho, en línea. Y este (antiguo) artículo implica que las reglas de coacción (por lo que tal vez sean diferentes en la práctica) son las mismas para carrozas y dobles: http://blogs.msdn.com/b/davidnotario/archive/2005/08/08/449092. aspx –

+1

@Andrew: las reglas de publicación no están documentadas, solo se insinúa en algunas publicaciones de blog. Importante, porque necesitan poder cambiar esto para mejorar el jitter sin romper las suposiciones hechas del comportamiento documentado. Solo puedo documentar lo que veo que hace mi jitter x86. Y definitivamente no incluye la versión flotante de estos métodos. ¿Ves un comportamiento diferente? –

Cuestiones relacionadas