Vektor

Überblick

Vektoroperationen werden nur von 64-Bit-Prozessoren nativ unterstützt und bieten nur mit diesen Prozessoren einen Leistungsvorteil. Informationen zum Prozessor finden Sie im Datenblatt Ihrer Steuerung.

Vektoroperationen auf x86/64-Bit-Plattformen mit SSE2 und ARM64 mit NEON werden nativ unterstützt. Auf anderen Plattformen werden Vektoroperationen in einzelne Anweisungen untergliedert. So wird eine Vektoraddition z. B. durch die Ausführung mehrerer Einzeladditionsoperationen ausgeführt.

Die Befehlssatzerweiterungen der Prozessoren sind SIMD-Erweiterungen (Single Instruction, Multiple Data). SIMD beschreibt eine Computerarchitektur, in der zahlreiche Datensätze desselben Typs über einen Befehlsaufruf simultan verarbeitet werden. In Vektoroperationen ist es beispielsweise möglich, vier Zahlenpaare gleichzeitig hinzuzufügen.

Syntax

<variable name> :  __VECTOR[ <vector size> ] OF <element type> ( := <initialization> )? ;

<vector size> : 1 |2 | 3 | 4 | 5| 6 | 7| 8
<element type> : REAL | LREAL
// (...)? : Optional

Ein Vektordatentyp entspricht einem Array aus Gleitkommazahlen mit maximal 8 Elementen. Die Operatoren __vc<operator name> sind für diesen Datentyp verfügbar. Sie ermöglichen Ihnen die Implementierung von Vektoroperationen ohne zusätzliche Funktionsaufrufe.

Syntax für Indexzugriff

<variable name>[ <index> ]
<index> : 0 | 1 | 2| 3 | 4 | 5| 6 | 7

Durch die Indizierung einer Vektorvariablen können Sie auf ein einzelnes Element des Vektors zugreifen. Der Indexbereich reicht von 0 bis <Vektorgröße> - 1.

Beispiel:

PROGRAM PLC_PRG
VAR
        vcA : __VECTOR[3] OF REAL;
END_VAR

vcA[0] := 1.1;
vcA[1] := 2.2;
vcA[2] := 3.3;

Ermitteln der optimalen Vektorgröße für Ihr System

Für die Programmierung eines effizienten Codes müssen Sie die geeignete Vektorgröße für Ihr Zielsystem ermitteln und verwenden.

Bei Zielsystemen mit Computerarchitektur, die sich in der Regel für eine Vektorverarbeitung eignet, hat es sich nicht bewährt, Vektoren einer beliebigen Größe einzusetzen. Für jeden Prozessor ist je nach Typ der Datenverarbeitung eine optiomale Vektorgröße verfügbar. Für Vektoren dieser Größe wird die Verarbeitungszeit optimiert. Es ergibt sich kein Geschwindigkeitsvorteil aus Vektoren, die als größeres Array deklariert werden. Vektoren, die als kleinere Arrays deklariert werden, schöpfen die Prozessorkapazität nicht vollständig aus.

Sie können die optimale Größe zur Laufzeit mit den folgenden Konstanten des Datentyps INT abfragen:

  • Constants.vcOptimalREAL: Für Vektoren mit REAL-Elementen.

  • Constants.vcOptimalLREAL: Für Vektoren mit LREAL-Elementen.

Der Rückgabewert 1 bedeutet, dass die beschleunigte Vektorverarbeitung für das Zielsystem nicht verfügbar ist.

Beispiel:

PROGRAM PLC_PRG
VAR
        iOVS_REAL : INT; // Optimal vector size for REAL elements
        iOVS_LREAL : INT; // Optimal vector size for LREAL elements
END_VAR

iOVS_REAL := Constants.vcOptimalREAL;
iOVS_LREAL := Constants.vcOptimalLREAL;

Operator __VCADD

Der Operator berechnet die Summe zweier Vektoren.

Syntax:

<vector variable> := <1st vector operand> __VCADD <2nd vector operand>;

Beispiel für eine Additionsoperation:

FUNCTION_BLOCK FB_ADD
VAR
        vcA : __VECTOR[3] OF REAL := __VCSET_REAL(3, 3, 3);
        vcB : __VECTOR[3] OF REAL := __VCSET_REAL(1, 2, 3);
        vcResult : __VECTOR[3] OF REAL;
