NEON サポート

NDK は、一般に「NEON」と呼ばれる ARM Advanced SIMD をサポートしています。これは、必須ではない ARMv7 と ARMv8 の命令セット拡張機能です。NEON は、x86 環境の MMX / SSE / 3DNow! と同等のスカラー / ベクター命令とレジスタ(FPU と共有)を提供します。NEON が正しく動作するには、VFPv3-D32(最小限の 16 個ではなく、32 個のハードウェア FPU 64 ビットレジスタ)が必要です。

必ずしもすべての ARMv7 ベース Android デバイスが NEON をサポートしているわけではありませんが、サポートしているデバイスであれば、NEON のスカラー / ベクター命令のサポートによって大きなメリットを得ることができます。

NDK は、NEON を利用することで、モジュールや特定のソースファイルをコンパイルすることができます。

LOCAL_ARM_NEON を使用する

NEON サポートに基づいて NDK ですべてのソースファイルをビルドするには、モジュール定義に次の行を追加します。 makefile LOCAL_ARM_NEON := true

特に、NEON 専用コードを含む静的ライブラリや共有ライブラリをビルドする場合、NEON サポートを利用してすべてのソースファイルをビルドすると便利です。

.neon サフィックスを使用する

LOCAL_SRC_FILES 変数に対してソースファイルのリストを指定する際、.neon サフィックスを使用することで、NEON サポートを利用して各ファイルをビルドするよう指定できます。たとえば、次の場合、1 つのファイル(foo.c)は NEON サポートを利用してビルドし、もう 1 つのファイル(bar.c)は NEON サポートを利用せずにビルドします。 makefile LOCAL_SRC_FILES := foo.c.neon bar.c

.neon サフィックスは、.arm サフィックスと組み合わせることができます。後者のサフィックスは、非 NEON 命令向けに Thumb2 ではなく 32 ビット ARM 命令セットを指定します。組み合わせる場合、.arm.neon の前に配置する必要があります。たとえば、foo.c.arm.neon は動作しますが、foo.c.neon.arm は動作しません。

ビルド要件

NEON サポートは、armeabi-v7a ABI と arm64-v8a ABI で機能します。NDK ビルド スクリプトが NEON サポートを利用してビルドしようとしたときに、他の ABI が検出された場合、NDK ビルド スクリプトは終了します。Android.mk ファイル内で次のようなチェックを使用してください。

# 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
    

ランタイム検出

アプリは、ターゲット デバイス上で NEON 対応マシンコードを実行できるか確認するため、ランタイム検出を実行する必要があります。NEON をサポートしていない ARMv7 ベース Android デバイスもあるため、この確認が必要です。アプリは、NDK に付属の cpufeatures ライブラリを利用して、このチェックを実行できます。

android_getCpuFamily()ANDROID_CPU_FAMILY_ARM を返し、android_getCpuFeatures() が、ANDROID_CPU_ARM_FEATURE_NEON フラグがセットされた値を返すかチェックします。たとえば、次のようになります。

    #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
        ...
    }

    ...
    

x86 向けのクロスプラットフォーム サポート

NDK は、サードパーティの NEON_2_SSE.h を使用することで、既存の ARM SIMD(NEON)イントリンシック関数を x86 SSE コードにコンパイルするクロスプラットフォーム コンパイルをサポートしています。詳細については、ARM NEON から Intel SSE へ - 自動移植ソリューション、ヒントとコツをご覧ください。

サンプルコード

hello-neon sample は、cpufeatures ライブラリと NEON イントリンシクスを同時に使用する方法を示すサンプルです。このサンプルは、FIR フィルタループの小規模なベンチマークを、C バージョンと、NEON 対応デバイス向けの NEON 最適化バージョンで実装した例です。