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

2022-04-07  本文已影响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

上一篇下一篇

猜你喜欢

热点阅读