2010-11-01 17 views
23

duplicados posibles: Hace
Is shifting bits faster than multiplying and dividing in Java? .NET?
Quick Java Optimization Question¿Debería cambiar de bit para dividir por 2 en Java?

muchos años en la universidad, he aprendido que de desplazamiento de bits a la derecha por uno consigue el mismo efecto que dividir por dos, pero es generalmente significativamente más rápido. No estoy seguro de cómo ha llegado Java en ese sentido, ya que hace 9 o 10 años aprendí sobre eso. ¿El compilador de Java convierte automáticamente una división por dos en una operación de cambio de bit, o debo realizar manualmente la operación de cambio de bit en el código?

+1

http://stackoverflow.com/questions/1514949/quick-java-optimization-question Aborda la multiplicación por dos, pero las respuestas son aplicables. –

+1

En general, si la operación A logra * exactamente * lo mismo que la operación B y lo hace más rápido, en algún lugar a lo largo de la línea B probablemente se optimice en A. El problema es cuando hay diferencias de casos fronterizos tales que uno no puede ser optimizado en el otro. En esos casos, debe: 1) evaluar si la diferencia en el rendimiento realmente importa (¡no hay optimización prematura!), 2) dar cuenta de los casos fronterizos (programe a su alrededor o demuestre que no serán golpeados, y 3) determine si existen ganancias y justifique la disminución en la legibilidad. –

+7

Estoy profundamente sadened por el espectro de respuestas que obtuvo esta pregunta. Primero, dividir por dos y desplazar uno a la derecha no arrojará el mismo resultado para los números negativos en todos los casos. En segundo lugar, donde el resultado desplazado es suficiente, es aproximadamente 10 a 20 veces más rápido que la división. Tercero, el compilador no optimizará esto porque en cualquier caso no trivial no podrá probar que el operando desplazado no es negativo. Ah, y las respuestas de la pregunta de multiplicación no cubren la división, ya que la situación con optimizadores es diferente xD – Durandal

Respuesta

52

A menos que esté trabajando en una tienda y una base de código donde el cambio de bit es común entonces, en mi humilde opinión, se está arriesgando a la ofuscación. Sí, las expresiones pueden ser equivalentes, pero lógicamente:

  • Un n00b podría confundirse por la sintaxis alternativa
  • Un viejo que no ha tenido que hacer ningún desplazamiento de bits desde la universidad, como yo, puede ser que consiga confundido
  • Si cambiaste un poco y sientes la necesidad de comentar sobre lo que acabas de hacer, entonces definitivamente estás apagado. Una simple división es auto-documentado y sería evidente para cualquiera que esté familiarizado con las matemáticas elementales
  • No vas a ser más astuto que un compilador para la optimización en algo tan sencillo así que no se molestó en tratar
  • Como buenas prácticas de codificación que es mejor para que el código sencilla/vainilla en vez de inteligente (er)

Todo esto es relativo y, de nuevo, realmente depende de las normas de su taller. Si a sus colegas les encanta cambiar de rumbo, entonces, por supuesto, avance y cambie de bit.

+29

Está en el ojo del espectador. ¿Por qué 'x * 2' está menos ofuscado que' x << 1'? ¿No significa 'x << 1' claramente' x * 2'? Es como decir hey 'x + 1' es más claro que' 1 + x'. – Pacerier

+7

Muchos programadores, especialmente desarrolladores menores, no están familiarizados con los cambios de bits, o no reconocerán de inmediato el intento. Este es básicamente un argumento de usabilidad para programadores que pueden funcionar en el código después de usted. – cacois

+0

Siempre puede comentar el código; y ¿por qué asumir el contexto en el que esto se está considerando cuando no se da ninguno? – Chris2048

10

La rutina de división para su CPU se encargará de esto. No hay necesidad de que lo hagas.

Esto se conoce como optimización prematura .

+14

¡Optimización anticipada! = Optimización prematura. Sí * la mayoría * del tiempo, cuando alguien quiere empezar a dar vueltas, probablemente sea un ejemplo de optimización prematura, pero ese no es siempre el caso. Personalmente, he visto casos en los que obtuve resultados notablemente mejores, porque tenía información que el compilador no tenía. Odio que todo el mundo siempre empiece a gritar "¡optimización prematura!" cada vez que se menciona algo como esto. –

+0

Estoy de acuerdo con eso, pero en general sería una optimización prematura. Y a menudo las optimizaciones no son tanto como encontrar algo que sea ligeramente más rápido y usarlo, sino que está encontrando una nueva forma de resolver un problema que requiere menos trabajo. – Malfist

+3

La división 'rutina' de su CPU es, de hecho, una instrucción, y siempre será alrededor de 20 veces más lenta que un cambio de bit. El 'compilador' puede reemplazar una división con un cambio, pero eso es todo. –

17

Los compiladores modernos son lo suficientemente inteligentes como para generar el código más rápido para divisiones por dos. Harán un cambio si es más rápido. Si lo que quieres lograr es una división por 2, usar una división aclarará tu código. Y evitará problemas cuando el número a dividir sea negativo.

+0

¿Evitar problemas o causarlos? He visto muchas más aplicaciones donde mantener el axioma '(n + d)/d == (n/d) + 1' era importante que donde' (-n)/d == - (n = d) 'tenía cualquier valor que sea. – supercat

11

Sí, esto es lo primero que hará cualquier persona que intente hacer optimizaciones de compilador (y lo ha hecho durante al menos 5 décadas), sin duda lo hace el compilador Java JIT, y probablemente tenga una es muy difícil encontrar cualquier compilador que no lo haga.

E incluso si no lo hicieran, todavía sería una micro-optimización prematura que debería evitarse a favor de que el código sea más claro.

+0

esta debería ser la respuesta, en lugar de responder la pregunta si Java lo hace o no, la gente baila si es una buena práctica o no ... – vach

Cuestiones relacionadas