END_VAR


vcResult := vcA __VCADD vcB;

Operator __VCSUB

Der Operator berechnet die Differenz zwischen zwei Vektoren.

Syntax:

<vector variable> := <vector minuend> __VCSUB <vector subtrahend>;

Beispiel für eine Subtraktionsoperation:

FUNCTION_BLOCK FB_SUB
VAR
        vcA : __VECTOR[3] OF REAL := __VCSET_REAL(3, 3, 3);
        vcB : __VECTOR[3] OF REAL := __VCSET_REAL(1, 2, 3);
        vcResult0 : __VECTOR[3] OF REAL;
        vcResult1 : __VECTOR[3] OF REAL;
END_VAR

vcResult0 := vcA __VCSUB vcB;
vcResult1 := vcB __VCSUB vcA;

Operator __VCMUL

Der Operator berechnet das Produkt zweier Vektoren oder eines Skalars (Gleitkommazahl) und eines Vektors.

Syntax:

<vector variable> := <1st vector operand> __VCMUL <2nd vector operand> | <scalar operand> __VCMUL <vector operand> | <vector operand> __VCMUL <scalar operand>;

Beispiel für eine Multiplikationsoperation:

FUNCTION_BLOCK FB_MUL
VAR
        rScalar : REAL := 1.1;
        vcA : __VECTOR[3] OF REAL;
        vcB : __VECTOR[3] OF REAL;
        vcResult0 : __VECTOR[3] OF REAL;
        vcResult1 : __VECTOR[3] OF REAL;
        vcResult2 : __VECTOR[3] OF REAL;
END_VAR

vcResult0 := vcA __VCMUL vcB;
vcResult1 := rScalar __VCMUL vcB;
vcResult2 := vcA __VCMUL 3.3;

Operator __VCDIV

Der Operator berechnet den Quotienten zweier Vektoren oder eines Vektors und eines Skalars.

Syntax:

<vector variable> := <vector dividend> __VCDIV <vector divisor> | <vector dividend> __VCMUL <scalar divisor>;

Beispiel für eine Divisionsoperation:

FUNCTION_BLOCK FB_DIV
VAR
        iScalar : INT := 3;
        rScalar : REAL := 1.5;
        vcA : __VECTOR[3] OF REAL := __VCSET_REAL(3, 3, 3);
        vcB : __VECTOR[3] OF REAL := __VCSET_REAL(1, 2, 3);
        vcResult0 : __VECTOR[3] OF REAL;
        vcResult1 : __VECTOR[3] OF REAL;
        vcResult2 : __VECTOR[3] OF REAL;
END_VAR

vcResult0 := vcA __VCDIV vcB;
// ERROR CODE vcResult1 := rScalar __VCDIV vcB;
// ERROR CODE vcResult1 := iScalar __VCDIV vcB;
// ERROR CODE vcResult1 := 3.3 __VCDIV vcB;
vcResult2 := vcA __VCDIV 1.5;
vcResult2 := vcA __VCDIV iScalar;
vcResult2 := vcA __VCDIV rScalar;

Operator __VCDOT

Der Operator berechnet das Punktprodukt (Skalarprodukt) zweier Vektoren.

Syntax:

<scalar variable> := <1st vector operand> __VCDOT <2nd vector operand>;

Beispiel für ein Punktprodukt:

FUNCTION_BLOCK FB_DOT
VAR
        rResult : REAL;
        vcA : __VECTOR[3] OF REAL := __VCSET_REAL(3, 3, 3);
        vcB : __VECTOR[3] OF REAL := __VCSET_REAL(1, 2, 3);
END_VAR

rResult := vcA __VCDOT vcB; // = 18

Operator __VCSQRT

Der Operator berechnet die Quadratwurzel jedes Elements im Vektor.

Syntax:

<vector variable> := __VCSQRT <vector operand>;

Beispiel für eine Quadratwurzel:

FUNCTION_BLOCK FB_SQRT
VAR
        vcA : __VECTOR[3] OF REAL := __VCSET_REAL(4, 9, 16);
        vcResult0 : __VECTOR[3] OF REAL;
