鲲鹏社区首页
中文
注册
开发者
我要评分
获取效率
正确性
完整性
易理解
在线提单
论坛求助

毕昇编译器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

  1. ZA相关

    默认情况下,函数不使用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与进入前一致。

  2. 流模式相关
    • __arm_streaming:标识函数为流模式类型,函数内所有语句均为流模式指令。
    • __arm_streaming_compatible:标识函数为流模式兼容类型,函数内所有语句均为流模式兼容指令。
    • __arm_locally_streaming:标识函数自身非流模式类型,但函数内的语句均为流模式兼容指令。

    不添加attribute的函数默认是non-streaming模式。

内置SME函数

PSTATE相关:

  • bool __arm_has_sme(void) __arm_streaming_compatible;

    返回当前线程是否可以使用SME的所有指令,true代表能,false代表不能。

  • bool __arm_in_streaming_mode(void) __arm_streaming_compatible;

    返回当前程序是否处于流模式下,true代表是,false代表不是。

  • void __arm_za_disable(void) __arm_streaming_compatible;

    提交待办的lazy save操作,并关闭ZA。

当系统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”来开启此功能。

  1. MATMUL

    MATMUL接口支持此功能的数据类型为:

    • real*4
    • real*8

    在使用real*8类型的MATMUL接口时,target还需要同时支持sme-f64f64特性才会使用SME指令实现接口。

  2. TRANSPOSE

    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指令的实现。