NEON サポート

NDK は、一般に NEON と呼ばれる ARM Advanced SIMD をサポートしています。NEON は、ARMv7 および ARMv8 向けのオプションの命令セット拡張です。NEON は、x86 環境の MMX / SSE / 3DNow! と同等のスカラー / ベクター命令とレジスタ(FPU と共有)を提供します。

API レベル 21 以降を搭載したすべてのデバイスを含め、ARMv7 ベースのほぼすべての Android デバイスが NEON をサポートしています。NDK はデフォルトで NEON を有効にしています。

ARMv8 ベースの Android デバイスはすべて NEON をサポートしています。

NDK は、NEON を利用することで、モジュールや特定のソースファイルをコンパイルすることができます。C および C++ コードで NEON イントリンシックを使用して、Advanced SIMD 拡張機能を利用できます。NEON イントリンシックと NEON プログラミングの全般について詳しくは、Armv8-A 向け NEON プログラマー ガイドをご覧ください。

構築

NEON をグローバルに有効にする

ndk-build

ndk-build では、NEON をグローバルに有効にすることはできません。ndk-build アプリ全体で NEON を有効にするには、アプリ内のすべてのモジュールにモジュールごとの手順を適用します。

CMake

CMake を呼び出すときに -DANDROID_ARM_NEON=ON を渡します。Android Studio / Gradle でビルドする場合は、build.gradle で以下のオプションを設定します。

android {
    defaultConfig {
        externalNativeBuild {
            cmake {
                arguments "-DANDROID_ARM_NEON=ON"
            }
        }
    }
}

モジュールごとに NEON を有効にする

ndk-build

NEON を使用して ndk-build モジュール内のすべてのソースファイルをビルドするには、Android.mk のモジュール定義に以下の行を追加します。

LOCAL_ARM_NEON := true

CMake

NEON を使用して CMake ターゲット内のすべてのソースファイルをビルドするには、CMakeLists.txt に以下の行を追加します。

if(ANDROID_ABI STREQUAL armeabi-v7a)
    set_target_properties(${TARGET} PROPERTIES COMPILE_FLAGS -mfpu=neon)
endif()

ここで ${TARGET} はライブラリの名前に置き換えます。

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

ソースファイルごとに NEON を有効にする

ndk-build

LOCAL_SRC_FILES 変数のためにソースファイルをリストする際、.neon サフィックスを使用して、NEON サポートを利用して個別のファイルをビルドする意図を示すことを選択できます。たとえば、以下の場合、1 つのファイル(foo.c)は NEON サポートを利用してビルドし、もう 1 つのファイル(bar.c)は NEON サポートを利用せずにビルドします。

LOCAL_SRC_FILES := foo.c.neon bar.c

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

CMake

特定のソースファイルを NEON でビルドするには、CMakeLists.txt に以下の行を追加します。

if(ANDROID_ABI STREQUAL armeabi-v7a)
    set_source_files_properties(foo.cpp PROPERTIES COMPILE_FLAGS -mfpu=neon)
endif()

ランタイム検出

API レベル 21 以降を搭載したすべてのデバイスを含め、ARMv7 ベースのほぼすべての Android デバイスが NEON をサポートしています。NDK はデフォルトで NEON を有効にしています。最大限の互換性を確保するため、32 ビットコードはランタイム検出を実行して、対象デバイスで NEON コードを実行できることを確認できます。このチェックの実行には、CPU 機能で紹介されているどの方法でも使用できます。

あるいは、Google Play Console で互換性のないデバイスを除外することもできます。コンソールを使用して、影響を受けるデバイスの数を確認することもできます。

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

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

サンプルコード

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