END_VAR

vcResult0 := __VCSQRT(vcA);

Operator __VCMAX

Der Operator berechnet den maximalen Vektor zweier Vektoren. Das Maximum wird Element für Element ermittelt.

Syntax:

<vector variable> := __VCMAX <1st vector operand>, <2nd vector operand>;

Beispiel für einen maximalen Vektor:

FUNCTION_BLOCK FB_MAX
VAR
        vcA : __VECTOR[3] OF REAL := __VCSET_REAL(3, 3, 3);
        vcB : __VECTOR[3] OF REAL := __VCSET_REAL(1, 2, 6);
        vcResult0 : __VECTOR[3] OF REAL;
END_VAR

vcResult0 := __VCMAX(vcA, vcB);

Operator __VCMIN

Der Operator berechnet den minimalen Vektor zweier Vektoren. Das Minimum wird Element für Element ermittelt.

Syntax:

<vector variable> := __VCMIN <1st vector operand>, <2nd vector operand>;

Beispiel für einen minimalen Vektor:

FUNCTION_BLOCK FB_MIN
VAR
        vcA : __VECTOR[3] OF REAL := __VCSET_REAL(3, 3, 3);
        vcB : __VECTOR[3] OF REAL := __VCSET_REAL(1, 2, 6);
        vcResult0 : __VECTOR[3] OF REAL;
END_VAR

vcResult0 := __VCMIN(vcA, vcB);

Operator __VCSET_REAL

Der Operator setzt die Elemente eines Vektors in einer Anweisung. Die Elemente sind vom Datentyp REAL.

Syntax:

<vector variable> __VCSET_REAL( <first literal>, ( < next literal> )+ ) ;
( ... )+ // number of elements have to match

Beispiel:

FUNCTION_BLOCK FB_SET
VAR
        vcA : __VECTOR[3] OF REAL := __VCSET_REAL(3, 3, 3);
        vcB : __VECTOR[3] OF REAL := __VCSET_REAL(1, 2, 3);
END_VAR

vcA := __VCSET_REAL(4, 4, 4);
vcB := __VCSET_REAL(1.1, 2.2, 3.3);

Operator __VCSET_LREAL

Der Operator setzt die Elemente eines Vektors in einer Anweisung. Die Elemente sind vom Datentyp LREAL.

Sie können den Operator verwenden, wenn die Variablen gültig sind, z. B. in Anweisungen, Implementierungen oder als Parameter in Funktionsaufrufen.

Syntax:

<vector variable> __VCSET_LREAL( <first literal>, ( < next literal> )+ ) ;
( ... )+ // number of elements have to match

Beispiel:

FUNCTION_BLOCK FB_SET
VAR
        vclA : __VECTOR[3] OF LREAL := __VCSET_LREAL(3, 3, 3);
        vclB : __VECTOR[3] OF LREAL := __VCSET_LREAL(1, 2, 3);
END_VAR

vclA := __VCSET_LREAL(-1.7976931348623158E+308, 0.0, 1.7976931348623158E+308);
vclB := __VCSET_LREAL(-1.7976931348623158E+308, 0.0, 1.7976931348623158E+308);

Operator __VCLOAD_REAL

Der Operator interpretiert jeden willkürlichen Speicherbereich als Vektor. Das kann sich für die Verbindung von Vektorvariablen mit bestehendem Code als nützlich erweisen.

Für den Operator sind zwei Parameter erforderlich:

  • Der erste Parameter gibt die Anzahl der Vektorelemente an.

  • Der zweite Parameter ist ein Zeiger auf die REAL-Daten.

__VCLOAD_REAL (<n>,<ptr>) liest <n> aufeinander folgende REAL-Werte an der Adresse <ptr>. Stellen Sie sicher, dass <n> Werte an dieser Adresse vorhanden sind.

 VORSICHT
UNGÜLTIGER ZEIGER
Überprüfen Sie die Gültigkeit der Zeiger, wenn Sie Zeiger für Adressen verwenden und den Befehl „Online-Change“ (Online-Änderung) ausführen.
Die Nichtbeachtung dieser Anweisungen kann Verletzungen oder Sachschäden zur Folge haben.

