¿Qué tan rápido se ejecuta una multiplicación o división de 64 bits en un FPGA?

Cuando se utiliza un FPGA normal como Xilinx Spartan 3 o Virtex 5, ¿cuántos ciclos se necesitan para ejecutar una multiplicación o división de punto flotante de 64 bits de doble precisión?

Según tengo entendido, la FPGA no tiene una FPU dura y debe crear una utilizando las bibliotecas IEEE estándar u otros materiales. Esto significa que no se ejecutará en un solo ciclo, por lo que estoy buscando una estimación aproximada para comparar el rendimiento de una CPU de 100 MHz con una FPGA Spartan/Virtex de 100 MHz.

Estoy principalmente interesado en los operadores de punto flotante, pero si tiene experiencia con operaciones con números enteros, también lo agradecería.

Primero, vale la pena aclarar la pregunta: usted habla de MPY / división de 64 bits, lo que implicaría una multiplicación / división de enteros de 64 bits; luego menciona FPU, lo que implica un punto flotante de doble precisión. Los detalles de la respuesta diferirán para cada...
Para una multiplicación a la vez, el tiempo es probablemente comparable o ligeramente a favor de la CPU. Obviamente, la ventaja del FPGA es que puedes tener muchos de ellos en paralelo.

Respuestas (5)

No he hecho esto para FP de doble precisión, pero se aplican los mismos principios que para precisión simple, para lo cual he implementado la división (como multiplicar por recíproco).

Lo que sí tienen estos FPGA, en lugar de FPU, son bloques DSP/multiplicadores cableados, capaces de implementar una multiplicación de 18*18 o (Virtex-5) 18*25 en un solo ciclo. Y los dispositivos más grandes tienen alrededor de mil de estos, o incluso 126 o 180 en el extremo superior de las familias Spartan-3 o Spartan-6.

Por lo tanto, puede descomponer una multiplicación grande en operaciones más pequeñas usando varias de estas (2 para el Virtex-5 que hace precisión simple) usando los sumadores de DSP o la estructura FPGA para sumar los productos parciales.

Obtendrá una respuesta en unos pocos ciclos, 3 o 4 para SP, tal vez 5 para DP, dependiendo de cómo componga el árbol sumador (y, a veces, ¡donde las herramientas de sintetizador insisten en agregar registros de canalización!).

Sin embargo, esa es la latencia: como está canalizado, el rendimiento será de 1 resultado por ciclo de reloj.

Para la división, aproximé un operador recíproco usando una tabla de búsqueda seguida de una interpolación cuadrática. Esto fue más preciso que la precisión simple y se extendería (con más hardware) a DP si quisiera. En Spartan-6 se necesitan 2 BlockRams y 4 DSP/multiplicadores, y un par de cientos de pares LUT/FF.

Su latencia es de 8 ciclos, pero nuevamente el rendimiento es de un solo ciclo, por lo que al combinarlo con el multiplicador anterior, obtiene una división por ciclo de reloj. Debe superar los 100 MHz en Spartan-3. En Spartan-6, la estimación de síntesis es de 185 MHz, pero eso es con 1,6 ns en una sola ruta de enrutamiento, por lo que 200 MHz está dentro de lo razonable.

En Virtex-5 alcanzó los 200 MHz sin esfuerzo, al igual que su gemelo de raíz cuadrada. Un par de estudiantes de verano intentaron volver a canalizarlo: con menos de 12 ciclos de latencia, se acercaron a 400 MHz, 2,5 ns por raíz cuadrada.

¿Pero recuerda que tiene entre cien y mil unidades DSP? Eso le da uno o dos órdenes de magnitud más de poder de procesamiento que una sola unidad FP.

Gracias por tu respuesta, Brian, pero ¿no es toda tu respuesta sobre la multiplicación/división de enteros? Estoy principalmente interesado en el punto flotante.
No, como dije, precisión simple, lo que significa punto flotante de 32 bits. Los mismos principios se aplican a los dobles, pero el uso de recursos es obviamente mayor.

Cuando se utiliza un FPGA normal como Xilinx Spartan 3 o Virtex 5, ¿cuántos ciclos se necesitan para ejecutar una multiplicación o división de punto flotante de 64 bits de doble precisión?

¡La respuesta es sí!

Pero en serio, es muy difícil llegar a un número. Cuando se diseña cualquier lógica compleja, siempre hay una compensación entre diferentes cosas, y ningún enfoque es bueno para todos los diseños. Trataré de cubrir los grandes.

Con el diseño lógico, una compensación es el tamaño frente a la velocidad. El ejemplo sencillo de esto es, digamos que un único multiplicador de punto flotante es demasiado lento. Para acelerarlo todo lo que tienes que hacer es agregar un segundo multiplicador. Su tamaño lógico se duplica, pero sí lo hace el número de multiplicaciones por segundo. Pero incluso mirando un solo multiplicador, hay diferentes formas de multiplicar números; algunos son rápidos y grandes, otros son pequeños y lentos.

Otra compensación es la velocidad del reloj frente a los relojes por multiplicación. Podría diseñar alguna lógica que hiciera que un solo punto flotante se multiplicara en un reloj. Pero eso también requeriría que el reloj fuera más lento, tal vez tan lento como 10 MHz. O bien, podría diseñarlo para que funcione con un reloj de 100 MHz, pero requeriría 10 relojes por multiplicación. La velocidad general es la misma (uno se multiplica en 100 ns), pero uno tiene un reloj más rápido.

