Stream-Verarbeitung - Stream processing

Stream - Verarbeitung ist ein Computer Programmierparadigma,entspricht Datenflussprogrammierung , Ereignisstrom Verarbeitung und reaktive Programmierung , dass einige Anwendungen zu leichter nutzeneine begrenzte Form ermöglicht eine parallele Verarbeitung . Solche Anwendungen können mehrere Recheneinheiten verwenden, wie beispielsweise die Gleitkommaeinheit auf einer Grafikverarbeitungseinheit oder feldprogrammierbare Gate-Arrays (FPGAs), ohne explizit die Zuweisung, Synchronisation oder Kommunikation zwischen diesen Einheiten zu verwalten.

Das Stream-Processing-Paradigma vereinfacht parallele Software und Hardware, indem es die durchführbare parallele Berechnung einschränkt. Bei einer gegebenen Datensequenz (einem Stream ) wird eine Reihe von Operationen ( Kernel-Funktionen ) auf jedes Element im Stream angewendet. Kernelfunktionen werden normalerweise in einer Pipeline ausgeführt , und eine optimale Wiederverwendung des lokalen Speichers auf dem Chip wird versucht, um den Bandbreitenverlust zu minimieren, der mit der Wechselwirkung des externen Speichers verbunden ist. Typisch ist ein einheitliches Streaming , bei dem eine Kernelfunktion auf alle Elemente im Stream angewendet wird. Da die Kernel- und Stream-Abstraktionen Datenabhängigkeiten offenlegen, können Compiler-Tools On-Chip-Verwaltungsaufgaben vollständig automatisieren und optimieren. Stream-Processing-Hardware kann beispielsweise Scoreboarding verwenden , um einen Direct Memory Access (DMA) zu initiieren, wenn Abhängigkeiten bekannt werden. Die Eliminierung der manuellen DMA-Verwaltung reduziert die Softwarekomplexität, und eine damit verbundene Eliminierung für Hardware-Cache-E/A reduziert die Datenbereichsausdehnung, die mit der Bedienung durch spezialisierte Recheneinheiten wie etwa arithmetische Logikeinheiten involviert sein muss .

In den 1980er Jahren wurde die Stream-Verarbeitung innerhalb der Datenflussprogrammierung erforscht . Ein Beispiel ist die Sprache SISAL (Streams and Iteration in a Single Assignment Language).

Anwendungen

Die Stream-Verarbeitung ist im Wesentlichen ein Kompromiss, der von einem datenzentrierten Modell angetrieben wird, das für traditionelle DSP- oder GPU-Typ-Anwendungen (wie Bild-, Video- und digitale Signalverarbeitung ) sehr gut funktioniert, aber weniger für die allgemeine Verarbeitung mit mehr zufälligem Datenzugriff ( wie Datenbanken). Durch den Verzicht auf eine gewisse Flexibilität des Modells ermöglichen die Implikationen eine einfachere, schnellere und effizientere Ausführung. Abhängig vom Kontext kann das Prozessordesign auf maximale Effizienz oder einen Kompromiss für Flexibilität abgestimmt werden.

Stream Processing eignet sich besonders für Anwendungen, die drei Anwendungsmerkmale aufweisen:

  • Compute Intensity , die Anzahl der arithmetischen Operationen pro E/A oder globaler Speicherreferenz. In vielen Signalverarbeitungsanwendungen liegt sie heute weit über 50:1 und nimmt mit der algorithmischen Komplexität zu.
  • Datenparallelität liegt in einem Kernel vor, wenn dieselbe Funktion auf alle Datensätze eines Eingabestroms angewendet wird und mehrere Datensätze gleichzeitig verarbeitet werden können, ohne auf Ergebnisse von vorherigen Datensätzen zu warten.
  • Datenlokalität ist eine spezielle Art von zeitlicher Lokalität, die in Signal- und Medienverarbeitungsanwendungen gebräuchlich ist, wo Daten einmal erzeugt, ein- oder zweimal später in der Anwendung gelesen und nie wieder gelesen werden. Zwischen Kernels übergebene Zwischenströme sowie Zwischendaten innerhalb von Kernelfunktionen können diese Lokalität direkt unter Verwendung des Stream-Processing-Programmiermodells erfassen.