Syntax:

<vector variable> __VCLOAD_REAL( <vector size>, ( < pointer to data of type REAL> ) ;
<vector size> : 2 | 3 | 4 | 5| 6 | 7| 8

Beispiel für eine Interpretation als Vektor:

FUNCTION_BLOCK FB_LOAD
VAR_INPUT
END_VAR
VAR_OUTPUT
END_VAR
VAR
        rData : ARRAY[0..2] OF REAL := [1.234, 5.678, 9.123];
        vcA : __VECTOR[3] OF REAL := __VCSET_REAL(3, 3, 3);
END_VAR

vcA := __VCLOAD_REAL(3, ADR(rData[0]));

Operator __VCLOAD_LREAL

Der Operator interpretiert jeden willkürlichen Speicherbereich als Vektor. Das kann sich für die Verbindung von Vektorvariablen mit bestehendem Code als nützlich erweisen.

Für den Operator sind zwei Parameter erforderlich:

  • Der erste Parameter gibt die Anzahl der Vektorelemente an.

  • Der zweite Parameter ist ein Zeiger auf die LREAL-Daten.

__VCLOAD_LREAL (<n>,<ptr>) liest <n> aufeinander folgende LREAL-Werte an der Adresse <ptr>. Stellen Sie sicher, dass <n> Werte an dieser Adresse vorhanden sind.

 VORSICHT
UNGÜLTIGER ZEIGER
Überprüfen Sie die Gültigkeit der Zeiger, wenn Sie Zeiger für Adressen verwenden und den Befehl „Online-Change“ (Online-Änderung) ausführen.
Die Nichtbeachtung dieser Anweisungen kann Verletzungen oder Sachschäden zur Folge haben.

Syntax:

<vector variable> __VCLOAD_LREAL( <vector size>, ( < pointer to data of type LREAL> ) ;
<number of vector elements> : 1 | 2 | 3 | 4 | 5| 6 | 7| 8

Beispiel für eine Interpretation als Vektor:

FUNCTION_BLOCK FB_LOAD
VAR_INPUT
END_VAR
VAR_OUTPUT
END_VAR
VAR
        rData : ARRAY[0..3] OF LREAL := [-1.7976931348623158E+308, 1.6E+308, 1.7E+308, -1.6E+308];
        vcA : __VECTOR[3] OF LREAL := __VCSET_LREAL(1, 2, 3);
END_VAR
vcA := __VCLOAD_LREAL(3, ADR(rData[0]));

Operator __VCSTORE

Der Operator speichert/kopiert den Inhalt des Vektors an der angegebenen Speicheradresse. Es werden die Nummer und der Typ der Elemente aus den Vektorvariablen angewendet.

__VCSTORE(<n>,<ptr>) schreibt <n> aufeinander folgende Werte an der Adresse <ptr>. Stellen Sie sicher, dass <n> Werte an dieser Adresse vorhanden sind.

 VORSICHT
UNGÜLTIGER ZEIGER
Überprüfen Sie die Gültigkeit der Zeiger, wenn Sie Zeiger für Adressen verwenden und den Befehl „Online-Change“ (Online-Änderung) ausführen.
Die Nichtbeachtung dieser Anweisungen kann Verletzungen oder Sachschäden zur Folge haben.

Syntax:

__VCSTORE( <pointer to data>, <vector variable> );

Beispiel für eine Speicherung:

FUNCTION_BLOCK FB_STORE
VAR_INPUT
END_VAR
VAR_OUTPUT
END_VAR
VAR
        rData : ARRAY[0..2] OF REAL := [1, 2, 3];
        pData: POINTER TO REAL := ADR(rData[0]);

        lrData : ARRAY [0..3] OF LREAL := [1, 2, 3, 4];
        plData: POINTER TO LREAL := ADR(lrData[0];


        vcA : __VECTOR[3] OF REAL := __VCSET_REAL( 1.234, 5.678, 9.123);
        vclA : __VECTOR[4] OF LREAL := __VCSET_LREAL(-1.7976931348623158E+308, 1.6E+308, 1.7E+308, -1.6E+308);
END_VAR

__VCSTORE(pData, vcA);
__VCSTORE(plData, vclA);