La mayoría de los algoritmos de multiplicación y división de hardware pueden calcular las palabras altas y bajas de un producto de dos enteros, o tanto el cociente como el resto de la división de dos enteros, al mismo tiempo. En las principales RISC ISA, existen muchos enfoques diferentes para la multiplicación y división de enteros. (En esta publicación, solo estoy considerando números enteros y no matemáticas de punto flotante).
SMULL
y UMULL
, que se introdujeron en v3M. Estos almacenan la palabra alta y baja del producto de dos enteros de 32 bits en diferentes registros de 32 bits. También tiene muchas otras instrucciones de multiplicación de variantes. Sin embargo, no calcula el resto de una división.SMULL
y UMULL
almacena el producto de 64 bits de dos enteros de 32 bits en un registro de 64 bits. No tiene instrucción de multiplicación de 64 bits per se . Para multiplicar, haces una multiplicación-suma que suma el registro cero. Hay división de enteros, pero no módulo de enteros.MULH
, y , pero el Manual del conjunto de instrucciones de RISC-VMUL
recomienda que cuando a va seguido de a con los mismos operandos de origen, o de a con los mismos operandos de origen, las microarquitecturas puede fusionar estas operaciones en una sola operación en lugar de realizar dos por separado.DIV
REM
MULH
MUL
DIV
REM
Definitivamente es posible calcular el resultado completo de una multiplicación o división y el resto al mismo tiempo. ¡Varios RISC ISA tienen una instrucción para hacerlo! En teoría, si solo desea un resultado, puede establecer el destino del otro en el registro cero. ¿Por qué, entonces, ningún RISC ISA que miré tiene una instrucción para almacenar tanto el cociente como el resto en registros separados de propósito general, y por qué el ISA que encontré hace esto para las palabras altas y bajas de un producto? ARM A32, ¿dejarlo caer en la próxima revisión importante?
Estoy particularmente interesado en saber por qué los primeros chips RISC de mediados de los 80 eligieron este diseño. SPARC V8 no tenía un formato de instrucción con dos registros de origen y dos de destino y posiblemente no quería complicar su decodificador con otro formato. MIPS I: ¿cortar esquinas para adaptar instrucciones más complejas a una canalización RISC clásica?
Pero también me pregunto por qué las arquitecturas RISC modernas se han alejado de él. Supongo que ARM A64 lo hace de esa manera porque la suma y multiplicación de precisión fija es útil para la decodificación multimedia, con menos sobrecarga relativa cuanto más bits multiplique y, una vez que tenga eso, tiene sentido reutilizar los circuitos para la multiplicación ( solo agregue 0). Pero la documentación de RISC-V sugiere que el núcleo debe tener una sola operación que calcule ambos resultados, entonces, ¿por qué no, en un diseño de RISC, exponer eso en el ISA?
¿Se han publicado artículos que traten este tema? ¿O los diseñadores de estas arquitecturas han explicado alguna vez su razón de ser?
Por lo general, los requisitos comerciales para los diseños de procesadores están dirigidos a cumplir con los puntos de referencia sintéticos o las cargas de trabajo de aplicaciones del mundo real . Las características que no abordan ninguno de los dos son más difíciles de vender y, por lo tanto, es más probable que se dejen de lado.
Durante los años 80, el benchmark Dhrystone fue muy popular. Por lo general, esto se presentaría en un lenguaje de alto nivel, generalmente C. Dhrystone no incluye ninguna operación de resto. Por lo tanto, los diseñadores que busquen una puntuación Dhrystone alta podrían dejar de lado la operación restante para reducir unos picosegundos del tiempo del ciclo.
La mayoría de los lenguajes de alto nivel tienen operadores aritméticos separados para el cociente y el resto, muy pocos proporcionan operaciones estandarizadas para obtener ambos de una sola operación (¡en parte porque C y FORTRAN no tienen tuplas nativas!). Hasta hace poco, los compiladores no han sido buenos en el tipo de detección de optimización que les permitiría unir dos operaciones en una sola instrucción.
Si observamos el tipo de trabajo aritmético pesado para el que se han optimizado los procesadores, tiende a no preocuparse por los restos. Los grandes ejemplos son FFT y multiplicación de matrices para álgebra lineal. Esa es la razón por la cual los procesadores tienden a tener instrucciones de acumulación múltiple e instrucciones SIMD.
%
operaciones. La biblioteca estándar de C tiene div()
y ldiv()
, que devuelven estructuras de dos miembros y están destinadas a aprovechar el hardware que encuentra tanto el cociente como el resto a la vez. Los compiladores ahora generalmente pueden hacer esta optimización automáticamente, esas instrucciones son (como se señaló) menos comunes y /
han %
sido tan bien especificadas como div()
y ldiv()
desde C99. Realmente ya no hay una ventaja en usarlos, y me pregunto cuánto código hizo alguna vez.mod
lento y era mod
lento porque los algoritmos como Good-Thomas no se consideraban importantes?
Neil_ES
Davislor
broma
broma
Davislor
broma
TonyM
viejo contador de tiempo
viejo contador de tiempo
Davislor