Compatibilidad con NEON

El NDK admite la extensión SIMD avanzado de ARM, más conocida como NEON, una extensión opcional del conjunto de instrucciones para ARMv7 y ARMv8. NEON proporciona instrucciones y registros escalares y vectoriales (que se comparten con las unidades de puntos flotantes) similares a MMX/SSE/3DNow! en el entorno x86. Para funcionar, requiere registros VFPv3-D32 (32 registros de FPU asistidas por hardware de 64 bits, en lugar de la cantidad mínima de 16).

No todos los dispositivos Android basados en ARMv7 admiten NEON, pero aquellos que lo hacen pueden beneficiarse notablemente de su compatibilidad con instrucciones escalares y vectoriales.

El NDK admite la compilación de módulos o incluso archivos de origen específicos que admiten NEON.

Uso de LOCAL_ARM_NEON

Para que NDK compile todos los archivos de origen (asumiendo que admite NEON), deberás incluir la siguiente línea en la definición de tu módulo: makefile LOCAL_ARM_NEON := true

Puede resultarte muy útil compilar todos los archivos de origen de manera que admitan NEON si quieres compilar una biblioteca compartida o estática que contenga específicamente solo código NEON.

Uso del sufijo .neon

Al enumerar los archivos de origen para tu variable LOCAL_SRC_FILES, puedes usar el sufijo .neon para indicar que quieres compilar archivos individuales que admitan NEON. Por ejemplo, a continuación, se compila un archivo (foo.c) que admite NEON y otro (bar.c) que no: makefile LOCAL_SRC_FILES := foo.c.neon bar.c

Puedes combinar el sufijo .neon con el sufijo .arm, que especifica el conjunto de instrucciones ARM de 32 bits (en lugar de Thumb2) para instrucciones que no son NEON. En ese caso, .arm debe incluirse antes de .neon. Por ejemplo: foo.c.arm.neon funciona, pero foo.c.neon.arm no.

Requisitos de la compilación

La compatibilidad con NEON funciona con las ABI armeabi-v7a y arm64-v8a. Si las secuencias de comandos de compilación del NDK encuentran otras ABI mientras intentan realizar compilaciones compatibles con NEON, entonces quedan excluidas. Es importante que incluyas comprobaciones en tu archivo Android.mk como las que se muestran a continuación:

# define a static library containing our NEON code
    ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
    include $(CLEAR_VARS)
    LOCAL_MODULE    := mylib-neon
    LOCAL_SRC_FILES := mylib-neon.c
    LOCAL_ARM_NEON  := true
    include $(BUILD_STATIC_LIBRARY)
    endif # TARGET_ARCH_ABI == armeabi-v7a
    

Detección del tiempo de ejecución

Tu app debe realizar una detección del tiempo de ejecución para confirmar que se pueda ejecutar código máquina compatible con NEON en el dispositivo de destino. Esta acción es necesaria porque no todos los dispositivos Android basados en ARMv7 admiten NEON. La app puede realizar esta comprobación por medio de la biblioteca cpufeatures que se incluye en el NDK.

Debes comprobar que android_getCpuFamily() devuelva ANDROID_CPU_FAMILY_ARM y que android_getCpuFeatures() devuelva un valor con el indicador ANDROID_CPU_ARM_FEATURE_NEON establecido. por ejemplo:

    #include <cpu-features.h>
    ...
    ...
    if (android_getCpuFamily() == ANDROID_CPU_FAMILY_ARM &&
        (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) != 0)
    {
        // use NEON-optimized routines
        ...
    }
    else
    {
        // use non-NEON fallback routines instead
        ...
    }

    ...
    

Compatibilidad entre plataformas para x86

El NDK admite la compilación entre plataformas de tus funciones intrínsecas existentes de ARM SIMD (NEON) en código x86 de SSE, mediante el uso de NEON_2_SSE.h de terceros. Para obtener más información sobre este tema, consulta De ARM NEON a Intel SSE: Soluciones, consejos y sugerencias de portabilidad automática.

Código de ejemplo

La muestra hello-neon proporciona un ejemplo de cómo usar la biblioteca cpufeatures y los elementos intrínsecos de NEON al mismo tiempo. En esta muestra, se implementa una pequeña referencia para un bucle de filtros FIR con una versión C y una versión optimizada para NEON para dispositivos compatibles con NEON.