我有一些Android的C代码可以进行大量的低级数字运算。我想知道我应该使用哪些设置(例如我的Android.mk和Application.mk),以便生成的代码可以在所有当前的Android设备上运行,但也可以利用特定芯片组的优化。我正在寻找使用良好的默认Android.mk和Application.mk设置,我希望避免使用#ifdef分支丢弃我的C代码。
例如,我知道ARMv7有浮点指令,一些ARMv7芯片支持NEON指令,默认ARM不支持这些指令。是否可以设置标志,以便我可以使用NEON,没有NEON的ARMv7和默认的ARM构建来构建ARMv7?我知道如何做后两者但不是全部3.我对我使用的设置持谨慎态度,因为我认为当前的默认值是最安全的设置,以及其他选项有什么风险。
对于GCC特定的优化,我使用以下标志:
LOCAL_CFLAGS=-ffast-math -O3 -funroll-loops
我已经检查了所有这三个加速了我的代码。我还可以添加其他常见的吗?
我的另一个提示是将“LOCAL_ARM_MODE:= arm”添加到Android.mk,以便加速更新的手臂芯片(尽管我对这件事以及旧芯片上发生的事情感到困惑)。
答案 0 :(得分:112)
ARM处理器有两个支持的通用指令集:“ARM”和“Thumb”。虽然两者都有不同的风格,但ARM指令各为32位,Thumb指令为16位。两者之间的主要区别在于ARM指令可以在一条指令中完成比Thumb更多的操作。例如,单个ARM指令可以将一个寄存器添加到另一个寄存器,同时在第二个寄存器上执行左移。在Thumb中,一条指令必须进行移位,然后第二条指令才能进行移位。
ARM指令不是两倍好,但在某些情况下它们可以更快。在手动ARM组件中尤其如此,它可以以新颖的方式进行调整,以充分利用“免费换档”。拇指指令有其自身的优势和尺寸:它们可以减少电量消耗。
无论如何,这就是LOCAL_ARM_MODE的作用 - 它意味着您将代码编译为ARM指令而不是Thumb指令。编译为Thumb是NDK中的默认值,因为它倾向于创建较小的二进制文件,并且速度差异对于大多数代码而言并不明显。编译器不能总是利用ARM可以提供的额外“oomph”,因此最终需要或多或少相同数量的指令。
从编译为ARM或Thumb的C / C ++代码中看到的结果将是相同的(禁止compiler bugs)。
这本身适用于所有现有Android手机的新旧ARM处理器。这是因为默认情况下,NDK编译为支持ARMv5TE指令集的基于ARM的CPU的“应用程序二进制接口”。这个ABI被称为“armeabi”,可以通过放置APP_ABI := armeabi
在Application.mk中明确设置。
较新的处理器还支持称为armeabi-v7a
的特定于Android的ABI,它扩展了armeabi以添加Thumb-2 instruction set和名为VFPv3-D16的硬件浮点指令集。 armeabi-v7a兼容CPU还可以选择支持NEON指令集,您必须在运行时检查它,并提供可用时和不可用时的代码路径。在NDK / samples目录中有一个例子(hello-neon)。在引擎盖下,Thumb-2更像“ARM-like”,因为它的指令可以在一条指令中完成更多工作,同时具有占用更少空间的优势。
为了编译包含armeabi和armeabi-v7a库的“胖二进制文件”,您可以将以下内容添加到Application.mk中:
APP_ABI := armeabi armeabi-v7a
安装.apk文件后,Android软件包管理器会为该设备安装最佳库。因此,在较旧的平台上,它将安装armeabi库,而在较新的设备上安装armeabi-v7a库。
如果要在运行时测试CPU功能,则可以使用NDK功能uint64_t android_getCpuFeatures()
来获取处理器支持的功能。如果支持硬件浮点,则在v7a处理器上返回ANDROID_CPU_ARM_FEATURE_ARMv7
的位标志,ANDROID_CPU_ARM_FEATURE_VFPv3
;如果支持高级SIMD指令,则返回ANDROID_CPU_ARM_FEATURE_NEON
。没有VFPv3,ARM不能拥有NEON。
总结:默认情况下,您的程序最兼容。使用LOCAL_ARM_MODE可能会因为使用ARM指令而使电池寿命稍微快一些 - 并且它与默认设置兼容。通过添加APP_ABI := armeabi armeabi-v7a
行,您可以在较新的设备上提高性能,保持与旧设备兼容,但您的.apk文件会更大(由于有2个库)。为了使用NEON指令,您需要编写在运行时检测CPU功能的特殊代码,这仅适用于可以运行armeabi-v7a的新设备。
答案 1 :(得分:23)
很棒的答案,就像添加你应该使用
一样APP_ABI := all
这将编译4个二进制文件,armv5,armv7,x86和mips
您可能需要新版本的ndk