美文网首页
Neon指令入门---第一个neon指令程序

Neon指令入门---第一个neon指令程序

作者: 教训小磊 | 来源:发表于2022-04-07 01:08 被阅读0次

    最近工作需要用到neon指令加速模型推理,所以在此记录neon指令的学习过程,一方面加强自己的记忆,另一方面帮助更多像我一样的小白早日实现财务自由。

    好了,neon指令的基本概念我就不多阐述了,直接上代码:
    c代码,主要实现这样一个简单的功能:

    void first_example_c(unsigned char  *src, unsigned char  *dst, int size, unsigned char  factor)
    {
        for (int i = 0; i < size; i++)
        {
            dst[i] = src[i] * factor;
        }
    }
    

    下面是使用neon指令实现的及具体步骤:

    #include<arm_neon.h>
    #include<stdio.h>
    
    void first_example_neon(unsigned char  *src, unsigned char  *dst, int size, unsigned char  factor)
    {
        int main_loop = size / 8;                 //一个循环处理8个数据,则需要 size / 8个循环
        uint8x8_t factor_vct = vdup_n_u8(factor); //将系数factor装载入neon寄存器
        for (int i = 0; i < main_loop; i++)
        {
            uint8x8_t src_vct = vld1_u8(src);    //将源数据装载入neon寄存器
            uint8x8_t dst_vct = vmul_u8(src_vct, factor_vct);  //执行乘法操作,且将结果放入dst_vct寄存器中
            vst1_u8(dst, dst_vct);              //将dst_vct寄存器中的结果放回内存中
            src += 8, dst += 8;                 //改变地址,指向下个循环要处理的数据。
        }
        int aa = size - main_loop * 8;          //考虑到size不能被8整除的情况
        for (int j = 0; j < aa; j++)
        {
            *dst = *src*factor;
            dst++;
            src++;
        }
    }
    void main()
    {
        unsigned char a[9] = { 1,2,3,4,5,6,7,8,9 };
        unsigned char b[9];
        int size = 9;
        unsigned char factor = 2;
        first_example_neon(a, b, size, factor);
        for (int i = 0; i < 9; i++)
        {
            printf("%d\n", b[i]);
        }
    }
    

    这里面用到了:uint8x8_t、vdup_n_u8、vld1_u8、vmul_u8和vst1_u8这几个neon指令。

    1. uint8x8_t
      表示寄存器的数据类型,第一个数字代表的是数据类型的宽度有8/16/32/64,这里数据宽度为8,第二个数字代表一个寄存器中该类型数据的数量,这里也是8。所以uint8x8_t表示8位无符号数的寄存器中共有8个数据。
    2. vdup_n_u8
      对向量进行复制,用于初始化,uint8x8_t factor_vct = vdup_n_u8(factor)表示将寄存器factor_vct存储的8个unsigned char都初始化为factor,如果factor=2,则factor_vct=[2,2,2,2,2,2,2,2]。
    3. vld1_u8
      将数据载入到寄存器中,uint8x8_t src_vct = vld1_u8(src),表示从src中取8个数据(为什么是8个?因为uint8x8类型的寄存器只能存8个数据)到寄存器src_vct中。
    4. vmul_u8
      向量相乘
    5. vst1_u8
      将寄存器中的数据放回内存中。

    附加:
    基本数据类型:
    64 位
    int8x8_t, int16x4_t, int32x2_t, int64x1_t,
    uint8x8_t, uint16x4_t, uint32x2_t, uint64x1_t,
    float32x2_t, float64x1_t(少见)
    128 位
    int8x16_t, int16x8_t, int32x4_t, int64_2_t,
    uint8x16_t, uint16_8_t, uint32x4_t, uint64x4_t,
    float32x4_t

    另外放一些网址用于neon学习:
    1.neon指令查询:https://developer.arm.com/architectures/instruction-sets/intrinsics/#q=vextq_f32
    2.一些指令参考:https://blog.csdn.net/weixin_41965270/article/details/89248540
    3.一些简单的实例:https://www.jianshu.com/p/70601b36540f

    相关文章

      网友评论

          本文标题:Neon指令入门---第一个neon指令程序

          本文链接:https://www.haomeiwen.com/subject/ciqjsrtx.html