GCC向量化方法
若要使用GCC自动向量化,必须使用GCC 9.3.0及以上版本进行编译。
使用方法如下:
- 头文件km.h中
- 单精度接口定义前添加#pragma omp declare simd simdlen(4) notinbranch。
- 在双精度接口定义前添加#pragma omp declare simd simdlen(2) notinbranch。
- 在链接选项中同时加上-lkm -lksvml -lm以提供向量接口,在编译选项中加上-fopenmp-simd -fno-math-errno -O3,其中-O3是为了开启编译器向量化优化,这是向量化数学库起效的前提。
示例1
km.h:
... #pragma omp declare simd simdlen(4) notinbranch float expf(float) ...
test.c:
#include <km.h> #include <stdio.h> #include <stdlib.h> int main() { long loop = 1e7; int len = 8192; float *a = (float*)malloc(sizeof(float) * len); float *b = (float*)malloc(sizeof(float) * len); float *d = (float*)malloc(sizeof(float) * len); for (int i = 0; i < len; i++) { a[i] = rand() * 7.7680f - 6.3840f; b[i] = rand() * 8.7680f - 6.3840f; d[i] = 0; } for (int j = 0; j < len; j++) { d[j] = expf(a[j]); } printf("%f\n", d[0]); return 1; }
编译指令:
gcc test.c -lkm -lksvml -lm -fopenmp-simd -fno-math-errno -O3
使用nm命令查看调用接口:
nm -D a.out
出现_ZGVnN4v_前缀接口表示调用成功。
示例2
若代码中出现深层嵌套,如test.c:
#include <km.h> #include <stdio.h> #include <stdlib.h> int main() { long loop = 1e7; int len = 8192; float *a = (float*)malloc(sizeof(float) * len); float *b = (float*)malloc(sizeof(float) * len); float *d = (float*)malloc(sizeof(float) * len); for (int i = 0; i < len; i++) { a[i] = rand() * 7.7680f - 6.3840f; b[i] = rand() * 8.7680f - 6.3840f; d[i] = 0; } for (int i = 0; i < loop; i++) { for (int j = 0; j < len; j++) { d[j] = expf(a[j]); } } printf("%f\n", d[0]); return 1; }
则需要添加额外编译选项提示编译器不将外层循环和内存循环合并,编译指令:
gcc test.c -lkm -lksvml -lm -fopenmp-simd -fno-math-errno -O3 -fno-tree-loop-ivcanon -fno-loop-interchange
使用nm命令查看调用接口:
nm -D a.out
出现_ZGVnN4v_前缀接口表示调用成功。
父主题: 编译器自动向量化