imx6ull移植Ne10库

imx6ull cortex-A7 armv7架构,已经引入了neon技术。ubuntu版本是16.04。Ne10则是引用了该技术,对数学计算进行优化,例如傅里叶变换、滤波、矩阵计算等。Ne10库在github上有源码,我用的版本是截至目前最新的。在一块老的A9平台编译,使用最新的版本编译,出现了很多问题,最后重新下载了最低的Ne10的版本,编译通过了。

编译Ne10需要用到cmake,如果环境中没有,需要安装下。Ne10下载包的doc里有building.md,讲述了如何编译。首先要使用cmake配置编译选项,涉及两个文件,第一个文件是GUNlinux_config.cmake,另一个是CMakeList.txt。

一步一步来,根据building.md里边的提示敲命令行:
//
cd $NE10_PATH
mkdir build && cd build
export NE10_LINUX_TARGET_ARCH=armv7 # Can also be “aarch64”
cmake -DCMAKE_TOOLCHAIN_FILE=…/GNUlinux_config.cmake …
make
/
/
当执行到cmake这句时,出现问题:
在这里插入图片描述
该错误和编译链有关,在GUNlinux_config.cmake文件中指定下编译链,再编译。在GUNlinux_config.cmake文件中添加的内容如下:
set(CMAKE_C_COMPILER /opt/imx6ull-yocto-L4.1.15-2.1.0/toolchain-qt5.6.2/sysroots/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-gnueabi/arm-poky-linux-gnueabi-gcc)
set(CMAKE_CXX_COMPILER /opt/imx6ull-yocto-L4.1.15-2.1.0/toolchain-qt5.6.2/sysroots/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-gnueabi/arm-poky-linux-gnueabi-g++)
set(CMAKE_ASM_COMPILER /opt/imx6ull-yocto-L4.1.15-2.1.0/toolchain-qt5.6.2/sysroots/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-gnueabi/arm-poky-linux-gnueabi-as)

再次编译,又一次出现问题:
在这里插入图片描述
编译链是找到了,但编译过程中需要搜索的路径不对。mmp. 百度了下,GUNlinux_config.cmake文件中指定了下CMAKE_SYSROOT参数:set(CMAKE_SYSROOT “/opt/imx6ull-yocto-L4.1.15-2.1.0/toolchain-qt5.6.2/sysroots/cortexa7hf-neon-poky-linux-gnueabi”);再次编译,依然出错:
在这里插入图片描述
百度呗。意思是检测我的编译链不行,太low。mmp,就非要用这个链编译。于是在cmake又多加俩参数,配置成功了。 cmake -DCMAKE_TOOLCHAIN_FILE=…/GNUlinux_config.cmake -DCMAKE_C_COMPILER_WORKS=ON -DCMAKE_CXX_COMPILER_FORCED=ON …
在这里插入图片描述
接下来就是执行make。开始编译库。刚执行,又报错,fk. 如下:
在这里插入图片描述
又没有头文件,不都指定了吗,继续百度吧。是编译选项不对,没指定-mfloat-abi编译选项,加吧。把build文件夹删除,然后在GUNlinux_config.cmake文件中添加如下语句:
set(CMAKE_C_FLAGS “-mfloat-abi=hard”)

从头再来!
//
mkdir build && cd build
export NE10_LINUX_TARGET_ARCH=armv7 # Can also be “aarch64”
cmake -DCMAKE_TOOLCHAIN_FILE=…/GNUlinux_config.cmake …
make
/
/

呦吼!!!编译过了。如图:
在这里插入图片描述

我编译的是静态库,如果想编译动态库,可以在CMakeList.txt中修改。
//
option(NE10_BUILD_SHARED “Build NE10 shared libraries” OFF)
option(NE10_BUILD_STATIC “Build NE10 static libraries” ON)
/
/
默认的是编译静态库。如果想编译动态库,就把第一行OFF改成ON,把第二行ON改为OFF。没测试编译动态库。

至此,Ne10的库就编译完成了。编译好的静态库在build/modules文件夹里libNE10.a。注意引用的时候还需要引用头文件,在inc目录里。build目录里还有个samples文件夹,里边有个demo,NE10_test_static,这个拷贝到开发板上,可以直接运行,计算fft啥的。

再说一下使用neon和不使用的对比。我所运行的代码包括fft、滤波、比特转符号等操作,对算法不熟悉,其实是在同事那拷贝过来的,然后替换部分函数使用neon,做对比。imx6ull开发板cpu运行在528M,不开启优化等级的时候:

当不使用neon时,运行一次所用时间大约是10.101ms。使用了neon后,运行一次大约是7.544ms。
使用neon分为两种情况:

第一种情况,使用Ne10库。原始代码中fft是自行编写,优化后是使用Ne10库中的fft计算。ne10_fft_c2c_1d_float32(dst, src, cfg, 0);如何使用请看demo。
这种情况运行一次所用时间大约是7.742ms。

第二种情况,使用编译链中提供的neon函数,在第一种情况基础上再次优化。编译链中提供的函数在arm_neon.h里,是内联函数。
在这里插入图片描述

使用这些函数计算编译后对应就是使用neon指令进行操作,在汇编文件已经查看:
在这里插入图片描述
指令前带v的,应该都是neon指令。说一下函数怎么用。先粘贴正常的代码:
for(i = 0; i < 2304; i++)
{
data= data1[i] + data2[i];
data = Modtopi(data);
data3[i] = data ;
}
变量都是int32类型的。

再粘一下使用arm_neon.h里函数的:

int32x4_add_neon(&data[0], (int32_t *)&data2[0], data3);

static void int32x4_add_neon(int32_t * sum, int32_t* sum2, int32_t* sum3)
{
int32_t sum4[2304];
int32x4_t sum1_v, sum2_v, sum_v;
uint16_t i, j;

for(i = 0; i < 576; i++)
{
	sum1_v = vld1q_s32(&sum[4*i]);  
	sum2_v = vld1q_s32(&sum2[4*i]);    
	sum_v = vaddq_s32 (sum1_v, sum2_v); 
	vst1q_s32 (&sum4[4*i], sum_v) ; 
	Mod2Pi_x(&sum4[4*i], &sum3[4*i]);
}

}

能够看出来,变量全是矢量了,所以分别把数组转换成矢量,然后加法,然后再把矢量转为数组。矢量类型int32x4_t 的含义是4个int32的数(个人理解,不一定对)。然后vld1q_s32转换时一次能转换4个int32数据到int32x4_t 里,所以长度是2304的数据需要转换576次。替换的代码不难,但是确有提升。arm_neon.h里有很多函数,需要慢慢查看。

个人纪录,如有错误,还望指正。

																																										与君共勉
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值