项目中的安卓APP不仅需要C语言来提高速度,还需要NEON指令进一步提高RemoteFX的解码速度,本笔记记录了安卓系统下C程序如何使用NEON指令。
- 新建neonTest.c,内容如下:
注意要包含头文件"arm_neon.h"。
关于NEON的用法,见《NEON指令集函数列表》这篇笔记。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <arm_neon.h>
//neon指令运算
void simd(unsigned short *output, unsigned short *input, int num){
while(num >= 8){
vst1q_u16(output, vshrq_n_u16(vmulq_n_u16(vshrq_n_u16(vmulq_n_u16(vld1q_u16(input), 17), 1), 19), 1));
output += 8;
input += 8;
num -= 8;
}
while(num > 0){
*output = ((((*input * 17) >> 1) * 19) >> 1);
output += 1;
input += 1;
num -= 1;
}
}
//非neon指令运算
void sisd(unsigned short *output, unsigned short *input, int num){
while(num > 0){
*output = ((((*input * 17) >> 1) * 19) >> 1);
output += 1;
input += 1;
num -= 1;
}
}
void init(unsigned short *data){
unsigned short i, j;
for(i=0; i<100; i++){
for(j=0; j<30; j++){
*data = i+j;
data += 1;
}
}
}
void dump(unsigned short *data){
unsigned short i, j;
for(i=0; i<100; i++){
for(j=0; j<30; j++){
printf("%5d", *data);
data += 1;
}
putchar('\n');
}
}
int main(int argc, char* argv[]){
if(argc < 3) return 0;
unsigned short buffer1[3000];
unsigned short buffer2[3000];
init(buffer1);
if(strcmp(argv[1], "simd") == 0){
int n = atoi(argv[2]);
while(n-- > 0) simd(buffer2, buffer1, 3000);
}
else if(strcmp(argv[1], "sisd") == 0){
int n = atoi(argv[2]);
while(n-- > 0) sisd(buffer2, buffer1, 3000);
}
if(argc >= 4){
dump(buffer1);
putchar('\n');
dump(buffer2);
}
return 0;
}
这个neon测试程序,根据第一个参数选择是用NEON指令还是非NEON指令来对3000个数做简单的乘法运算和移位运算,并根据第二个参数来决定这样的运算做多少遍。使用time命令来执行这个测试程序,根据运行时间粗略比较NEON指令的效率。
- 新建Makefile文件,内容如下:
ARG1=-ID:\Android\ndk64\sysroot\usr\include -ID:\Android\ndk64\sysroot\usr\include\arm-linux-androideabi -Wall -Wno-attributes
ARG2=--sysroot=D:\Android\ndk64\platforms\android-19\arch-arm -Wall
neonTest.out : neonTest.o
arm-linux-androideabi-gcc.exe -o neonTest.out neonTest.o $(ARG2)
neonTest.o : neonTest.c
arm-linux-androideabi-gcc.exe -c -o neonTest.o neonTest.c $(ARG1)
cls:
del neonTest.o
del neonTest.out
-
打开批处理命令行,敲make命令编译:
编译失败。根据提示信息,需要让编译器启用NEON,见上图红框。
关于批处理命令行环境变量的配置方法,见《安卓系统应用程序纯命令行编译环境_第一个C程序hello.c》这篇笔记。 -
编辑Makefile,添加编译选项
-mfloat-abi=softfp -mfpu=neon
并保存,再次敲make命令: -
编译成功,生成了可执行文件neonTest.out:
-
将可执行文件拷贝到开发板上运行试试:
从运行结果可以看出,对3000个数做10万遍运算,采用NEON指令大约用时3.38秒,采用非NEON指令大约用时5.36秒。
网友评论