毕昇编译器SME支持
毕昇编译器当前支持SME指令范围不包含SME2和SME2p1版本中新增的指令。
基础编译命令
通过指定cpu型号打开SME:
1 2 | $ export PATH=${BISHENG_INSTALL_DIR}:$PATH $ clang -mcpu=hip11 foo.c -O2 // hip11为920 72F8对应的CPU代号,默认打开sme, sme-f64f64, sme-fa64 |
-mcpu选项不仅会打开对应cpu支持的核特性,还会打开编译器中针对该CPU实现的优化能力,以及调试后的代价模型,相比-march通常会有更佳的性能表现。
C/C++ Attribute
- ZA相关
不共享状态:
- __arm_new("za"):标识函数内将ZA清零并仅在内部使用,不与调用者共享。
共享状态:
- __arm_in("za"):标识函数接受调用者传入的ZA,并且返回时ZA内容不变。
- __arm_out("za"):标识函数忽略传入的ZA并返回新的ZA内容。
- __arm_inout("za"):标识函数接受传入的ZA,并返回新的ZA内容。
- __arm_preserves("za"):标识函数不会读取传入的ZA内容,并且返回时ZA内容不变。
__arm_in("za")和__arm_preserves("za")不代表标识的函数不会修改ZA的内容,而只需要确保在函数返回时ZA与进入前一致。
- 流模式相关
- __arm_streaming:标识函数为流模式类型,函数内所有语句均为流模式指令。
- __arm_streaming_compatible:标识函数为流模式兼容类型,函数内所有语句均为流模式兼容指令。
- __arm_locally_streaming:标识函数自身非流模式类型,但函数内的语句均为流模式兼容指令。
不添加attribute的函数默认是non-streaming模式。
内置SME函数
PSTATE相关:
当系统libgcc版本过低时,程序正常使用内置sme函数需要通过选项使用毕昇内置的compiler-rt库。
使用毕昇内置compiler-rt库示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | $ cat test-sme.c #include <arm_sme.h> #include <stdio.h> int test_has_sme(void) __arm_streaming { return __arm_has_sme(); } int main() { printf("has_sme: %d\n", test_has_sme()); } $ clang -mcpu=hip11 test-sme.c /usr/bin/ld: /tmp/test-ecb063.o: in function `test_has_sme': test.c:(.text+0xc): undefined reference to `__arm_sme_state' clang: error: linker command failed with exit code 1 (use -v to see invocation) $ clang -mcpu=hip11 test-sme.c --rtlib=compiler-rt $ ./a.out has_sme: 1 |
ZA状态断言
void svundef_za() __arm_streaming_compatible;
此调用表示当前ZA中不存在任何有用数据,因此可作为编译器提示(hint)以避免不必要的上下文保存,提高程序性能。示例:
1 2 3 4 | ... use_za_statements; // 使用ZA,并且ZA上的内容后续不会再被使用 svundef_za(); // 告知编译器ZA内容不再被需要,破坏前不需要被保护 clobber_za_statements;// ZA内容被改写 |
FORTRAN支持使用SME指令
在使用fortran语言的MATMUL和TRANSPOSE接口时,如果指定的target支持SME特性,毕昇编译器可以使用SME指令去实现接口。
此功能默认情况下为关闭状态,可以通过添加编译选项“-ffortran-sme-intrinsic”来开启此功能。
- MATMUL
- real*4
- real*8
在使用real*8类型的MATMUL接口时,target还需要同时支持sme-f64f64特性才会使用SME指令实现接口。
- TRANSPOSE
- integer*1
- integer*2
- integer*4
- integer*8
- logical*1
- logical*2
- logical*4
- logical*8
- real*4
- real*8
接口的使用示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | program example real*8, dimension(5,7) :: a real*8, dimension(9,7) :: b real*8, dimension(7,9) :: c real*8, dimension(5,9) :: d integer :: i, j do i = 1, 5 do j = 1, 7 a(i, j) = i * 0.1 + j end do end do do i = 1, 9 do j = 1, 7 b(i, j) = j * 0.2 + i end do end do c = transpose(b) d = matmul(a, c) end program example |
编译命令:
1 | flang example.f90 -march=armv8-a+sve+sme+sme-f64f64 -ffortran-sme-intrinsic |
如果在matmul或tranpose接口的参数或返回值中,采用了矩阵切片的形式,当且仅当所有的切片步长都是常量且为1的情况下,才会使用SME指令的实现。
父主题: SME优化指导