GNU Radio Companion

Stream vs. Vector

Die zwei Arten, wie GRC-Ports Daten strukturieren — und warum das nicht dasselbe ist wie die Puffer-Häppchen, die work() bekommt.

In GNU Radio Companion werden die Begriffe Stream und Vector für zwei unterschiedliche Dinge verwendet, die leicht durcheinandergebracht werden: den Port-Typ eines Blocks und die Art, wie work() intern Daten übergeben bekommt. Nur Ersteres ist eine echte Design-Entscheidung beim Bau eines Flowgraphs.

Wichtige Unterscheidung: Die work()-Funktion eines Blocks bekommt immer ein Array (einen Puffer) von Items pro Aufruf übergeben — das gilt für Stream-Ports genauso wie für Vector-Ports und ist reine API-Mechanik des Schedulers, keine Eigenschaft des Datentyps selbst. Ob ein Port als „Stream" oder „Vector" gilt, entscheidet sich stattdessen daran, was ein einzelnes Item auf diesem Port ist.

Stream-Port

Bei einem Stream-Port ist jedes einzelne Item ein Skalar — z. B. ein einzelner IQ-Sample-Wert. Eine Signal Source liefert genau das: einen kontinuierlichen Stream, bei dem jeder Wert im Datenstrom ein einzelner Abtastwert ist. Die zeitliche Komponente wird dabei nicht als eigene Dimension gespeichert, sondern ist implizit über die Abtastrate gegeben — die Sample Rate muss bekannt sein, um das Signal zeitlich korrekt aus den Daten zu rekonstruieren.

Für reale Signale, die über eine SDR-Hardware-Source empfangen werden, besteht ein direkter Zusammenhang zwischen Abtastrate und Sample-Wert — die Hardware liefert Samples in Echtzeit. Erzeugt man dagegen selbst Signale in GRC (z. B. Sinuswellen oder Rauschen), fließen die Daten normalerweise nicht in Echtzeit durch den Flowgraph, sondern so schnell, wie die CPU sie verarbeiten kann. Der Throttle-Block zwingt den Flowgraph dann dazu, sich an eine vorgegebene Abtastrate zu halten. Bei realen Hardware-Quellen ist er dagegen nicht nötig — die Hardware gibt das Tempo ohnehin vor.

Vector-Port

Bei einem Vector-Port ist jedes einzelne Item selbst ein Array fester Länge — der Port transportiert also nicht einen Strom von Einzelwerten, sondern einen Strom von kompletten Blöcken fester Größe. Das klassische Beispiel ist der FFT-Block: Sein Ausgang liefert pro Item ein vollständiges Spektrum (einen Vektor von FFT Size Bins), nicht einzelne Zahlen. In GRC ist der Port dementsprechend explizit als „Vector" mit fester Länge deklariert.

Kurz gesagt: Bei einem Stream-Port bedeutet input_items[0] in work() "ein Puffer aus vielen einzelnen Samples". Bei einem Vector-Port bedeutet dieselbe Zeile "ein Puffer aus vielen kompletten Vektoren", wobei jeder Vektor selbst wieder aus mehreren Werten besteht. Die Puffer-Mechanik ist identisch — nur die Bedeutung eines einzelnen Items unterscheidet sich.