Pipeline vs. Parallelität

Betrachten wir einen Algorithmus (zum Beispiel Verschlüsselung), der 8 streng identische Schritte hat (die Ausgabe wird als Eingabe für den nächsten Schritt verwendet).

Angesichts der Tatsache, dass ich über genügend Ressourcen verfüge, um 8 "Step-Module" auf meinem Board unterzubringen, frage ich mich, welche Vorteile es hat, dies als Pipeline (8 Module, die mit einigen Puffern dazwischen verbunden sind) oder als 8 getrennte Module (mit eine Schleife auf sich selbst über Multiplexer und Puffer).

Wenn ich einen Eingangsport habe, um die Daten zu verschlüsseln, sollte sich die Leistung nicht ändern, die Gesamtlatenz und der Durchsatz bleiben gleich .

schematisch

Simulieren Sie diese Schaltung – Mit CircuitLab erstellter Schaltplan

Oben: die Pipeline, unten die Parallele (wenn man nur 2 mal durch das "Step-Modul" geht und die Puffer weglässt)

Gibt es einen signifikanten Unterschied?

Weitere Exploration: Was ist, wenn ich nicht genug Platz für 8 Module habe (vielleicht aber auch nur 7) oder für mehr als 8 (vielleicht 9)?

Ich denke, Sie sollten Ihr Beispiel als Blockdiagramm erstellen.
Ich glaube, dass die beiden Blockdiagramme, die Sie gezeichnet haben, nicht das gleiche Ergebnis erzielen. Vielleicht ist der Verschlüsselungsblock im 2. Diagramm nicht derselbe wie im ersten Diagramm?
Es hängt davon ab, was das "Verschlüsselungsmodul" tatsächlich tut. Wenn es wirklich eine Pipeline ist, würden Sie nur eines verwenden (vorausgesetzt, die Module sind in beiden Diagrammen gleich) und dann einfach jeden Eingang der Reihe nach durchleiten. Dadurch wird der Logikverbrauch auf Kosten der Bandbreite massiv reduziert (Sie können jeweils nur ein Wort eingeben). In der parallelen verwenden Sie viel mehr Logik, aber Sie können mehrere Wörter gleichzeitig eingeben. Wenn Sie ein wenig klarstellen können, schreibe ich dies als Antwort auf.
Ich bin verwirrt von Ihrem Diagramm - Sie scheinen zu sagen, dass Sie zur Verarbeitung eines Datenstroms (in Blöcken) Daten achtmal durch ein einzelnes Modul führen können, indem Sie Module "schleifen" ODER "kaskadieren". Wenn das der Kern Ihrer Frage ist, warum zeigen Sie dann die gesamte Ein- und Ausgabelogik in Szenario B - Sie haben in Szenario B eine Schleife um die Module gezeigt, und das ist sicherlich genug ODER vielleicht verstehe ich alles falsch?
Sie brauchen die Frage nicht zu löschen, bearbeiten Sie einfach die zusätzlichen Informationen als zweiten Teil am Ende.
Die Seite ist als Informationsarchiv konzipiert. Wenn jemand anderes mit einer ähnlichen Frage auf diese Frage stößt, finden sie die Informationen möglicherweise nützlich.
Nein, weil der erste Teil Ihrer Antwort nicht auf die (aktualisierte) Frage eingeht [ja, es ist meine Schuld, dass die Frage nicht kristallklar war, als ich sie zum ersten Mal geschrieben habe]
Ich habe eine Bearbeitung vorgenommen. Wenn Sie der Meinung sind, dass es nicht passt, kann es einfach zurückgerollt werden. Aber die Antwort passt immer noch zur Frage und gibt Ihnen die Informationen, nach denen Sie meiner Meinung nach gesucht haben.

Antworten (3)

