Pipeline vs Paralelismo

Consideremos un algoritmo (por ejemplo, el cifrado) que tiene 8 pasos estrictamente idénticos (la salida se usa como entrada del siguiente paso).

Teniendo en cuenta que tengo suficientes recursos para poner 8 "módulos de pasos" en mi placa, me pregunto cuáles son las ventajas de hacerlo como una tubería (8 módulos conectados en línea con algunos búfer en el medio) o como 8 módulos separados (con un bucle sobre sí mismo a través del multiplexor y el búfer).

Si tengo un puerto de entrada para proporcionar los datos para cifrar, el rendimiento no debería cambiar, la latencia general y el rendimiento serán los mismos .

esquemático

simular este circuito : esquema creado con CircuitLab

En la parte superior: la tubería, debajo del paralelo (considerando solo 2 veces a través del "módulo de pasos" y omitiendo los búferes)

¿Hay alguna diferencia significativa?

Exploración adicional: ¿qué sucede si no tengo suficiente espacio para 8 módulos (pero quizás solo 7) o para más de 8 (quizás 9)?

Creo que deberías dibujar tu ejemplo como un diagrama de bloques.
Creo que esos dos diagramas de bloques que ha dibujado no logran el mismo resultado. ¿Quizás el bloque de cifrado del segundo diagrama no es el mismo que el del primer diagrama?
Depende de lo que realmente haga el "Módulo de cifrado". Si realmente está canalizado, solo usaría uno (asumiendo que los módulos son los mismos en ambos diagramas) y luego simplemente alimentaría cada entrada a través de él por turno. Esto reduce enormemente el consumo de lógica a expensas del ancho de banda (solo puede ingresar una palabra a la vez). En el paralelo, usa mucha más lógica, pero puede ingresar varias palabras a la vez. Si puede aclarar un poco, escribiré esto como una respuesta.
Estoy confundido por su diagrama: parece estar diciendo que para procesar un flujo de datos (en fragmentos) puede ejecutar datos a través de un solo módulo 8 veces "bucle" O "módulos en cascada". Si ese es el quid de su pregunta, ¿por qué mostrar toda la lógica de entrada y salida en el escenario B? Ha mostrado un ciclo alrededor de los módulos en el escenario B y seguramente eso es suficiente O tal vez me estoy equivocando.
No es necesario eliminar la pregunta, solo edite la información adicional como una segunda parte al final.
El sitio está diseñado para ser un archivo de información. Si alguien más encuentra esta pregunta con una consulta similar, puede encontrar útil la información.
No, porque la primera parte de su respuesta no aborda la pregunta (actualizada) [sí, es mi culpa que la pregunta no fuera muy clara cuando la escribí por primera vez]
He hecho una edición. Si cree que no encaja, puede revertirlo fácilmente. Pero la respuesta aún se ajusta a la pregunta y le brinda la información que creo que estaba buscando.
En realidad, aprendí mucho al refinar la pregunta (como el pato de goma) y, de hecho, solo su comentario me trajo algo (ya sabía qué es canalización y paralelismo, pero usé mal las palabras cuando inicialmente planteé mi pregunta)

Respuestas (3)

Tiene un módulo que debe procesar los datos varias veces seguidas para completar la conversión. En el ejemplo 'canalizado', simplemente alimenta cada uno a su vez. Esto tendrá cierta latencia ya que los datos tardan un tiempo en pasar de la entrada a la salida. Sin embargo, si los bloques están realmente canalizados, esto es solo una latencia: puede ingresar una nueva palabra de datos en cada ciclo, y habrá múltiples muestras en la etapa de canalización en cualquier punto dado, lo que permitirá el mismo rendimiento al final.

Su caso 'paralelo' no es realmente un caso paralelo. Es básicamente el mismo caso canalizado, pero en lugar de pegarlos uno tras otro, termina con una lógica adicional para distribuir los datos entrantes a cada bloque, y luego, presumiblemente, cada bloque tiene más lógica para retroalimentar su salida a través de sí mismo suficientes veces para completar la conversión. Al final tienes que recombinarlos todos. Es básicamente un método feo de hacer un cálculo canalizado.

No estoy seguro de dónde saca la idea de que su tubería debe tener 2,4,8,16 unidades. Si necesita procesar los datos a través del módulo 7 veces, simplemente colocaría 7 seguidos en la canalización: cada uno opera en la salida del último, por lo que no importa si no es una potencia de dos longitudes. .