Beispiele für Datensätze in Streams sind:

  • In Grafiken kann jeder Datensatz die Eckpunkt-, Normal- und Farbinformationen für ein Dreieck sein;
  • Bei der Bildverarbeitung kann jeder Datensatz ein einzelnes Pixel aus einem Bild sein;
  • In einem Videocodierer kann jeder Datensatz 256 Pixel umfassen, die einen Makroblock von Daten bilden; oder
  • Bei der drahtlosen Signalverarbeitung könnte jeder Datensatz eine Sequenz von Abtastwerten sein, die von einer Antenne empfangen werden.

Für jeden Datensatz können wir nur von der Eingabe lesen, Operationen darauf ausführen und in die Ausgabe schreiben. Es sind mehrere Eingänge und mehrere Ausgänge zulässig, aber niemals ein Stück Speicher, das sowohl lesbar als auch beschreibbar ist.

Vergleich mit früheren parallelen Paradigmen

Grundlegende Computer begannen mit einem sequentiellen Ausführungsparadigma. Herkömmliche CPUs basieren auf SISD , was bedeutet, dass sie konzeptionell nur eine Operation gleichzeitig ausführen. Mit der Entwicklung der Computeranforderungen der Welt nahm die zu verwaltende Datenmenge sehr schnell zu. Es war offensichtlich, dass das sequentielle Programmiermodell dem erhöhten Bedarf an Rechenleistung nicht gerecht werden konnte. Es wurden verschiedene Anstrengungen unternommen, um alternative Wege zu finden, um riesige Mengen an Berechnungen durchzuführen, aber die einzige Lösung bestand darin, ein gewisses Maß an paralleler Ausführung auszunutzen. Das Ergebnis dieser Bemühungen war SIMD , ein Programmierparadigma, das es ermöglichte, eine Anweisung auf mehrere Instanzen von (verschiedenen) Daten anzuwenden. Die meiste Zeit wurde SIMD in einer SWAR- Umgebung verwendet. Durch die Verwendung komplizierterer Strukturen könnte man auch MIMD- Parallelität haben.

Obwohl diese beiden Paradigmen effizient waren, waren reale Implementierungen mit Einschränkungen von Problemen bei der Speicherausrichtung bis hin zu Synchronisationsproblemen und begrenzter Parallelität geplagt. Als eigenständige Komponenten überlebten nur wenige SIMD-Prozessoren; die meisten waren in Standard-CPUs eingebettet.

Stellen Sie sich ein einfaches Programm vor, das zwei Arrays addiert, die 100 4-Komponenten- Vektoren enthalten (dh insgesamt 400 Zahlen).

Konventionelles, sequentielles Paradigma

for (int i = 0; i < 400; i++)
    result[i] = source0[i] + source1[i];

Dies ist das bekannteste sequentielle Paradigma. Variationen existieren (wie innere Schleifen, Strukturen und dergleichen), aber sie laufen letztendlich auf dieses Konstrukt hinaus.

Paralleles SIMD-Paradigma, gepackte Register (SWAR)

for (int el = 0; el < 100; el++) // for each vector
    vector_sum(result[el], source0[el], source1[el]);

Das ist eigentlich zu stark vereinfacht. Es geht davon aus, dass die Anweisung vector_sumfunktioniert. Obwohl dies bei Instruktionsintrinsics der Fall ist, werden viele Informationen hier nicht berücksichtigt, wie die Anzahl der Vektorkomponenten und deren Datenformat. Dies geschieht aus Gründen der Übersichtlichkeit.

Sie können jedoch sehen, dass diese Methode die Anzahl der decodierten Anweisungen von numElements * componentsPerElement auf numElements reduziert . Die Anzahl der Sprungbefehle wird ebenfalls verringert, da die Schleife seltener durchlaufen wird. Diese Gewinne resultieren aus der parallelen Ausführung der vier mathematischen Operationen.

