Процессоры ARM имеют 2 общих набора команд, которые они поддерживают: «ARM» и «Thumb». Хотя есть разные варианты обоих, инструкции ARM - 32 бита каждая, а инструкции Thumb - 16 бит. Основное различие между ними состоит в том, что инструкции ARM имеют возможность делать больше за одну инструкцию, чем Thumb. Например, одна инструкция ARM может добавить один регистр в другой регистр, выполняя сдвиг влево по второму регистру. В Thumb одна инструкция должна выполнить сдвиг, затем вторая инструкция добавит.
Инструкции ARM не в два раза лучше, но в некоторых случаях они могут быть быстрее. Это особенно актуально для сборки ARM, свернутой вручную, которая может быть настроена новыми способами, чтобы наилучшим образом использовать «сдвиги бесплатно». Инструкции для большого пальца имеют свои преимущества и размер: они меньше разряжают батарею.
В любом случае, это то, что делает LOCAL_ARM_MODE - это означает, что вы компилируете свой код как инструкции ARM вместо инструкций Thumb. Компиляция в Thumb является значением по умолчанию в NDK, так как он имеет тенденцию создавать меньший двоичный файл, и разница в скорости не так заметна для большинства кода. Компилятор не всегда может воспользоваться преимуществами дополнительной «поддержки», которую может предоставить ARM, так что в конечном итоге вам все равно понадобится более или менее одинаковое количество инструкций.
Результат того, что вы видите из кода C / C ++, скомпилированного в ARM или Thumb, будет идентичным (исключая ошибок компилятора ).
Это совместимо между новыми и старыми процессорами ARM для всех телефонов Android, доступных сегодня. Это связано с тем, что по умолчанию NDK компилируется в «двоичный интерфейс приложения» для процессоров на основе ARM, которые поддерживают набор инструкций ARMv5TE. Этот ABI известен как «armeabi» и может быть явно установлен в Application.mk, поставив APP_ABI := armeabi
.
Более новые процессоры также поддерживают специфичный для Android ABI, известный как armeabi-v7a
, который расширяет armeabi для добавления набора команд Thumb-2 и набора аппаратных команд с плавающей запятой под названием VFPv3-D16. Совместимые с armeabi-v7a процессоры также могут дополнительно поддерживать набор команд NEON, который вы должны проверять во время выполнения и предоставлять пути к коду, когда он доступен, а когда нет. В каталоге NDK / samples есть пример, который делает это (привет-неон). Под капотом Thumb-2 более «ARM-подобен» в том смысле, что его инструкции могут выполнять больше операций за одну инструкцию, но при этом имеют преимущество, занимая меньше места.
Чтобы скомпилировать «толстый двоичный файл», содержащий библиотеки armeabi и armeabi-v7a, вы должны добавить в Application.mk:
следующее
APP_ABI := armeabi armeabi-v7a
Когда файл .apk установлен, менеджер пакетов Android устанавливает лучшую библиотеку для устройства. Так что на старых платформах будет установлена библиотека armeabi, а на новых устройствах - armeabi-v7a.
Если вы хотите проверить функции ЦП во время выполнения, вы можете использовать функцию NDK uint64_t android_getCpuFeatures()
, чтобы получить функции, поддерживаемые процессором. Возвращает битовый флаг ANDROID_CPU_ARM_FEATURE_ARMv7
на процессорах v7a, ANDROID_CPU_ARM_FEATURE_VFPv3
, если поддерживаются аппаратные плавающие точки, и ANDROID_CPU_ARM_FEATURE_NEON
, если поддерживаются расширенные инструкции SIMD. У ARM не может быть NEON без VFPv3.
В итоге: по умолчанию ваши программы наиболее совместимы. Использование LOCAL_ARM_MODE может немного ускорить процесс за счет времени автономной работы из-за использования инструкций ARM - и оно так же совместимо, как и настройки по умолчанию. Добавив строку APP_ABI := armeabi armeabi-v7a
, вы улучшите производительность на новых устройствах, оставаясь совместимыми со старыми, но ваш файл .apk будет больше (из-за наличия 2 библиотек). Чтобы использовать инструкции NEON, вам нужно написать специальный код, который определяет возможности ЦП во время выполнения, и это относится только к более новым устройствам, которые могут запускать armeabi-v7a.