如何在Android NDK中为特定文件设置优化级别?

时间:2012-09-30 18:24:53

标签: android optimization android-ndk neon

我有一个Android原生库,其中包含一些包含NEON汇编代码的文件。我从其他编码器那里继承了这个代码,并且考虑到我对NEON汇编编码(或者任何汇编,对于那个问题)的了解,至少可以说是吝啬。无论如何,我注意到以下问题:当我用'ndk-build NDK_DEBUG = 1'编译时,一切都很好。当我编译发布'ndk-build NDK_DEBUG = 0'时,编译器会优化汇编代码。我设法通过破解ndk构建脚本来解决这个问题,并将我的库分成两个,其中一个lib包含所有的汇编文件 - 对于这个库,我以非常hacky的方式将优化设置为'-O0' 。 所以问题是:如何为特定文件指定优化级别?设置APP_OPTIM在Application.mk中完成,它影响所有编译的文件。 NDK_DEBUG标志也是如此。

编辑:根据Alex的要求,这里是我最终使用的Android.mk,将lib分成两部分:一部分使用汇编代码(和-O0),另一部分使用常规C代码(和-O2):< / p>
LOCAL_PATH := $(call my-dir)

# assembly_neon_code_here (neon) module - turn optimization off
include $(CLEAR_VARS)

LOCAL_MODULE := assembly_neon_code_here
LOCAL_SRC_FILES := assembly_neon_code_here.cpp
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
    LOCAL_ARM_NEON := true
endif

LOCAL_CFLAGS := -O0
LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog 
include $(BUILD_SHARED_LIBRARY)

# main module
include $(CLEAR_VARS)

LOCAL_MODULE    := complete_lib
LOCAL_SRC_FILES := regular_src1.cpp regular_src2.cpp regular_src3.cpp 
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
    LOCAL_ARM_NEON := true
endif

# allow logcat calls
LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog -lz
LOCAL_SHARED_LIBRARIES := assembly_neon_code_here
include $(BUILD_SHARED_LIBRARY)

2 个答案:

答案 0 :(得分:3)

GCC&gt; = 4.4似乎支持#pragma GCC optimize更改中间文件的优化级别,并且还将optimize属性设置为按功能设置。

请参阅http://gcc.gnu.org/onlinedocs/gcc-4.4.7/gcc/Function-Specific-Option-Pragmas.html#Function-Specific-Option-Pragmashttp://gcc.gnu.org/onlinedocs/gcc-4.4.7/gcc/Function-Attributes.html#Function-Attributes

根据这些链接,将#pragma GCC optimize ("O0")放在导致问题的文件顶部应该可以解决问题。

答案 1 :(得分:1)

我不知道如何更改每个文件的优化级别,但这样做可能会损害您的应用程序的性能,所以我不会推荐它。我假设汇编代码是内联汇编块的形式,即汇编编码器的块与普通的C或C ++代码交错。它看起来如下

asm {
  .. assembly goes here, usually each line in double-quotes, often ending in \n\t
  : ... input operands. Might not be present ...
  : ... output operands. Might not be present ...
  : ... clobber operands. Might not be present ...
}

编译器删除内联汇编块的最可能原因是它不包含输出操作数,或者输出操作数是否全部未使用。您可以通过将内联汇编块标记为volatile来避免尝试,它会告诉编译器不要弄乱它。为此,只需在volatile关键字后面写asm

阻止编译器搞乱内联汇编块的另一件事是在其clobber列表中添加“内存”。这告诉编译器程序集正在读取或写入任意内存位置。当你在它的时候,也加上“cc”来衡量。这告诉编译器内联汇编与条件代码寄存器混淆,即它执行影响后续条件分支指令行为的测试指令。

总之,尝试使所有内联汇编块看起来像这样

asm volatile {
  .. whatever ...
  : ... whatever ...
  : ... whatever ...
  : ... whatever ..., "cc", "memory"
}

请注意,asm也可拼写为__asm__,而volatile也可拼写为__volatile__