Ответ 1
Процессоры ARM имеют 2 общих набора инструкций, которые они поддерживают: "ARM" и "Thumb". Хотя есть разные варианты обоих, инструкции ARM имеют 32 бита, а команды Thumb - 16 бит. Основное различие между ними состоит в том, что инструкции ARM имеют возможность делать больше в одной инструкции, чем Thumb. Например, одна команда ARM может добавить один регистр в другой регистр, выполняя сдвиг влево по второму регистру. В Thumb одна инструкция должна была бы сделать сдвиг, тогда вторая инструкция сделает дополнение.
Инструкции ARM не так хороши, но в некоторых случаях они могут быть быстрее. Это особенно актуально для ручной сборки ARM, которая может быть настроена по новым способам наилучшего использования "сдвигов бесплатно". У Thumb-инструкций есть свои преимущества, а также размер: они меньше разряжают батарею.
В любом случае, это то, что LOCAL_ARM_MODE делает - это означает, что вы компилируете свой код как инструкции ARM вместо инструкций Thumb. Компиляция в Thumb является значением по умолчанию в NDK, поскольку она имеет тенденцию создавать меньший двоичный файл, а разница в скорости не является заметной для большинства кодов. Компилятор не всегда может воспользоваться дополнительным "oomph", который может предоставить ARM, поэтому вам в конечном итоге требуется более или менее одинаковое количество инструкций.
Результат того, что вы видите из кода C/С++, скомпилированного в ARM или Thumb, будет идентичным (запрет ошибок компилятора).
Это само по себе совместимо между новыми и старыми ARM-процессорами для всех телефонов Android, доступных сегодня. Это связано с тем, что по умолчанию NDK компилируется в "Application Binary Interface" для процессоров на базе 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.