Una versión verdaderamente paralela sería aquella en la que el cálculo se puede dividir en operaciones parciales. Digamos, por ejemplo, que desea multiplicar dos números de 16 bits, pero solo tiene un bloque multiplicador de 8x8 que tarda un ciclo de reloj en completarse. Podría colocar 4 en serie y tener algo de acumulación (esta sería una operación canalizada), o podría agregar varias instancias del multiplicador y ponerlas en paralelo. En paralelo, el resultado tendría una latencia de 1 ciclo de reloj, en canalización (serie) tendría una latencia de 4 ciclos. Esto tiene el costo de usar 4 veces más lógica.

Otro ejemplo de comportamiento paralelo verdadero es si necesita procesar varias palabras a la vez, y más rápido de lo que podría manejar un bloque. Digamos que tenía un bloque que tomó una palabra de datos y la encriptó. El bloque solo puede manejar una palabra en su entrada en cada ciclo de reloj. Ahora, ¿qué sucede si su flujo de datos entrante consta de cuatro palabras que llegan todas en el mismo ciclo de reloj, pero su bloque de cifrado solo puede manejar una a la vez? El rendimiento del módulo de cifrado es 1/4 de lo que se requiere. Ahora, si coloca cuatro bloques en paralelo, ahora puede procesar cada una de las cuatro palabras al mismo tiempo, lo que permite el rendimiento requerido, nuevamente a expensas de requerir cuatro veces más lógica.


Hay un caso en el que el segundo enfoque está realmente justificado. Digamos que necesita procesar cada palabra a través de la etapa de cálculo 8 veces, pero debido al tamaño del cálculo, solo tiene espacio en el FPGA para, digamos, 3 pases, luego necesitaría una forma de reutilizar el recurso. Está tratando de romper el cálculo para usar menos bloques.

En esta situación, sí, tener lógica para retroalimentar el mismo bloque varias veces es bastante ventajoso. Esto le permite reutilizar el mismo módulo y muchos menos recursos lógicos para procesar el cálculo. Sin embargo, esto se produce a expensas del rendimiento. Si necesita pasar la misma palabra de datos a través del mismo bloque 8 veces, entonces su rendimiento se reduce a un octavo, porque mientras lo hace, ninguna palabra nueva puede ingresar al bloque.

Tener espacio para bloques adicionales (digamos 3) le permitiría realizar el cálculo en paralelo para tres palabras de datos a la vez. Usted instancia tres copias de su circuito de bloque único y agrega algo de lógica adicional para determinar cuándo es el momento de que una nueva palabra ingrese a cada uno de los bloques. Esto, a su vez, recupera algo de rendimiento: ahora es 3/8 de lo que era.


Puedo actualizar la respuesta con algunos diagramas si es necesario, pero espero que la explicación sea bastante clara.

@oliverpool Creo que mi punto es que el método "feo" no ayuda en absoluto, no hay ningún beneficio en hacerlo de esa manera; de hecho, consume más lógica y es un gran dolor de cabeza para la depuración.
@oliverpool NO hay beneficio. Ambos arreglos tienen exactamente el mismo retardo de tubería y exactamente el mismo rendimiento. La única diferencia es que uno tiene una carga de lógica adicional para multiplexar.
Su último comentario en realidad debería reemplazar su respuesta (ya que responde exactamente a mi pregunta, que anteriormente no estaba bien formulada)
@oliverpool mira mi edición.

En palabras simples, una sola canalización solo hará UNA cosa a la vez. Si tiene módulos en serie, cada módulo tendrá que esperar a que se complete el módulo anterior.

Dado que todos los pasos son idénticos, esto solo será un problema hasta que la canalización esté llena.

Si se hace en paralelo, se anulará esta penalización inicial.

Estas son las diferencias que se me ocurren (después de escribir la pregunta y editarla de acuerdo con los comentarios):

La versión paralela necesitará más lógica (multiplexores) para enviar la entrada y realizar un seguimiento de cuántas veces los datos ya pasaron por el módulo.

Pero la versión paralela también admite un número arbitrario* de "módulo de pasos" (por ejemplo, 7 de 9), mientras que la canalización no es tan flexible (depende estrictamente de los requisitos del algoritmo).

*teniendo en cuenta que mi algoritmo requiere 8 pasos, pero mi FPGA quizás solo tenga lugar para 7 (o 9) módulos de pasos, puedo hacer 7 (o 9) versiones paralelas y el rendimiento aumentará en consecuencia.

El último párrafo está mal. Completamente mal. No entiendo por qué crees que no puedes tener un número arbitrario de módulos en el primer diseño.
¿Por qué no? Simplemente coloque tres módulos uno tras otro.
Tu edición acaba de cambiar completamente la pregunta. Si yo fuera usted, eliminaría esta respuesta y la copiaría toda en la pregunta.
¿Por qué esta respuesta ha sido rechazada? Tiene más o menos el mismo contenido que @TomCarpenter (y se publicó antes...)