矢量

概述

矢量运算仅在 64 位处理器上原生支持,只有在这些处理器上才能具有性能优势。有关处理器信息,请参阅控制器的数据表。

原生支持在搭载 SSE2ARM64NEON 的 x86/64 位平台上执行矢量运算。在其他平台上,矢量运算被划分为多个独立的语句。例如,通过执行多个单一加法运算,来执行矢量相加。

处理器的命令集扩展是 SIMD(单指令多数据)扩展。SIMD 描述的是一种计算机架构,其中通过单次命令调用,同时处理相同类型的多个数据集。比如,在矢量运算中,可以同时对四对数字执行相加。

语法

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

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

矢量数据类型是由浮点数组成的数组,最多包含 8 个元素。操作符 __vc<operator name> 可用于这种数据类型。它们让您能够在不额外执行函数调用的情况下实现矢量运算。

索引访问语法

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

对矢量变量编索引时,可以访问矢量的单个元素。矢量的范围为 0...<矢量大小> - 1。

示例:

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

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

确定系统的最佳矢量大小

为了执行高效的代码编程,需确定并使用适合目标系统的矢量大小。

如果目标系统的计算机架构总体上适用于矢量处理,则建议不要使用任意大小的矢量。每个处理器都有最佳的矢量大小,具体取决于数据处理的类型。这个大小的矢量的处理时间可被优化。对于被声明为较大数组的矢量,没有速度优势。被声明为较小数组的矢量不会完全占用处理器能力。

您可以使用数据类型为 INT 的以下常量,查询运行时的最佳大小:

  • Constants.vcOptimalREAL:适用于包含 REAL 元素的矢量。

  • Constants.vcOptimalLREAL:适用于包含 LREAL 元素的矢量。

返回值 1 意味着,目标系统不支持加速矢量处理。

示例:

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;

操作符 __VCADD

此操作符计算两个矢量的和。

语法:

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

加法运算示例:

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;

操作符 __VCSUB

此操作符计算两个矢量的差。

语法:

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

减法运算示例:

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;

操作符 __VCMUL

此操作符计算两个矢量的乘积或者标量(浮点数)与矢量的乘积。

语法:

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

乘法运算示例:

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;

操作符 __VCDIV

此操作符计算两个矢量的乘积或者矢量与标量的商。

语法:

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

除法运算示例:

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;

操作符 __VCDOT

此操作符计算两个矢量的点积(标量积)。

语法:

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

点积示例:

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

操作符 __VCSQRT

此操作符计算矢量中每个元素的平方根。

语法:

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

平方根示例:

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);

操作符 __VCMAX

此操作符计算两个矢量的最大矢量。这个最大值的确定是逐个元素进行的。

语法:

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

最大矢量示例:

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);

操作符 __VCMIN

此操作符计算两个矢量的最小矢量。这个最小值的确定是逐个元素进行的。

语法:

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

最小矢量示例:

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);

操作符 __VCSET_REAL

此运算设置语句中的矢量元素。这些因素的数据类型为 REAL

语法:

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

示例:

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);

操作符 __VCSET_LREAL

此运算设置语句中的矢量元素。这些因素的数据类型为 LREAL

可以在变量有效的任何位置使用此操作符,比如在赋值、实现中使用,或者在函数调用中用作参数。

语法:

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

示例:

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);

操作符 __VCLOAD_REAL

此操作符将每个任意内存区解译为矢量。这适用于将矢量变量连接到现有代码。

此操作符需要两个参数:

  • 第一个参数指示矢量元素的数量。

  • 第二个参数是指向 REAL 数据的指针。

__VCLOAD_REAL (<n>,<ptr>)<ptr> 地址读取 <n> 连续 REAL 值。确保此地址存在 <n> 值。

 小心
指针无效
对地址使用指针并执行在线更改命令时,请检查指针的有效性。
不遵循上述说明可能导致人身伤害或设备损坏。

语法:

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

解译为矢量的示例:

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]));

操作符 __VCLOAD_LREAL

此操作符将每个任意内存区解译为矢量。这适用于将矢量变量连接到现有代码。

此操作符需要两个参数:

  • 第一个参数指示矢量元素的数量。

  • 第二个参数是指向 LREAL 数据的指针。

__VCLOAD_LREAL (<n>,<ptr>)<ptr> 地址读取 <n> 连续 LREAL 值。确保此地址存在 <n> 值。

 小心
指针无效
对地址使用指针并执行在线更改命令时,请检查指针的有效性。
不遵循上述说明可能导致人身伤害或设备损坏。

语法:

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

解译为矢量的示例:

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]));

操作符 __VCSTORE

此操作符将矢量内容保存/复制到指定的内存地址。其中应用矢量变量元素的数量和类型。

__VCSTORE(<n>,<ptr>)<ptr> 地址写入 <n> 连续值。确保此地址存在 <n> 值。

 小心
指针无效
对地址使用指针并执行在线更改命令时,请检查指针的有效性。
不遵循上述说明可能导致人身伤害或设备损坏。

语法:

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

存储示例:

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);