2010-04-11 10 views
16

Estoy trabajando en un dispositivo GPU que tiene latencia de enteros de división muy alta, varios cientos de ciclos. Estoy buscando optimizar divisiones.¿División de enteros más rápida cuando se conoce el denominador?

Todas las divisiones por denominador que están en un conjunto {1,3,6,10}, sin embargo el numerador es un valor positivo en tiempo de ejecución, aproximadamente 32000 o menos. debido a restricciones de memoria, la tabla de búsqueda puede no ser una buena opción.

¿Puedes pensar en alternativas? He pensado en calcular las inversas del punto flotante y usarlas para multiplicar el numerador.

Gracias

PS. gracias a la gente hackear cambio de bit es realmente genial. para recuperarse de redondeo, lo uso siguiente segmento C:

sistemas
// q = m/n 
q += (n*(j +1)-1) < m; 

Respuesta

9
a/b=a*(1/b) 
x=(1<<16)/b 
a/b=(a*x)>>16 

¿Puedes construir una tabla de búsqueda para los denominadores? ya que dijo numeradores 15 bits, puede utilizar 17 para los turnos si todo está sin signo de 32 bits:

a/b=a*((1<<17)/b)>>17 

Cuanto mayor sea el cambio de menor será el error de redondeo. Puede hacer un control de fuerza bruta para ver cuántas veces, si es que hay alguna, esto es realmente incorrecto.

+0

sí, eso es lo suficientemente pequeño. Gracias – Anycorn

+0

obtengo un error de redondeo, pero tengo una forma de recuperar el resultado correcto. Gracias – Anycorn

+0

Para el error de redondeo, puede probar el clásico agregar la mitad antes de dividir, que en este caso sería a/b = (a * ((1 << 16)/b) + (1 <<15))>> 16 – drawnonward

6

El estándar incrustado corte para esto es para convertir una división entera por N en una multiplicación de punto fijo por 1/N.

Suponiendo 16 bits, 0.33333 se puede representar como 21845 (decimal). Multiplica, dando un producto entero de 32 bits, y bajando 16 bits.

Es casi seguro que encontrará algún error de redondeo (truncamiento). Esto puede o no ser algo con lo que puedas vivir.

PODRÍA merecer la pena observar detenidamente su GPU y ver si puede codificar manualmente una rutina de división de enteros más rápida, aprovechando su conocimiento del rango restringido del numerador.

+0

truncamiento sería un problema, necesito valores reales. Sin embargo, creo que puedo lidiar con esto comprobando el redondeo y aumentando el resultado si se encuentra – Anycorn

+0

gracias. Esto es muy útil para mí – Anycorn

+0

En la mayoría de los casos, se puede evitar el error de redondeo multiplicando por un valor que es uno más grande que el recíproco redondeado (21846 en el caso de 1/3 con 16 bits). – supercat

6

, el libro, "Hacker's Delight" by Henry Warren, tiene un capítulo completo dedicado a la división de enteros por constantes, incluidas las técnicas que transforman una división de enteros en una serie de operaciones de multiplicación/desplazamiento/suma.

Esta página calcula los números mágicos para la multiplicación/SHIFT/ADD operaciones:

Cuestiones relacionadas