Sie haben ein Modul, das die Daten mehrmals hintereinander verarbeiten muss, um die Konvertierung abzuschließen. In dem „pipelined“-Beispiel füttern Sie einfach alle nacheinander. Dies hat eine gewisse Latenz, da die Daten einige Zeit brauchen, um von der Eingabe zur Ausgabe zu gelangen. Wenn die Blöcke jedoch wirklich per Pipeline verarbeitet werden, ist dies nur eine Latenz - Sie können bei jedem Zyklus ein neues Datenwort einspeisen, und es werden an jedem beliebigen Punkt mehrere Abtastungen in der Pipeline-Phase vorhanden sein, die am Ende den gleichen Durchsatz ermöglichen.

Ihr "paralleler" Fall ist nicht wirklich ein paralleler Fall. Es ist im Grunde der gleiche Pipeline-Fall, aber anstatt sie nacheinander zu kleben, erhalten Sie am Ende zusätzliche Logik, um die eingehenden Daten an jeden Block zu verteilen, und dann hat vermutlich jeder Block mehr Logik, um seine Ausgabe genügend oft durch sich selbst zu führen die Umstellung abschließen. Am Ende musst du sie dann alle neu kombinieren. Es ist im Grunde eine hässliche Methode, eine Pipeline-Berechnung durchzuführen.

Ich bin mir nicht sicher, woher Sie die Idee haben, dass Ihre Pipeline 2,4,8,16 Einheiten haben muss? Wenn Sie die Daten 7 Mal durch das Modul verarbeiten müssen, würden Sie einfach 7 hintereinander in die Pipeline stecken - jeder arbeitet mit dem Ausgang des letzten, sodass es keine Rolle spielt, ob es sich nicht um eine Zweierpotenz handelt .


Eine wirklich parallele Version wäre eine, bei der die Berechnung in Teiloperationen aufgeteilt werden kann. Angenommen, Sie wollten zwei 16-Bit-Zahlen multiplizieren, hatten aber nur einen 8x8-Multiplikatorblock, der einen Taktzyklus benötigt, um abgeschlossen zu werden. Sie könnten 4 in Reihe stecken und eine gewisse Akkumulation haben (dies wäre eine Pipeline-Operation), oder Sie könnten mehrere Instanzen des Multiplikators hinzufügen und sie parallel schalten. Parallel hätte das Ergebnis eine Latenz von 1 Taktzyklus, in Pipeline-Verarbeitung (seriell) hätte es eine Latenz von 4 Zyklen. Dies geht auf Kosten der Verwendung von 4-mal so viel Logik.

Ein weiteres Beispiel für echtes paralleles Verhalten ist, wenn Sie mehrere Wörter gleichzeitig und schneller verarbeiten müssen, als ein Block verarbeiten könnte. Angenommen, Sie hätten einen Block, der ein Datenwort nahm und es verschlüsselte. Der Baustein kann in jedem Taktzyklus nur ein Wort an seinem Eingang verarbeiten. Was ist nun, wenn Ihr eingehender Datenstrom aus vier Wörtern besteht, die alle im selben Taktzyklus ankommen, Ihr Verschlüsselungsblock jedoch nur jeweils eines verarbeiten kann. Der Durchsatz des Verschlüsselungsmoduls beträgt 1/4 dessen, was erforderlich ist. Wenn Sie nun vier Blöcke parallel schalten, können Sie jetzt jedes der vier Wörter gleichzeitig verarbeiten, was den erforderlichen Durchsatz ermöglicht - wiederum auf Kosten des vierfachen Bedarfs an Logik.


Es gibt einen Fall, in dem der zweite Ansatz tatsächlich gerechtfertigt ist. Angenommen, Sie müssen jedes Wort 8 Mal durch die Berechnungsphase verarbeiten, aber aufgrund der Größe der Berechnung haben Sie im FPGA nur Platz für beispielsweise 3 Durchgänge, dann bräuchten Sie eine Möglichkeit zur Wiederverwendung von Ressourcen. Sie versuchen, die Berechnung zu unterbrechen, um weniger Blöcke zu verwenden.