Relacionado con el párrafo anterior está la compensación de la velocidad del reloj frente a la latencia múltiple. Hay una técnica en el diseño lógico llamada canalización. Básicamente, tomas un trozo de lógica y lo divides en etapas más pequeñas, donde cada etapa toma un ciclo de reloj para completarse. La ventaja aquí es que cada etapa puede estar trabajando en una multiplicación mientras que las otras etapas están trabajando en otras multiplicaciones. Por ejemplo, digamos que estamos funcionando a 100 MHz con una canalización de 10 etapas. Esto significa que tomará 10 relojes para cada multiplicación, ¡pero la lógica también funciona en 10 multiplicaciones diferentes al mismo tiempo! Lo bueno es que está completando una multiplicación en cada ciclo de reloj. Entonces, los relojes efectivos por multiplicación son 1, solo se necesitan 10 relojes para que se complete cada una de esas multiplicaciones.

Entonces, la respuesta a su pregunta, qué tan rápido puede un FPGA hacer una multiplicación, realmente depende de usted. Los FPGA vienen en diferentes tamaños y velocidades, y puede dedicar tanta lógica a la tarea en cuestión como desee. Pero veamos un escenario específico...

Digamos que queremos usar el Spartan-3A más grande y lo único que nos importa son las multiplicaciones de coma flotante de 32 bits. Una multiplicación flotante de 32 bits requiere un multiplicador de enteros de 24x24 y un sumador de 8 bits. Esto requiere cuatro de los bloques multiplicadores dedicados y algunas porciones genéricas (muy pocas para preocuparse). El XC3S1400A tiene 32 multiplicadores dedicados, por lo que podemos hacer ocho de nuestros multiplicadores de coma flotante en paralelo. Una estimación muy aproximada de la velocidad del reloj sería de unos 100 MHz. Podemos canalizar completamente este diseño para que podamos completar cuatro multiplicaciones de coma flotante de 32 bits por ciclo de reloj, para una velocidad efectiva de 800 millones de multiplicaciones de coma flotante por segundo.

Una multiplicación de doble precisión requiere 9 bloques multiplicadores dedicados por multiplicación de coma flotante, por lo que solo podríamos hacer 3 multiplicaciones en paralelo, lo que da como resultado una velocidad de alrededor de 300 millones de multiplicaciones de coma flotante de 64 bits por segundo.

A modo de comparación, consideremos la nueva serie Xilinx Virtex-7. Los multiplicadores dedicados son más grandes, por lo que solo necesitamos 6 bloques multiplicadores dedicados para una multiplicación de punto flotante de 64 bits. También hay 1920 multiplicadores dedicados en la mayor parte, por lo que podemos hacer 320 multiplicaciones de punto flotante de doble precisión en paralelo. Esas partes también son mucho más rápidas. Estimo que podemos ejecutar esas partes a 200 MHz, lo que nos da una velocidad total de 64 MIL MILLONES de puntos flotantes de doble precisión multiplicados por segundo. Por supuesto, esos chips cuestan unos 10.000 dólares cada uno.

La división de punto flotante es mucho más difícil de hacer rápidamente. La lógica es mucho más grande, especialmente en un FPGA, y funciona mucho más lento. Lo mismo es cierto para la mayoría de las CPU, en el sentido de que las instrucciones de división (coma flotante y fija) se ejecutan mucho más lentamente. Si la velocidad es importante, entonces desea eliminar la mayor cantidad posible de divisiones. Por ejemplo, en lugar de dividir por 5, debes multiplicar por 0,2. De hecho, en muchos sistemas es más rápido calcular un recíproco y luego multiplicar que simplemente dividir.

Las mismas compensaciones se aplican a la división que a la multiplicación, solo que la división siempre será mucho más lenta y mucho más grande que la multiplicación.

Un TI DSP o incluso una GPU en una Rasberry Pi 3 absorberán el humo mágico de lo que alguna vez fue una ALU en FPGA.

Al menos en el componente de división Altera ALT_FP, la división de 64 bits de doble precisión (mantisa de 52 bits) toma 10, 24 o 61 ciclos de reloj (seleccionable). La precisión ampliada individual puede variar. Por ejemplo, división de 43 bits donde el exponente es de 11 bits, la mantisa es de 26 bits y permite seleccionar tales opciones de latencia de salida de reloj: 8, 18 o 35. Inicie ISE y verifique lo que puede tener en Xilinx.

¿Son estos números latencia o rendimiento?
¿Se pueden seleccionar ciclos de reloj de doble precisión? ¿Por qué factor? ¿Usar más/menos bloques? ¿Y qué hay de la multiplicación?
No me moví junto con los parámetros del componente, solo inicié una ventana principal y copié lo que dice. Probablemente necesite leer el docu y verificar qué otros parámetros ofrece el componente gui. Básicamente, no puedo responder a ambas preguntas por ahora.

No hay razón por la que no pueda tomar un solo ciclo. Sin embargo, probablemente sería un ciclo bastante grande y usaría muchos recursos...

Tengo implementaciones de multiplicación y división de punto flotante de doble precisión. La multiplicación toma 13 ciclos de reloj y la división toma 109 ciclos de reloj. Ambos están canalizados para un rendimiento del 100 % (un resultado por reloj) y una operación de alrededor de 200 MHz en un Xilinx V5. No sé cuántos relojes menos podría obtener a 100 MHz, pero dividir por dos sería una apuesta segura.

También tengo implementaciones de punto flotante de precisión simple que toman 10 y 51 relojes en la misma situación.