使用 IBM z13 SIMD 单元和 IBM z/OS XL C/C++ 编译器为 C/C++ 程序添加并行性(2)
 
- UID
- 1066743
|

使用 IBM z13 SIMD 单元和 IBM z/OS XL C/C++ 编译器为 C/C++ 程序添加并行性(2)
算术运算常见算术运算,比如加法、减法、增量、减量、逻辑非,这些均受支持。这些运算与大多数矢量运算一样,按照 SIMD 模型逐个元素地起作用。例如,以下代码将一个有 4 个整数值的 result 变量(所有整数的值都是 55)显示到 stdout。
1
2
3
4
5
6
7
8
9
10
| #include <stdio.h>
int main(void) {
vector unsigned int a = {1, 2, 3, 4};
vector unsigned int b = {54, 53, 52, 51};
vector unsigned int result = a + b;
printf("Result: %vld\n", result);
return result[2];
}
|
在 USS 中编译此代码的命令如下:
1
| xlc –qvector –qarch=11 getResult.c –o getResult
|
上述示例还使用 [] 矢量元素选择运算符。该运算符支持读写各个矢量元素,行为如同数组索引运算符。请注意,由于未使用矢量双精度类型,不需要指定 -qfloat=ieee 选项。
其他运算符除了算术和逻辑运算符之外,还有一组常见的数据类型运算符,比如 sizeof、__alignof__、address of、typeof、casts 和 assignment。给出矢量中元素数量的一个新 vec_step 运算符也是可用的。该运算符可用于帮助迭代底层的标量类型数组。
用于进行比较的关系运算符也受支持。在条件句中使用时,基于一个运算元和另一个运算元的所有元素之间的关系,关系运算符的值为 1 或 0。如需了解如何获取各元素结果或 OR 归约结果的更多信息,参见 “” 部分。
C 和 C++ 提供的默认参数提升规则对矢量类型无效。这意味着运算元可能要比一个同等标量运算更严格相关。例如,逐位左移运算符需要相同的(忽略符号)矢量类型(目的在于允许逐元素移位)或一个无符号长数据类型(目的在于按单一位数移位)作为右侧的运算元。它也不支持矢量布尔类型,因为这些类型的逻辑值仅是最大元素类型值和 0。
内置函数为了最高效地访问机器指令和不适合用常规 C 和 C++ 运算符的运算,IBM z/OS XL C/C++ 编译器加入了大量内置函数 (BIF) 来处理这些运算。
如同大多数其他 BIF,这些矢量 BIF 在 builtins.h 中成形。它们仅在 VECTOR 选项被指定时激活。
可用的 BIF 包括专门的算数运算(传统的 C 和 C++ 运算符无法完成这些运算)、比较、范围比较、搜寻元素、集中/分散、掩码生成、复制到零、加载和存储、专门的逻辑运算、合并、打包/解包、复制、旋转和移位、舍入和换算、测试、ANY 谓词和 ALL 谓词。
这些 BIF 通常对应于机器 SIMD 指令,可实现高效且高性能的代码。例如,在以下程序代码中,对于 vec_any_lt,您可以看到在伪汇编清单中生成 VFCH (VECTOR FP COMPARE HIGH) 指令。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
| #include <builtins.h>
#include <math.h>
#include <stdio.h>
double getMinimumValue(vector double *list, int numberOfArrayElements) {
vector double currentMinimum = { INFINITY, INFINITY }; // Infinities
for (int i = 0; i < numberOfArrayElements; i++) {
if (vec_any_lt(list, currentMinimum)) {
// At least one element in the list element is smaller
if (list[0] < list[1]) {
currentMinimum = vec_splat(list, 0);
} else {
currentMinimum = vec_splat(list, 1);
}
}
}
return currentMinimum[0];
}
#define NUM_ELEMENTS 3
int main(void) {
vector double array[NUM_ELEMENTS] = {
{ 5.5, 6.6 },
{ 7.7, -3.14 },
{ 2.73, 0.0 }
};
double minValue = getMinimumValue(array, NUM_ELEMENTS);
printf("Minimum Value: %e\n", minValue);
return 55;
}
|
在 USS 中编译此代码的命令如下:
1
| xlc –qvector –qarch=11 –qfloat=ieee –qlist –qlanglvl=extc99 getMinimum.c –o getMinimum
|
BIF 通常直接转换为相关的机器指令,但如果编译器看到更好的行事方式,仍然可优化该指令(甚至删除该指令)。
尽管上述示例很简单,但却展示了如何使用数组索引和矢量元素索引初始化和选择矢量元素。还展示了将 BIF 和矢量类型用作函数的参数和自变量。
结束语IBM z13 SIMD 单元提供一个非常丰富、非常重要的机制来帮助更快地处理数据,并编写利用数据级并行性的代码。使用 C 和 C++ 中的新数据类型、运算和 BIF,可非常简单直观地编写程序来利用新单元。
结合使用 IBM z/OS XL C/C++ 编译器的其他功能,比如架构分段、内联汇编和高度优化,可以编写程序来充分利用新处理器,大幅改善数据分析和处理。 |
|
|
|
|
|