NE10库使用
NE10库编译
官方编译Ne10文档:https://github.com/projectNe10/Ne10/blob/master/doc/building.md#building-ne10
NE10交叉编译(推荐)
- sudo apt-get install gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf
- git clone https://gitee.com/ykhumanspider/Ne10.git
- cd $NE10_PATH
- vi CMakeLists.txt
//将OFF改成ON ,option(NE10_BUILD_UNIT_TEST “Build NE10 unit test” ON)(原来是OFF)
// 将OFF改为ON ,option(NE10_PERFORMANCE_TEST “Run performance test” ON)(原来是OFF)
- export NE10_LINUX_TARGET_ARCH=armv7(64位则是aarch64)
- mkdir build && cd build
- cmake -DCMAKE_TOOLCHAIN_FILE=../GNUlinux_config.cmake ..
- make
可能遇到的问题:
找不到编译器:
解决办法
- 查看哪些版本可以安装()
apt-cache search aarch64- 选择某个需要的版本进行安装
apt-get install gcc-10-aarch64-linux-gnu- 然后重新编译即可
在Ne10主目录的CMakeLists.txt可以配置编译静态库还是动态库
option(NE10_BUILD_SHARED "Build NE10 shared libraries" OFF)
option(NE10_BUILD_STATIC "Build NE10 static libraries" ON)
build文件夹下面会生成modules文件夹,里面有 libNE10.a静态库文件
samples文件夹里面有例程库里面的例程编译成的静态库执行文件 NE10_test_static
test文件夹里面也有几个测试程序
构建测试单元
Ne10 有许多单元测试,围绕测试框架的修改版本"seatest"构建。特别是,该项目有三种不同的测试模式:
- 一致性测试(也称为烟雾测试),以检查库是否正常工作。
- 回归测试,类似于一致性测试,但更具体地旨在测试库在更改后是否仍然正常运行。
- 性能测试,它指示库执行某些任务的速度。
可以通过指定CMake的-DNE10_BUILD_UNIT_TEST = ON选项以及以下其中一项来构建这些文件 。
- DNE10_BUILD_UNIT_TEST=ON
- DNE10_SMOKE_TEST=ON
- DNE10_REGRESSION_TEST=ON
- DNE10_PERFORMANCE_TEST=ON$NE10_PATH/build/test/
然后将在目录中生成每个 Ne10 模块的相应测试程序。
NE10库的使用
API文档:http://projectne10.github.io/Ne10/doc/modules.html
静态库的使用方法和普通静态库一样,把静态库文件和Ne10目录下的inc头文件文件夹放入自己的工程下即可开始编程
ArmV7编程
/usr/bin/arm-linux-gnueabihf-gcc -fno-strict-aliasing -O2 -DNDEBUG -mthumb -march=armv7-a -mfpu=neon-vfpv3 -o test test.c libNE10.a -lm
编译命令如上,根据需求编写Makefile文件(以后再补上)
Aarch64编程
/usr/bin/aarch64-linux-gnu-gcc -fno-strict-aliasing -O2 -DNDEBUG -o test test.c libNE10.a -lm
注意上面armv7和aarch64架构处理器使用的编译工具链有所不同,根据需要去掉DEBUG编译
编程方法
有关编译器的说明(A9 armv7)
E9V2采用的交叉编译器是gcc-arm-linux-gnueabihf,有关编译器区别如下
• gcc-arm-linux-gnueabi – The GNU C compiler for armel architecture
• gcc-arm-linux-gnueabihf – The GNU C compiler for armhf architecture可见这两个交叉编译器适用于armel和armhf两个不同的架构, armel和armhf这两种架构在对待浮点运算采取了不同的策略(有fpu的arm才能支持这两种浮点运算策略)
其实这两个交叉编译器只不过是gcc的选项-mfloat-abi的默认值不同. gcc的选项-mfloat-abi有三种值soft,softfp,hard(其中后两者都要求arm里有fpu浮点运算单元,soft与后两者是兼容的,但softfp和hard两种模式互不兼容):
- soft : 不用fpu进行浮点计算,即使有fpu浮点运算单元也不用,而是使用软件模式。
- softfp : armel架构(对应的编译器为gcc-arm-linux-gnueabi)采用的默认值,用fpu计算,但是传参数用普通寄存器传,这样中断的时候,只需要保存普通寄存器,中断负荷小,但是参数需要转换成浮点的再计算。
- hard : armhf架构(对应的编译器gcc-arm-linux-gnueabihf)采用的默认值,用fpu计算,传参数也用fpu中的浮点寄存器传,省去了转换, 性能最好,但是中断负荷高
经测试只能使用gcc-arm-linux-gnueabihf
有关编译选项的说明
- -mfpu = name(neon or vfpvx)指定FPU 单元
- -mfloat-abi = name(soft、hard、 softfp):指定软件浮点或硬件浮点或兼容软浮点调用接口
如果只指定 -mfpu,那么默认编译不会选择选择硬件浮点指令集
如果只指定 -mfloat-abi = hard或者softfp,那么编译会使用硬件浮点指令集
经过测试使用gcc-arm-linux-gnueabihf编译器-mfloat-abi只能使用hard硬件浮点编译
-mfpu=neon-vfpv3、-mfpu=neon、-mfpu= vfpv3三种情况测试运算结果时间一样 - -fopenmp 多核调度,这个以后单独细说
有关程序计算时间说明:
经过搜寻NE10库源代码,寄存器的存取操作应该是已经封装在函数中了,比如:
ne10_mat4x4f_t src[MATRICES]; // 输入矩阵MATRICES*4的源数组
ne10_vec4f_t mul[MATRICES]; // 一组矩阵,用于将src中的矩阵乘以
ne10_vec4f_t dst[MATRICES]; // 乘法结果的目标数组
上面创建的数组应该是在内存中创建的,当执行矩阵运算时:
ne10_mulcmatvec_cm4x4f_v4f_c(dst, src, mul, MATRICES); //矩阵与向量相乘
就已经进行了将数据放入neon寄存器-计算-取出到内存的操作了
所以这里测试的时间的开始时间与结束时间在上面这个函数的前面与后面
有关NE10库的说明
NE10库在armv8架构的处理器上面还不支持数学和物理运算的库,暂时只支持DSP信号处理和图像处理函数。并且在数学库,只支持浮点型运算函数
开始编程
使用前先初始化ne10库
if (ne10_init() != NE10_OK)
{
fprintf(stderr, "Failed to initialise Ne10.\n");
return 1;
}
一些程序优化技巧
重点关注for循环部分,尽量取代并且不使用for循环
数值复制时尽量不要使用for循环,可以考虑memcpy等函数