Was jedoch passiert ist, ist, dass das gepackte SIMD-Register eine bestimmte Datenmenge enthält, so dass es nicht möglich ist, mehr Parallelität zu erreichen. Die Geschwindigkeit wird durch die Annahme eingeschränkt, dass wir vier parallele Operationen durchführen (bitte beachten Sie, dass dies sowohl für AltiVec als auch für SSE gilt ).

Parallel-Stream-Paradigma (SIMD/MIMD)

// This is a fictional language for demonstration purposes.
elements = array streamElement([number, number])[100]
kernel = instance streamKernel("@arg0[@iter]")
result = kernel.invoke(elements)

In diesem Paradigma wird der gesamte Datensatz definiert, anstatt dass jeder Komponentenblock separat definiert wird. Bei der Beschreibung des Datensatzes wird davon ausgegangen, dass er sich in den ersten beiden Zeilen befindet. Danach wird das Ergebnis aus den Quellen und dem Kernel abgeleitet. Der Einfachheit halber gibt es eine 1:1-Zuordnung zwischen Eingabe- und Ausgabedaten, dies muss jedoch nicht sein. Angewandte Kernel können auch viel komplexer sein.

Eine Implementierung dieses Paradigmas kann eine Schleife intern "entrollen". Dadurch kann der Durchsatz mit der Chipkomplexität skaliert werden, wobei Hunderte von ALUs problemlos genutzt werden können. Die Eliminierung komplexer Datenmuster macht einen Großteil dieser zusätzlichen Leistung verfügbar.

Obwohl die Stream-Verarbeitung ein Zweig der SIMD/MIMD-Verarbeitung ist, dürfen sie nicht verwechselt werden. Obwohl SIMD-Implementierungen oft "streaming" arbeiten können, ist ihre Leistung nicht vergleichbar: Das Modell sieht ein ganz anderes Nutzungsmuster vor, das selbst eine weitaus höhere Leistung ermöglicht.

Es wurde festgestellt, dass bei Anwendung auf generischen Prozessoren wie Standard-CPUs nur eine 1,5-fache Geschwindigkeit erreicht werden kann. Im Gegensatz dazu erreichen Ad-hoc-Stream-Prozessoren leicht die 10-fache Leistung, was hauptsächlich auf den effizienteren Speicherzugriff und die höhere Parallelverarbeitung zurückzuführen ist.

Obwohl das Modell verschiedene Grade an Flexibilität erlaubt, erlegen Stream-Prozessoren in der Regel einige Einschränkungen hinsichtlich der Kernel- oder Stream-Größe auf. Beispielsweise fehlt Verbraucherhardware häufig die Fähigkeit, hochpräzise Berechnungen durchzuführen, es fehlen komplexe Indirektionsketten oder es gibt niedrigere Grenzen für die Anzahl von Befehlen, die ausgeführt werden können.

Forschung

Stanford University Stream - Verarbeitung Projekte enthalten die Stanford Real-Time Programmable Shading - Projekt im Jahr 1999. Ein Prototyp gestartet wurde im Jahr 2002 ein Projekt entwickelt namens Imagine Merrimac genannt lief bis etwa 2004 AT & T auch Strom-enhanced Prozessoren erforscht Grafikverarbeitungseinheiten schnell entwickelt in Geschwindigkeit und Funktionalität. Seit diesen frühen Tagen wurden Dutzende von Stream-Processing-Sprachen sowie spezialisierte Hardware entwickelt.

Hinweise zum Programmiermodell

