矢量运算仅在 64 位处理器上原生支持,只有在这些处理器上才能具有性能优势。有关处理器信息,请参阅控制器的数据表。
原生支持在搭载 SSE2、ARM64 和 NEON 的 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;
此操作符计算两个矢量的和。
语法:
<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;
此操作符计算两个矢量的差。
语法:
<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;
此操作符计算两个矢量的乘积或者标量(浮点数)与矢量的乘积。
语法:
<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;
此操作符计算两个矢量的乘积或者矢量与标量的商。
语法:
<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;
此操作符计算两个矢量的点积(标量积)。
语法:
<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
此操作符计算矢量中每个元素的平方根。
语法:
<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);
此操作符计算两个矢量的最大矢量。这个最大值的确定是逐个元素进行的。
语法:
<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);
此操作符计算两个矢量的最小矢量。这个最小值的确定是逐个元素进行的。
语法:
<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);
此运算设置语句中的矢量元素。这些因素的数据类型为 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);
此运算设置语句中的矢量元素。这些因素的数据类型为 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);
此操作符将每个任意内存区解译为矢量。这适用于将矢量变量连接到现有代码。
此操作符需要两个参数:
第一个参数指示矢量元素的数量。
第二个参数是指向 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]));
此操作符将每个任意内存区解译为矢量。这适用于将矢量变量连接到现有代码。
此操作符需要两个参数:
第一个参数指示矢量元素的数量。
第二个参数是指向 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(<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);