NEON サポート

NDK は、ARMv7 仕様の任意の命令セット拡張機能である ARM Advanced SIMD をサポートしています。NEON は、x86 環境の MMX、SSE、3DNow! と同等の、一連のスカラー / ベクトル命令とレジスタ(FPU と共有)を提供します。 NEON が正しく動作するには、VFPv3-D32(最低 16 本ではなく、32 本のハードウェア FPU 64 ビット レジスタ)が必要です。

NDK は NEON を有効にしてモジュールや特定のソースファイルをコンパイルできます。これにより、特定のコンパイラー フラグにより、GCC ARM NEON Intrinsics と VFPv3-D32 を同時に利用できるようになります。

すべての ARMv7 ベースの Android 端末が NEON をサポートしているわけではありませんが、サポート端末は、 NEON のスカラー / ベクトル命令によって大きなメリットを得ることができます。 x86 端末の場合、複数の制約はありますが、NDK で NEON 命令を SSE に変換することもできます。 詳細については、ARM NEON Intrinsics の x86 サポートをご覧ください。

LOCAL_ARM_NEON の使用

NDK で NEON を有効にしてすべてのソースファイルをビルドするには、モジュール定義に次の行を含めます。

LOCAL_ARM_NEON := true

特に、NEON コードパスを含む静的ライブラリや共有ライブラリをビルドしたい場合には、NEON を有効にしてすべてのソースファイルをビルドすると便利です。

.neon 拡張子の使用

LOCAL_SRC_FILES 変数にソースファイルを指定するときに、末尾に .neon を付けると、NEON を有効にしてバイナリをビルドできることを表せます。たとえば、次の例では .neon サポートありのファイルと、サポートなしのファイルをビルドしています。

LOCAL_SRC_FILES := foo.c.neon bar.c

この .neon 拡張子は、非 NEON 命令向けの 32 ビット ARM 命令セットを表す .arm 拡張子と組み合わせることができます。 この定義では、armneon よりも前にくる必要があります。 たとえば、foo.c.arm.neon は動作しますが、foo.c.neon.arm は動作しません。

ビルド要件

NEON は armeabi-v7a ABI と x86 ABI に対してのみサポートされています。NEON を有効にしてビルドをしようとした際に他の ABI が検出されると、NDK ビルド スクリプトは終了し、x86 は変換ヘッダーを介して部分的な NEON サポートを提供します。 Android.mk ファイルで次のようなチェックをすることが重要です。

# define a static library containing our NEON code
ifeq ($(TARGET_ARCH_ABI),$(filter $(TARGET_ARCH_ABI), armeabi-v7a x86))
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 || x86

ランタイム検出

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

android_getCpuFamily()ANDROID_CPU_FAMILY_ARM を返し、android_getCpuFeatures()ANDROID_CPU_ARM_FEATURE_NEON flag セットを含む値を返すことを明示的にチェックする必要があります。 次に例を示します。

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

...

サンプルコード

NDK の hello-neon サンプルのソースコードを見ると、cpufeatures ライブラリと NEON intrinsics を同時に使用する方法を確認できます。 このサンプルは、FIR フィルタ ループの小規模なベンチマークを C バージョンと、NEON 対応端末向けに NEON で最適化されたバージョンで実装した例です。