Die unmittelbarste Herausforderung im Bereich der Parallelverarbeitung liegt weniger in der Art der verwendeten Hardwarearchitektur, sondern darin, wie einfach es sein wird, das betreffende System in einer realen Umgebung mit akzeptabler Leistung zu programmieren. Maschinen wie Imagine verwenden ein unkompliziertes Single-Thread-Modell mit automatisierten Abhängigkeiten, Speicherzuweisung und DMA- Planung. Dies allein ist ein Ergebnis der Forschung am MIT und in Stanford, um eine optimale Aufgabenschichtung zwischen Programmierer, Tools und Hardware zu finden. Programmierer schlagen Tools beim Abbilden von Algorithmen auf parallele Hardware, und Tools schlagen Programmierer beim Herausfinden der intelligentesten Speicherzuweisungsschemata usw. Von besonderer Bedeutung sind MIMD-Designs wie Cell , für die der Programmierer mit der Anwendungspartitionierung über mehrere Kerne umgehen und sich damit befassen muss Prozesssynchronisation und Lastausgleich. Effiziente Multi-Core-Programmierwerkzeuge fehlen heute stark.

Ein Nachteil der SIMD-Programmierung war das Problem von Array-of-Structures (AoS) und Structure-of-Arrays (SoA) . Programmierer wollten oft Datenstrukturen mit einer „echten“ Bedeutung aufbauen, zum Beispiel:

 // A particle in a three-dimensional space.
struct particle_t {
    float x, y, z;          // not even an array!
    unsigned byte color[3]; // 8 bit per channel, say we care about RGB only
    float size;
    // ... and many other attributes may follow...
};

Was passiert ist, ist, dass diese Strukturen dann in Arrays zusammengestellt wurden , um die Dinge gut organisiert zu halten. Dies ist ein Array von Strukturen (AoS). Wenn die Struktur im Speicher angelegt wird, erzeugt der Compiler verschachtelte Daten in dem Sinne, dass alle Strukturen zusammenhängend sind, aber es gibt einen konstanten Versatz zwischen beispielsweise dem "size"-Attribut einer Strukturinstanz und dem gleichen Element der folgenden Instanz. Der Offset hängt von der Strukturdefinition ab (und möglicherweise anderen Dingen, die hier nicht berücksichtigt werden, wie beispielsweise den Richtlinien des Compilers). Es gibt auch andere Probleme. Beispielsweise können die drei Positionsvariablen nicht auf diese Weise SIMD-isiert werden, da nicht sicher ist, ob sie im kontinuierlichen Speicherbereich zugewiesen werden. Um sicherzustellen, dass SIMD-Operationen mit ihnen arbeiten können, sollten sie in einem 'gepackten Speicherort' oder zumindest in einem Array gruppiert werden. Ein weiteres Problem liegt darin, dass sowohl "Farbe" als auch "xyz" in Dreikomponenten-Vektorgrößen definiert werden müssen. SIMD-Prozessoren unterstützen normalerweise nur 4-Komponenten-Operationen (mit einigen Ausnahmen).

Diese Art von Problemen und Einschränkungen machten die SIMD-Beschleunigung auf Standard-CPUs ziemlich unangenehm. Die vorgeschlagene Lösung, Struktur von Arrays (SoA) sieht wie folgt aus:

struct particle_t {
    float *x, *y, *z;
    unsigned byte *colorRed, *colorBlue, *colorGreen;
    float *size;
};

Für Leser, die keine Erfahrung mit C haben , bedeutet das '*' vor jedem Bezeichner einen Zeiger. In diesem Fall werden sie verwendet, um auf das erste Element eines Arrays zu zeigen, das später zugewiesen werden soll. Für Java- Programmierer entspricht dies ungefähr "[]". Der Nachteil hierbei ist, dass die verschiedenen Attribute im Speicher verteilt sein könnten. Um sicherzustellen, dass dies keine Cache-Misses verursacht, müssen wir alle verschiedenen "Rottöne" aktualisieren, dann alle "Grünen" und "Blauen".

