¿Por qué la división de hardware tarda tanto más que la multiplicación en un microcontrolador? Por ejemplo, en un dsPIC, una división toma 19 ciclos, mientras que la multiplicación toma solo un ciclo de reloj.
Revisé algunos tutoriales, incluidos el algoritmo de división y el algoritmo de multiplicación en Wikipedia. Aquí está mi razonamiento.
Un algoritmo de división, como un método de división lenta con restauración en Wikipedia, es un algoritmo recursivo. Esto significa que los resultados (intermedios) del paso k
se utilizan como entradas para el paso k+1
, lo que significa que estos algoritmos no se pueden paralelizar. Por lo tanto, se necesitan al menos n
ciclos para completar la división, mientras que n
hay una cantidad de bits en un dividendo. Para dividendos de 16 bits, esto equivale a al menos 16 ciclos.
Un algoritmo de multiplicación no necesita ser recursivo, lo que significa que es posible paralelizarlo. Sin embargo, hay muchos algoritmos de multiplicación diferentes, y no tengo ni idea de cuál puede ser utilizado por los microcontroladores. ¿Cómo funciona la multiplicación en un hardware / microcontrolador?
Encontré un algoritmo multiplicador Dadda , que se supone que toma solo un ciclo de reloj para terminar. Sin embargo, lo que no entiendo aquí es que el algoritmo de Dadda procede en tres pasos, mientras que los resultados del paso 1 se usan en el paso 2, etc. De acuerdo con esto, esto tomaría al menos tres ciclos de reloj para terminar.
fuente
Respuestas:
Un divisor se asigna mucho menos elegantemente al hardware típico. Tome los FPGA Lattice ICE40 como ejemplos.
Comparemos dos casos: este multiplicador de 8x8 bits a 16 bits:
y este divisor que reduce los operandos de 8 y 8 bits a un resultado de 8 bits:
(Sí, lo sé, el reloj no hace nada)
Puede encontrar una descripción general del esquema generado al asignar el multiplicador a un FPGA ICE40 aquí y el divisor aquí .
Las estadísticas de síntesis de Yosys son:
multiplicar
dividir
Vale la pena señalar que el tamaño del verilog generado para un multiplicador de ancho completo y un divisor de división máxima no son tan extremos. Sin embargo, si observa las imágenes a continuación, notará que el multiplicador tiene quizás una profundidad de 15, mientras que el divisor se parece más a 50; ¡La ruta crítica (es decir, la ruta más larga que puede ocurrir durante la operación) es lo que define la velocidad!
De todos modos, no podrá leer esto para obtener una impresión visual. Creo que las diferencias en complejidad son posibles de detectar. ¡Estos son multiplicadores / divisores de ciclo único!
Multiplicar
Multiplique en un ICE40 (advertencia: ~ 100 imágenes de Mpixel)
Dividir
( Dividir en un ICE40 ) (advertencia: ~ imagen de 100 Mpixel)
fuente
La división lenta es inherentemente iterativa, por lo que tiende a tomar más tiempo. Hay algoritmos de división lenta algo más rápidos que los simples, que usan tablas de búsqueda. El algoritmo SRT produce dos bits por ciclo. Un error en dicha tabla fue la causa del infame error Pentium FDIV (ca. 1994). Luego están los llamados algoritmos de división rápida.
Por supuesto, en principio, podría simplemente usar una gran tabla de búsqueda para calcular el producto o el cociente de dos números, y así obtener resultados en un solo ciclo, pero eso tiende a volverse poco práctico rápidamente a medida que aumenta el número de bits por número.
fuente
Podemos tener múltiples capas de lógica por ciclo de reloj, pero hay un límite, exactamente cuántas capas de lógica podemos tener y cuán complejas pueden ser esas capas dependerá de nuestra velocidad de reloj y nuestro proceso de semiconductores.
Afaict la mayoría de la multiplicación en computadoras usa una variante de multiplicación binaria larga. La multiplicación binaria larga implica
Así que echemos un vistazo a la implementación de esto en hardware.
Así que vamos a calcular cuántas etapas lógicas necesitamos para un multiplicador 8x8 con resultados de 16 bits. Para simplificar, supongamos que no intentamos optimizar por el hecho de que no todos los resultados intermedios tienen bits en todas las posiciones.
Supongamos que se implementa un sumador completo en dos "etapas de puerta".
Entonces, alrededor de 46 etapas lógicas en total. La mayoría de los cuales se gastan sumando los dos últimos resultados intermedios.
Esto podría mejorarse aún más explotando el hecho de que no todos los resultados intermedios tienen todos los bits presentes (eso es básicamente lo que hace el multiplicador dada), mediante el uso de un sumador anticipado de acarreo para el paso final. Al agregar 7 números para producir 3 en lugar de tres para producir dos (reduciendo el número de etapas al precio de más puertas y puertas más anchas), etc.
Sin embargo, todos estos detalles son menores, lo importante es que el número de etapas necesarias para multiplicar dos números de n bits y producir un resultado de 2n bits es aproximadamente proporcional a n.
Por otro lado, si miramos los algoritmos de división, encontramos que todos tienen un proceso iterativo donde.
Entonces, el número de etapas lógicas requeridas para implementar la división es aproximadamente proporcional a n al cuadrado.
fuente
Se puede hacer un algoritmo de división (de hecho, cualquier algoritmo) en un ciclo de reloj. Si está dispuesto a pagar los transistores adicionales y la tasa de reloj más baja permitida.
Supongamos que tiene un conjunto de puertas que implementa un ciclo de reloj de un algoritmo de división de varios ciclos existente. Para hacer que el algoritmo sea de ciclo único, use varias etapas de hardware (similar a la utilizada en una etapa del algoritmo de ciclo múltiple), con la salida de una etapa alimentando la etapa siguiente.
Por supuesto, la razón para no hacerlo de esa manera es que usa muchos transistores. Por ejemplo, para una división de 16 bits, puede usar casi 16 veces más transistores. Además, tener más etapas de compuertas reduce la frecuencia de reloj máxima permitida (porque hay más etapas de retraso de propagación).
fuente
Los algoritmos prácticos de división se basan en conjuntos numéricos que convergen al cociente.
Existen métodos aditivos, como la no restauración o SRT, que funciona agregando o eliminando 2 ^ N al cociente y, en consecuencia, agregue o elimine el divisor 2 ^ N * al resto parcial hasta que haya convergido a cero.
Existen métodos multiplicativos, como Newton-Raphson o Goldshmidth, que son métodos de búsqueda de raíces donde la división se calcula como la inversa de la multiplicación.
Los métodos aditivos dan uno o unos pocos bits por ciclo. Los métodos multiplicativos duplican el número de bits para cada ciclo, pero necesitan una aproximación inicial, a menudo obtenida con una tabla constante.
Las denominaciones "lenta" y "rápida" son engañosas, ya que la velocidad real depende de la cantidad de bits, cuánto hardware se dedica a la función (y un multiplicador rápido es muy grande) ...
La división es más lenta que la multiplicación porque no existe un método directo y paralelo para calcularla: o hay una iteración, o se copia el hardware para implementar la iteración como bloques en cascada (o canalizados).
fuente
Esta no es una pregunta electrónica. En el mejor de los casos, es una pregunta de computadora, mejor dirigida a Stack Overflow.
Ver, por ejemplo, aquí: ¿Es la multiplicación más rápida que la división flotante?
En realidad, es una pregunta de la vida real: ¿por qué la división tarda mucho más que la multiplicación?
¿Cuál preferirías calcular en papel?
o
La división lleva más tiempo que la multiplicación porque es más difícil de hacer .
fuente