¿Produce código NDK optimizado para múltiples arquitecturas?

Tengo un código C para Android que hace un montón de crujidos de bajo nivel. Me gustaría saber qué configuración debo usar (por ejemplo, para mis archivos Android.mk y Application.mk) para que el código producido se ejecute en todos los dispositivos Android actuales, pero también aprovecha las optimizaciones para chipsets específicos. Estoy buscando una buena configuración predeterminada de Android.mk y Application.mk para usar y quiero evitar tener que desperdiciar mi código C con las ramas #ifdef.

Por ejemplo, soy consciente de que ARMv7 tiene instrucciones de punto flotante y algunos chips ARMv7 admiten instrucciones NEON y que el ARM por defecto no soporta ninguno de estos. ¿Es posible establecer banderas para que pueda construir ARMv7 con NEON, ARMv7 sin NEON y la compilación ARM predeterminada? Soy saber cómo hacer los dos últimos pero no todos 3. Soy cauteloso sobre qué ajustes utilizo pues asumo que los defaults actuales son los ajustes más seguros y qué riesgos otras opciones tienen.

Para la optimización específica de GCC, utilizo los siguientes indicadores:

LOCAL_CFLAGS=-ffast-math -O3 -funroll-loops 

He comprobado los 3 de estos acelerar mi código. ¿Hay otros comunes que podría agregar?

Otro consejo que tengo es añadir "LOCAL_ARM_MODE: = brazo" a Android.mk para permitir una aceleración en los chips de brazo más nuevos (aunque estoy confundido en exactamente lo que hace esto y lo que sucede en los chips más antiguos).

Los procesadores ARM tienen 2 conjuntos de instrucciones generales que admiten: "ARM" y "Thumb". Aunque hay diferentes sabores de ambos, las instrucciones ARM son 32 bits cada una y las instrucciones Thumb son 16 bits. La principal diferencia entre los dos es que las instrucciones ARM tienen la posibilidad de hacer más en una sola instrucción de lo que Thumb puede. Por ejemplo, una sola instrucción ARM puede añadir un registro a otro registro, mientras realiza un cambio a la izquierda en el segundo registro. En Pulgar una instrucción tendría que hacer el cambio, entonces una segunda instrucción haría la adición.

Las instrucciones ARM no son dos veces más buenas, pero en ciertos casos pueden ser más rápidas. Esto es especialmente cierto en el montaje ARM rodado a mano, que se puede ajustar de manera novedosa para hacer el mejor uso de "turnos de forma gratuita". Pulgar instrucciones tienen su propia ventaja, así como el tamaño: que drenan la batería menos.

De todos modos, esto es lo que LOCAL_ARM_MODE hace – significa que compila su código como instrucciones ARM en lugar de instrucciones Thumb. Compilación a pulgar es el valor predeterminado en el NDK, ya que tiende a crear un binario más pequeño y la diferencia de velocidad no es tan notable para la mayoría de código. El compilador no siempre puede aprovechar el extra "oomph" que ARM puede proporcionar, por lo que terminan necesitando más o menos el mismo número de instrucciones de todos modos.

El resultado de lo que ves desde código C / C ++ compilado en ARM o Thumb será idéntico (salvo errores de compilador ).

Esto por sí mismo es compatible entre los nuevos y antiguos procesadores ARM para todos los teléfonos Android disponibles en la actualidad. Esto se debe a que por defecto el NDK compila a una "Interfaz binaria de la aplicación" para las CPU basadas en ARM que soportan el conjunto de instrucciones ARMv5TE. Este ABI se conoce como "armeabi" y se puede establecer explícitamente en el Application.mk poniendo APP_ABI := armeabi .

Los procesadores más recientes también soportan el ABI específico de Android conocido como armeabi-v7a , que extiende armeabi para agregar el conjunto de instrucciones Thumb-2 y un conjunto de instrucciones de punto flotante de hardware llamado VFPv3-D16. Las CPUs compatibles con armeabi-v7a también pueden soportar opcionalmente el conjunto de instrucciones NEON, que hay que comprobar durante el tiempo de ejecución y proporcionar rutas de código cuando está disponible y cuando no. Hay un ejemplo en el directorio NDK / samples que hace esto (hello-neon). Bajo el capó, Thumb-2 es más "ARM-like" en que sus instrucciones pueden hacer más en una sola instrucción, mientras que tener la ventaja de ocupar todavía menos espacio.

Con el fin de compilar un "binario de grasa" que contiene las bibliotecas armeabi y armeabi-v7a, agregaría lo siguiente a Application.mk:

 APP_ABI := armeabi armeabi-v7a 

Cuando el archivo .apk está instalado, el administrador de paquetes de Android instala la mejor biblioteca para el dispositivo. Así que en las plataformas más antiguas se instalaría la biblioteca armeabi, y en los dispositivos más nuevos el armeabi-v7a uno.

Si desea probar las características de la CPU en tiempo de ejecución, puede utilizar la función NDK uint64_t android_getCpuFeatures() para obtener las funciones compatibles con el procesador. Esto devuelve un indicador de ANDROID_CPU_ARM_FEATURE_ARMv7 de ANDROID_CPU_ARM_FEATURE_ARMv7 en los procesadores v7a, ANDROID_CPU_ARM_FEATURE_VFPv3 si se soportan puntos flotantes de hardware y ANDROID_CPU_ARM_FEATURE_NEON si se admiten instrucciones avanzadas de SIMD. ARM no puede tener NEON sin VFPv3.

En resumen: por defecto, sus programas son los más compatibles. El uso de LOCAL_ARM_MODE puede hacer las cosas un poco más rápido a expensas de la duración de la batería debido al uso de instrucciones ARM – y es tan compatible como la configuración predeterminada. Al agregar la línea APP_ABI := armeabi armeabi-v7a , habrá mejorado el rendimiento de los dispositivos más nuevos, seguirá siendo compatible con los anteriores, pero su archivo .apk será mayor (debido a tener 2 bibliotecas). Para utilizar las instrucciones NEON, necesitará escribir un código especial que detecte las capacidades de la CPU en tiempo de ejecución, y esto sólo se aplica a los dispositivos más nuevos que pueden ejecutar armeabi-v7a.

Gran respuesta, al igual que añadir que debe utilizar

 APP_ABI := all 

Esto compilará 4 binarios, armv5, armv7, x86 y mips

Puede que necesite una nueva versión de ndk

  • Android: Uso de JNI desde NativeActivity
  • ¿Qué es el método Descriptor / signature para byte byte array usando JNI?
  • Ptrace devuelve -1 en Android
  • Filtrado de MatOfDMatch
  • ¿Puedo usar excepciones de C ++ en la biblioteca JNI en Android?
  • Recorte de video de Android a través de ffmpeg
  • No se puede asignar suficiente memoria en JNI
  • Java JNI vs. Android NDK
  • Firma de android apk con gradle-experimental: 0.2.0
  • Error durante la compilación de la muestra de jni de android: inválido -march = opción: `armv5te '
  • ¿Qué dispositivos Android admiten jni?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.