Für Stream-Prozessoren wird die Verwendung von Strukturen empfohlen. Aus Anwendungssicht können alle Attribute mit einer gewissen Flexibilität definiert werden. Nimmt man GPUs als Referenz, steht eine Reihe von Attributen (mindestens 16) zur Verfügung. Für jedes Attribut kann die Anwendung die Anzahl der Komponenten und das Format der Komponenten angeben (vorerst werden jedoch nur primitive Datentypen unterstützt). Die verschiedenen Attribute werden dann an einen Speicherblock angehängt, wobei möglicherweise ein Schritt zwischen "aufeinanderfolgenden" Elementen der gleichen Attribute definiert wird, wodurch effektiv verschachtelte Daten ermöglicht werden. Wenn die GPU die Stream - Verarbeitung beginnen, wird es sammelt all die verschiedene Attribute in einem einzigen Satz von Parametern ( in der Regel das sieht aus wie eine Struktur oder eine „magische globale Variable“), führen die Operationen und streut für später die Ergebnisse zu einem gewissen Speicherbereich Verarbeitung (oder Abruf).

Modernere Stream-Processing-Frameworks bieten eine FIFO-ähnliche Schnittstelle, um Daten als literalen Stream zu strukturieren. Diese Abstraktion bietet ein Mittel, um Datenabhängigkeiten implizit zu spezifizieren, während es der Laufzeit/Hardware ermöglicht wird, dieses Wissen für eine effiziente Berechnung voll auszunutzen. Eine der einfachsten und effizientesten Stream-Processing-Modalitäten für C++ ist RaftLib , die es ermöglicht, unabhängige Rechenkerne als Datenflussgraphen mit C++-Stream-Operatoren miteinander zu verknüpfen . Als Beispiel:

#include <raft>
#include <raftio>
#include <cstdlib>
#include <string>

class hi : public raft::kernel
{
public:
    hi() : raft::kernel()
    {
       output.addPort< std::string >( "0" ); 
    }

    virtual raft::kstatus run()
    {
        output[ "0" ].push( std::string( "Hello World\n" ) );
        return( raft::stop ); 
    }
};

int
main( int argc, char **argv )
{
    /** instantiate print kernel **/
    raft::print< std::string > p;
    /** instantiate hello world kernel **/
    hi hello;
    /** make a map object **/
    raft::map m;
    /** add kernels to map, both hello and p are executed concurrently **/
    m += hello >> p;
    /** execute the map **/
    m.exe();
    return( EXIT_SUCCESS );
}

Berechnungsmodelle für die Streamverarbeitung

Neben der Spezifikation von Streaming-Anwendungen in Hochsprachen werden Rechenmodelle (MoCs) auch häufig als Datenflussmodelle und prozessbasierte Modelle verwendet.

Generische Prozessorarchitektur

In der Vergangenheit begannen CPUs mit der Implementierung verschiedener Stufen von Speicherzugriffsoptimierungen aufgrund der ständig steigenden Leistung im Vergleich zu relativ langsam wachsender externer Speicherbandbreite. Als sich diese Lücke vergrößerte, wurden große Mengen an Chipfläche dafür verwendet, Speicherlatenzen zu verbergen. Da das Abrufen von Informationen und Opcodes zu diesen wenigen ALUs teuer ist, wird nur sehr wenig Chipbereich für die tatsächliche mathematische Maschinerie reserviert (als grobe Schätzung nehmen Sie an, dass er weniger als 10% beträgt).

Eine ähnliche Architektur gibt es bei Stream-Prozessoren, aber dank des neuen Programmiermodells ist die Anzahl der für das Management vorgesehenen Transistoren tatsächlich sehr gering.

Ausgehend vom Gesamtsystemgesichtspunkt existieren Stream-Prozessoren normalerweise in einer kontrollierten Umgebung. GPUs existieren auf einem Add-In-Board (dies scheint auch für Imagine zu gelten ). CPUs erledigen die schmutzige Arbeit der Verwaltung von Systemressourcen, der Ausführung von Anwendungen und dergleichen.