In dieser Situation ist es ziemlich vorteilhaft, eine Logik zu haben, um mehrmals durch denselben Block zu koppeln. Auf diese Weise können Sie dasselbe Modul wiederverwenden und so viel weniger Logikressourcen zur Verarbeitung der Berechnung verwenden. Dies geht jedoch zu Lasten des Durchsatzes. Wenn Sie dasselbe Datenwort 8 Mal durch denselben Block führen müssen, reduziert sich Ihr Durchsatz auf ein Achtel, da währenddessen keine neuen Wörter in den Block gelangen können.

Wenn Sie Platz für zusätzliche Blöcke (z. B. 3) haben, können Sie die Berechnung parallel für drei Datenwörter gleichzeitig durchführen. Sie instanziieren drei Kopien Ihrer Einzelblockschaltung und fügen zusätzliche Logik hinzu, um zu bestimmen, wann es Zeit für ein neues Wort ist, in jeden der Blöcke einzutreten. Dies wiederum gewinnt etwas Leistung zurück - es sind jetzt 3/8 von dem, was es war.


Ich kann die Antwort bei Bedarf mit einigen Diagrammen aktualisieren, aber hoffentlich ist die Erklärung ziemlich klar.

@oliverpool Ich denke, mein Punkt ist, dass die "hässliche" Methode überhaupt nicht hilft, es hat keinen Vorteil, es auf diese Weise zu tun - tatsächlich verbraucht es mehr Logik und verursacht massive Debugging-Kopfschmerzen.
@oliverpool es gibt KEINEN Vorteil. Beide Anordnungen haben genau dieselbe Pipeline-Verzögerung und genau denselben Durchsatz. Der einzige Unterschied besteht darin, dass man eine Menge zusätzlicher Logik zum Multiplexen hat.
Ihr letzter Kommentar sollte eigentlich Ihre Antwort ersetzen (da er genau meine Frage beantwortet - die zuvor nicht gut gestellt wurde).
@oliverpool siehe meine Bearbeitung.

Mit einfachen Worten, eine einzelne Pipeline wird nur EINE Sache auf einmal tun. Wenn Sie Module in Reihe haben, muss jedes Modul warten, bis das vorherige Modul abgeschlossen ist.

Da alle Schritte identisch sind, ist dies nur ein Problem, bis die Pipeline voll ist.

Wenn es parallel gemacht wird, wird diese anfängliche Strafe negiert.

Hier sind die Unterschiede, die mir einfallen (nachdem ich die Frage geschrieben und gemäß den Kommentaren bearbeitet habe):

Die parallele Version benötigt mehr Logik (Multiplexer), um die Eingabe zu versenden und zu verfolgen, wie oft die Daten bereits durch das Modul gegangen sind.

Aber die parallele Version unterstützt auch eine beliebige* Anzahl von "Step-Modulen" (z. B. 7 von 9), während die Pipeline nicht so flexibel ist (streng abhängig von den Anforderungen des Algorithmus).

*Wenn man bedenkt, dass mein Algorithmus 8 Schritte benötigt , aber mein FPGA vielleicht nur Platz für 7 (oder 9) Schrittmodule hat, kann ich 7 (oder 9) parallele Versionen machen und der Durchsatz wird entsprechend erhöht.

Der letzte Absatz ist falsch. Komplett falsch. Ich verstehe nicht, warum Sie denken, dass Sie im ersten Design keine beliebige Anzahl von Modulen haben können.
Warum nicht? Setzen Sie einfach drei Module hintereinander.
Ihre Bearbeitung hat die Frage gerade komplett geändert. Wenn ich Sie wäre, würde ich diese Antwort löschen und alles in die Frage kopieren.
Warum wurde diese Antwort abgelehnt? Es hat mehr oder weniger den gleichen Inhalt wie @TomCarpenter (und wurde schon einmal gepostet...)