android.mk ndk编译选项优化,Android NDK(ARM开发)使用NEON优化 - Fla

从CSDN博客搬家:

在进行Android开发时,一般考虑加速某些算法处理速率时,需要使用NDK进行开发,

为了进一步加速程序执行速率,还可以进行汇编级别的优化。

比如采用 NEON 技术进行代码的优化,以实现模块处理效率的成倍增长。

在C/C++中使用内联汇编的用法如下:

asm(

"ADD R0,R0,#1 \n\t" // 使R0寄存器值增加1,后面加换行符和制表符是为了汇编代码的美观,其中有多条指令时 换行符是必须的

"SUB R0,R0,#1 " // 使R0寄存器的值减少1

);

然后是如何在NDK中编译使用这种指令,需要修改Android.mk和Application.mk两个文件:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

# 这里填写要编译的源文件路径,这里只列举了一部分

LOCAL_SRC_FILES := NcHevcDecoder.cpp JNI_OnLoad.cpp TAppDecTop.cpp

# 默认包含的头文件路径

LOCAL_C_INCLUDES := \

$(LOCAL_PATH) \

$(LOCAL_PATH)/..

# -g 后面的一系列附加项目添加了才能使用 arm_neon.h 头文件 -mfloat-abi=softfp -mfpu=neon 使用 arm_neon.h 必须

LOCAL_CFLAGS := -D__cpusplus -g -mfloat-abi=softfp -mfpu=neon -march=armv7-a -mtune=cortex-a8

LOCAL_LDLIBS := -lz -llog

TARGET_ARCH_ABI :=armeabi-v7a

LOCAL_ARM_MODE := arm

ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)

# 采用NEON优化技术

LOCAL_ARM_NEON := true

endif

LOCAL_MODULE := avcodecinclude $(BUILD_STATIC_LIBRARY)

include $(BUILD_SHARED_LIBRARY)

下面是Application.mk,需要指定编译的目标平台类型:

APP_PROJECT_PATH := $(call my-dir)/..

APP_PLATFORM := android-10

APP_STL := stlport_static

APP_ABI := armeabi-v7a

APP_CPPFLAGS += -fexceptions

其中APP_ABI这句指定了编译的目标平台类型,可以针对不同平台进行优化。

当然这样指定了之后,就需要相应的设备支持NEON指令。

我的一个NDK应用,在使用上述配置之后,即NEON优化等,程序的性能提升了近一倍。

系统的处理延时由原来的 95ms左右降低到了 51ms。

后续可以使用NEON库进一步优化 NDK 程序代码,实现更加优化的结果。

PS:参考的文章有如下几篇,可能跟我的平台有所不同,所以我都不能完全照搬使用:

1、未使用NEON优化的代码

void reference_convert (uint8_t * __restrict dest, uint8_t * __restrict src, int n)

{

int i;

for (i=0; i

{

int r = *src++; // load red

int g = *src++; // load green

int b = *src++; // load blue

// build weighted average:

int y = (r*77)+(g*151)+(b*28);

// undo the scale by 256 and write to memory:

*dest++ = (y>>8);

}

}

2、使用NEON进行优化的代码

void neon_convert (uint8_t * __restrict dest, uint8_t * __restrict src, int n)

{

int i;

uint8x8_t rfac = vdup_n_u8 (77); // 转换权值 R

uint8x8_t gfac = vdup_n_u8 (151); // 转换权值 G

uint8x8_t bfac = vdup_n_u8 (28); // 转换权值 B

n/=8;

for (i=0; i

{

uint16x8_t temp;

uint8x8x3_t rgb = vld3_u8 (src);

uint8x8_t result;

temp = vmull_u8 (rgb.val[0], rfac); // vmull_u8 每个字节(8bit)对应相乘,结果为每个单位2字节(16bit)

temp = vmlal_u8 (temp,rgb.val[1], gfac); // 每个比特对应相乘并加上

temp = vmlal_u8 (temp,rgb.val[2], bfac);

result = vshrn_n_u16 (temp, 8); // 全部移位8位

vst1_u8 (dest, result); // 转存运算结果

src += 8*3;

dest += 8;

}

}

3、汇编优化

// 这里针对生成的目标汇编代码进一步作了优化,优化的代码如下:

convert_asm_neon:

# r0: Ptr to destination data

# r1: Ptr to source data

# r2: Iteration count:

push {r4-r5,lr}

lsr r2, r2, #3

# build the three constants:

mov r3, #77

mov r4, #151

mov r5, #28

vdup.8 d3, r3

vdup.8 d4, r4

vdup.8 d5, r5

.loop:

# load 8 pixels:

vld3.8 {d0-d2}, [r1]!

# do the weight average:

vmull.u8 q3, d0, d3

vmlal.u8 q3, d1, d4

vmlal.u8 q3, d2, d5

# shift and store:

vshrn.u16 d6, q3, #8

vst1.8 {d6}, [r0]!

subs r2, r2, #1

bne .loop

pop { r4-r5, pc }

最后的结果对比:

C-version:             15.1 cycles per pixel.

NEON-version:       9.9 cycles per pixel.

Assembler:             2.0 cycles per pixel.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值