Der Stream-Prozessor ist normalerweise mit einem schnellen, effizienten, proprietären Speicherbus ausgestattet (Crossbar-Switches sind heute üblich, in der Vergangenheit wurden Multi-Busse verwendet). Die genaue Anzahl der Speicherspuren hängt vom Marktangebot ab. Wie dies geschrieben steht, gibt es immer noch 64-Bit breite Verbindungen (Einstiegsebene). Die meisten Mittelklasse-Modelle verwenden eine schnelle 128-Bit-Crossbar-Switch-Matrix (4 oder 2 Segmente), während High-End-Modelle riesige Mengen an Speicher (eigentlich bis zu 512 MB) mit einer etwas langsameren Crossbar mit einer Breite von 256 Bit verwenden. Standard-Prozessoren vom Intel Pentium bis hin zu einigen Athlon 64 haben dagegen nur einen einzigen 64 Bit breiten Datenbus.

Speicherzugriffsmuster sind viel vorhersehbarer. Arrays existieren zwar, ihre Dimension wird jedoch beim Kernel-Aufruf festgelegt. Am ehesten entspricht eine Indirektion mit mehreren Zeigern einer Indirektionskette , die jedoch garantiert aus einem bestimmten Speicherbereich (innerhalb eines Streams) liest oder schreibt.

Aufgrund der SIMD-Natur der Ausführungseinheiten (ALUs-Cluster) des Stream-Prozessors wird erwartet, dass Lese-/Schreibvorgänge in großen Mengen erfolgen, sodass Speicher für hohe Bandbreite und nicht für niedrige Latenz optimiert sind (dies ist ein Unterschied zu Rambus und DDR-SDRAM , z Beispiel). Dies ermöglicht auch effiziente Speicherbusverhandlungen.

Die meiste (90 %) der Arbeit eines Stream-Prozessors wird auf dem Chip erledigt, sodass nur 1 % der globalen Daten im Speicher gespeichert werden müssen. Hier zahlt es sich aus, die Kernel-Temporaries und -Abhängigkeiten zu kennen.

Intern verfügt ein Stream-Prozessor über einige clevere Kommunikations- und Verwaltungsschaltungen, aber interessant ist die Stream Register File (SRF). Dies ist konzeptionell ein großer Cache, in dem Streamdaten gespeichert werden, um in großen Mengen an einen externen Speicher übertragen zu werden. Als Cache-ähnliche softwaregesteuerte Struktur für die verschiedenen ALUs wird die SRF von allen verschiedenen ALU-Clustern geteilt. Das Schlüsselkonzept und die Innovation, die hier mit dem Imagine-Chip von Stanford umgesetzt wird, besteht darin, dass der Compiler in der Lage ist, Speicher optimal zu automatisieren und zuzuweisen, völlig transparent für den Programmierer. Die Abhängigkeiten zwischen Kernelfunktionen und Daten sind durch das Programmiermodell bekannt, das es dem Compiler ermöglicht, eine Flussanalyse durchzuführen und die SRFs optimal zu packen. Im Allgemeinen kann diese Cache- und DMA-Verwaltung den Großteil des Zeitplans eines Projekts in Anspruch nehmen, was der Stream-Prozessor (oder zumindest Imagine) vollständig automatisiert. In Stanford durchgeführte Tests zeigten, dass der Compiler beim Planen des Speichers genauso gute oder bessere Arbeit leistete, als wenn Sie das Ding mit viel Aufwand von Hand tunen würden.

Es gibt Beweise; Es kann viele Cluster geben, da angenommen wird, dass die Kommunikation zwischen den Clustern selten ist. Intern kann jedoch jeder Cluster eine viel geringere Menge an ALUs effizient nutzen, da die Kommunikation innerhalb des Clusters üblich ist und daher hocheffizient sein muss.

Um diese ALUs mit Daten geholt zu halten, ist jede ALU mit lokalen Registerdateien (LRFs) ausgestattet, die im Grunde ihre verwendbaren Register sind.

Dieses dreistufige Datenzugriffsmuster macht es einfach, temporäre Daten von langsamen Speichern fernzuhalten, wodurch die Siliziumimplementierung hocheffizient und energiesparend wird.

Hardware-in-the-Loop-Probleme

