NEON_9

示例:矢量加法
让我们看看如何使用编译器选项自动矢量化和优化简单的C程序。

1、创建一个包含以下功能的新文件vec_add.c。 此函数将两个32位浮点值数组相加。

void vec_add(float *vec_A, float *vec_B, float *vec_C, int len_vec) {
        int i;
        for (i=0; i<len_vec; i++) {
                vec_C[i] = vec_A[i] + vec_B[i];
        }
}

 

编译代码,不使用自动向量化:

armclang --target=aarch64-arm-none-eabi -g -c -O1 vec_add.c

反汇编生成的目标文件以查看生成的指令:

fromelf --disassemble vec_add.o -o disassembly_vec_on.txt


反汇编的代码类似于以下内容:

vec_add                  ; Alternate entry point
        CMP      w3,#1
        B.LT     |L3.36|
        MOV      w8,w3
|L3.12|
        LDR      s0,[x0],#4
        LDR      s1,[x1],#4
        SUBS     x8,x8,#1
        FADD     s0,s0,s1
        STR      s0,[x2],#4
        B.NE     |L3.12|
|L3.36|
        RET

在这里,我们可以看到该函数的标签名称vec_add,后面是组成该函数的生成的汇编指令。 FADD指令执行操作的核心部分,但是由于一次仅执行一次加法操作,因此代码未使用Neon。 我们可以看到这是因为FADD指令正在标量寄存器S0和S1上运行。

 

重新编译代码,这次使用自动向量化:

armclang --target=aarch64-arm-none-eabi -g -c -O1 vec_add.c -fvectorize

反汇编生成的目标文件以查看生成的指令:

fromelf --disassemble vec_add.o -o disassembly_vec_on.txt

反汇编的代码类似于以下内容:

vec_add                  ; Alternate entry point
        CMP      w3,#1
        B.LT     |L3.184|
        CMP      w3,#4
        MOV      w8,w3
        MOV      x9,xzr
        B.CC     |L3.140|
        LSL      x10,x8,#2
        ADD      x12,x0,x10
        ADD      x11,x2,x10
        CMP      x12,x2
        ADD      x10,x1,x10
        CSET     w12,HI
        CMP      x11,x0
        CSET     w13,HI
        CMP      x10,x2
        CSET     w10,HI
        CMP      x11,x1
        AND      w12,w12,w13
        CSET     w11,HI
        TBNZ     w12,#0,|L3.140|
        AND      w10,w10,w11
        TBNZ     w10,#0,|L3.140|
        AND      x9,x8,#0xfffffffc
        MOV      x10,x9
        MOV      x11,x2
        MOV      x12,x1
        MOV      x13,x0
|L3.108|
        LDR      q0,[x13],#0x10
        LDR      q1,[x12],#0x10
        SUBS     x10,x10,#4
        FADD     v0.4S,v0.4S,v1.4S
        STR      q0,[x11],#0x10
        B.NE     |L3.108|
        CMP      x9,x8
        B.EQ     |L3.184|
|L3.140|
        LSL      x12,x9,#2
        ADD      x10,x2,x12
        ADD      x11,x1,x12
        ADD      x12,x0,x12
        SUB      x8,x8,x9
|L3.160|
        LDR      s0,[x12],#4
        LDR      s1,[x11],#4
        SUBS     x8,x8,#1
        FADD     s0,s0,s1
        STR      s0,[x10],#4
        B.NE     |L3.160|
|L3.184|
        RET

从指令FADD v0.4S,v0.4S,v1.4S可以看出,SLP自动矢量化已成功完成,该指令对打包到SIMD寄存器中的四个32位浮点数执行加法运算。 但是,这给代码大小带来了巨大的代价,因为它必须检测SIMD宽度不是数组长度的因数的情况。 取决于项目和目标硬件,这样的代码大小增加可能是可接受的,也可能不是。 对于代码大小的变化与可用内存相比微不足道的电话应用程序,这可能是可以容忍的,但是对于具有少量RAM的嵌入式应用程序,这是不可接受的。

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值