NEON サポート

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

すべての ARMv7 ベースの Android 端末が NEON をサポートしているわけではありませんが、サポート端末は、NEON のスカラー / ベクトル命令のサポートによって大きなメリットを得ることができます。

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

LOCAL_ARM_NEON の使用

NDK で NEON サポートがあることを前提にすべてのソースファイルをビルドするには、モジュール定義に次の行を含めます。

LOCAL_ARM_NEON := true

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

.neon 接尾辞の使用

LOCAL_SRC_FILES 変数にソースファイルを指定するときに、.neon 接尾辞を使用することで、NEON を利用して個々のファイルをビルドすることを指定できます。

たとえば、次の場合は、1 つのファイル(foo.c)は NEON を利用してビルドし、別のファイル(bar.c)は利用しないでビルドします。

LOCAL_SRC_FILES := foo.c.neon bar.c

この .neon 接尾辞は、非 NEON 命令向けの(Thumb2 ではなく)32 ビット ARM 命令セットを表す .arm 接尾辞と組み合わせることができます。 このような場合、.arm.neon の前に配置する必要があります。 たとえば、foo.c.arm.neon は動作しますが、foo.c.neon.arm は動作しません。

ビルド要件

NEON はarmeabi-v7aarm64-v8a ABI で動作します。 NDK ビルド スクリプトが NEON を利用してビルドを試みたときに、他の ABI が検出された場合、NDS ビルド スクリプトは終了します。 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)intrinsic 関数の x86 SSE コードへのクロスプラットフォーム コンパイルをサポートしています。 このトピックに関する詳細については、ARM NEON から Intel SSE - 自動移植ソリューション、ヒントとコツをご覧ください。

サンプルコード

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