Obwohl eine Beschleunigung um eine Größenordnung vernünftigerweise zu erwarten ist (selbst von Mainstream-GPUs beim Streaming-Verfahren), profitieren nicht alle Anwendungen davon. Kommunikationslatenzen sind eigentlich das größte Problem. Obwohl PCI Express dies mit Vollduplex-Kommunikation verbessert hat, dauert es möglicherweise lange, bis eine GPU (und möglicherweise ein generischer Stream-Prozessor) zum Laufen kommt. Dies bedeutet, dass es normalerweise kontraproduktiv ist, sie für kleine Datensätze zu verwenden. Da das Ändern des Kernels eine ziemlich kostspielige Operation ist, zieht die Stream-Architektur auch Strafen für kleine Streams nach sich, ein Verhalten, das als Short-Stream-Effekt bezeichnet wird .

Pipelining ist eine sehr weit verbreitete und stark genutzte Praxis auf Stream-Prozessoren, wobei GPUs Pipelines von mehr als 200 Stufen aufweisen. Die Kosten für das Umschalten der Einstellungen hängen von der geänderten Einstellung ab, gelten jedoch heute als immer teuer. Um diese Probleme auf verschiedenen Ebenen der Pipeline zu vermeiden, wurden viele Techniken wie "Über Shader" und "Texture Atlanten" eingesetzt. Diese Techniken sind aufgrund der Natur von GPUs spielorientiert, aber die Konzepte sind auch für die allgemeine Stream-Verarbeitung interessant.

Beispiele

  • Der Blitter im Commodore Amiga ist ein früher (ca. 1985) Grafikprozessor, der in der Lage ist, drei Quellströme von 16 Komponentenbitvektoren auf 256 Arten zu kombinieren, um einen Ausgabestrom bestehend aus 16 Komponentenbitvektoren zu erzeugen. Die Gesamtbandbreite des Eingangsstroms beträgt bis zu 42 Millionen Bits pro Sekunde. Die Bandbreite des Ausgabestreams beträgt bis zu 28 Millionen Bits pro Sekunde.
  • Stellen Sie sich unter der Leitung von Professor William Dally von der Stanford University eine flexible Architektur vor, die sowohl schnell als auch energieeffizient sein soll. Das ursprünglich 1996 konzipierte Projekt umfasste Architektur, Softwaretools, eine VLSI-Implementierung und ein Entwicklungsboard und wurde von DARPA , Intel und Texas Instruments finanziert .
  • Ein weiteres Stanford- Projekt namens Merrimac zielt auf die Entwicklung eines Stream-basierten Supercomputers ab. Merrimac beabsichtigt, eine Stream-Architektur und fortschrittliche Verbindungsnetzwerke zu verwenden, um mehr Leistung pro Einheitskosten zu bieten als Cluster-basierte wissenschaftliche Computer, die auf der gleichen Technologie basieren.
  • Die Storm-1- Familie von Stream Processors, Inc , einem kommerziellen Spin-off des Stanford- Projekts Imagine , wurde während einer Feature-Präsentation auf der ISSCC 2007 angekündigt pro Sekunde), die alle bei TSMC in einem 130-Nanometer-Prozess hergestellt werden. Die Geräte zielen auf das obere Ende des DSP- Marktes ab, einschließlich Videokonferenzen , Multifunktionsdruckern und digitaler Videoüberwachungsausrüstung .
  • GPUs sind weit verbreitete Stream-Prozessoren für Verbraucher, die hauptsächlich von AMD und Nvidia entwickelt wurden . Aus Sicht der Stream-Verarbeitung sind verschiedene Generationen zu beachten:
    • Pre-R2xx/NV2x: keine explizite Unterstützung für die Stream-Verarbeitung. Kernel-Operationen waren in der API versteckt und boten zu wenig Flexibilität für den allgemeinen Gebrauch.
    • R2xx/NV2x: Kernel-Stream-Operationen wurden explizit unter die Kontrolle des Programmierers, aber nur für die Vertex-Verarbeitung (Fragmente verwendeten noch alte Paradigmen). Keine Verzweigungsunterstützung behinderte die Flexibilität stark, aber einige Arten von Algorithmen konnten ausgeführt werden (insbesondere Fluidsimulation mit niedriger Genauigkeit).
    • R3xx/NV4x: flexible Verzweigungsunterstützung, obwohl noch einige Einschränkungen hinsichtlich der Anzahl der auszuführenden Operationen und der strikten Rekursionstiefe sowie der Array-Manipulation bestehen.
    • R8xx: Unterstützt Append/Consume-Puffer und atomare Operationen. Diese Generation ist der Stand der Technik.
  • Markenname AMD FireStream für Produktlinie, die auf HPC ausgerichtet ist
  • Nvidia Tesla Markenname für Produktlinie, die auf HPC abzielt
  • Der Cell-Prozessor von STI , einer Allianz von Sony Computer Entertainment , Toshiba Corporation und IBM , ist eine Hardwarearchitektur, die mit entsprechender Softwareunterstützung wie ein Stream-Prozessor funktionieren kann. Es besteht aus einem steuernden Prozessor, dem PPE (Power Processing Element, an IBM PowerPC ) und einer Reihe von SIMD-Coprozessoren, SPEs (Synergistic Processing Elements) genannt, jeder mit unabhängigen Programmzählern und Befehlsspeicher, praktisch eine MIMD- Maschine. Beim nativen Programmiermodell wird die gesamte DMA- und Programmplanung dem Programmierer überlassen. Die Hardware stellt einen schnellen Ringbus zwischen den Prozessoren für die lokale Kommunikation bereit. Da der lokale Speicher für Anweisungen und Daten begrenzt ist, benötigen die einzigen Programme, die diese Architektur effektiv nutzen können, entweder einen winzigen Speicherbedarf oder halten sich an ein Stream-Programmiermodell. Mit einem geeigneten Algorithmus kann die Leistung der Cell mit der von reinen Stream-Prozessoren konkurrieren, dies erfordert jedoch fast immer ein komplettes Redesign von Algorithmen und Software.

