2008-11-18 8 views
8

Mientras miraba una pregunta de micro-optimización que hice ayer (here), encontré algo extraño: una declaración or en Java está ejecutando ligeramente más rápido que buscar un valor booleano en una matriz de booleanos.¿Por qué este código con varias instrucciones "o" es más rápido que usar una tabla de búsqueda en Java?

En mis pruebas, ejecutando los siguientes algoritmos en long valores de 0 a 1 mil millones, alg1 es aproximadamente un 2% más rápido. (He alterado el orden en que se prueban los algoritmos, y obtengo los mismos resultados). Mi pregunta es: ¿Por qué es alg1 más rápido? Hubiera esperado que alg2 fuera ligeramente más rápido ya que usa una tabla de búsqueda, mientras que alg1 tiene que ejecutar 4 comparaciones y 3 o operaciones para el 75% de las entradas.

private final static boolean alg1(long n) 
{ 
    int h = (int)(n & 0xF); 
    if(h == 0 || h == 1 || h == 4 || h == 9) 
    { 
    long tst = (long)Math.sqrt(n); 
    return tst*tst == n; 
    } 
    return false; 

} 

private final static boolean[] lookup = new boolean[16]; 
static 
{ 
    lookup[0] = lookup[1] = lookup[4] = lookup[9] = true; 
} 
private final static boolean alg2(long n) 
{ 
    if(lookup[(int)(n & 0xF)]) 
    { 
    long tst = (long)Math.sqrt(n); 
    return tst*tst == n; 
    } 
    else 
    return false; 
} 

Si tienes curiosidad, este código está probando si un número es un cuadrado perfecto, y utiliza el hecho de que los cuadrados perfectos deben terminar en 0, 1, 4, 9 o en hexadecimal.

Respuesta

6

Cargar algunos datos aleatorios generalmente es más lento que un pequeño código no ramificado.

Todo depende de la arquitectura del procesador, por supuesto. Su primera declaración if podría implementarse como cuatro instrucciones. El segundo puede necesitar verificación nula del puntero, comprobación de límites, así como la carga y comparación. Además, más código significa más tiempo de compilación y más posibilidades de que la optimización se impida de alguna manera.

+0

Una búsqueda simple en el nivel del procesador es generalmente bastante más rápida que incluso una pequeña serie de cálculos. Pensando g es la verificación de límites/otra sobrecarga que Java agrega para administrar el proceso. –

+0

límites comprobando FTL! –

1

De acuerdo con this article, acceder a los elementos de la matriz es "2 o 3 veces más costoso que acceder a elementos que no son de matriz". Su prueba muestra que la diferencia puede ser aún mayor.

3

Supongo supongo que el problema es que la verificación de rango para la matriz y si la búsqueda de matriz se implementa como una llamada a método. Eso ciertamente eclipsaría 4 comparaciones directas. ¿Has mirado el código de bytes?

0

Es una pieza interesante de código, pero el 2% es una diferencia realmente pequeña. No creo que pueda concluir mucho de eso.

+0

Sí, no es lo suficientemente significativo como para cambiar la forma en que escribo el código o algo así ... Solo tenía curiosidad, en un nivel intelectual, por qué este podría ser el caso. – Kip

0

En el ejemplo actual, que coinciden en que la comprobación de límites es probablemente lo que está haciendo (¿por qué la JVM no optimiza esto es más allá de mí - el código de ejemplo podría manera determinista se puede demostrar que no se desborde ...

Otra posibilidad (especialmente con tablas de búsqueda más grandes) es la latencia de caché ... Depende del tamaño de los registros de los procesadores y cómo la JVM elige usarlos, pero si la matriz de bytes no se mantiene totalmente en el procesador, entonces usted Veremos un golpe de rendimiento en comparación con un OR simple a medida que la matriz se inserta en la CPU para cada control.

Cuestiones relacionadas