Streaming-Programmierbibliotheken und -sprachen

Die meisten Programmiersprachen für Stream-Prozessoren beginnen mit Java, C oder C++ und fügen Erweiterungen hinzu, die spezifische Anweisungen bereitstellen, die es Anwendungsentwicklern ermöglichen, Kernel und/oder Streams mit Tags zu versehen. Dies gilt auch für die meisten Shading-Sprachen , die bis zu einem gewissen Grad als Stream-Programmiersprachen angesehen werden können.

Nicht-kommerzielle Beispiele für Stream-Programmiersprachen sind:

Kommerzielle Implementierungen sind entweder universell einsetzbar oder von einem Anbieter an spezifische Hardware gebunden. Beispiele für allgemeine Sprachen sind:

Zu den herstellerspezifischen Sprachen gehören:

Ereignisbasierte Verarbeitung

Batchdateibasierte Verarbeitung (emuliert einen Teil der tatsächlichen Stream-Verarbeitung, aber im Allgemeinen viel weniger Leistung)

Kontinuierliche Verarbeitung von Operator-Streams

Stream-Verarbeitungsdienste:

Siehe auch

Verweise

Externe Links

  1. ^ Chintapalli, Sanket; Dagit, Derek; Evans, Bobby; Farivar, Reza; Gräber, Thomas; Holderbaugh, Mark; Liu, Zhuo; Nusbaum, Kyle; Patil, Kishorkumar; Peng, Boyang Jerry; Poulosky, Paul (Mai 2016). "Benchmarking von Streaming Computation Engines: Storm, Flink und Spark Streaming". 2016 IEEE International Parallel and Distributed Processing Symposium Workshops (IPDPSW) . IEEE. S. 1789–1792. doi : 10.1109/IPDPSW.2016.138 . ISBN 978-1-5090-3682-0. S2CID  2180634 .