CPU 機能の使用

ABI: プリプロセッサの定義済みマクロの使用

通常、#ifdef を以下とともに使用し、ビルド時に ABI を決定すると最も便利です。

  • __arm__(32 ビット ARM の場合)
  • __aarch64__(64 ビット ARM の場合)
  • __i386__(32 ビット X86 の場合)
  • __x86_64__(64 ビット X86 の場合)

32 ビット X86 は想定される __x86__ ではなく __i386__ と呼ばれることに注意してください。

CPU コア数: libc の sysconf(3) の使用

sysconf(3) では、_SC_NPROCESSORS_CONF(システム内の CPU コアの数)と _SC_NPROCESSORS_ONLN(現在オンラインになっている CPU コアの数)の両方をクエリできます。

機能: libc の getauxval(3) の使用

API レベル 18 以降、getauxval(3) は Android の C ライブラリで使用できます。 AT_HWCAP 引数と AT_HWCAP2 引数は CPU 固有の機能を示すビットマスクを返します。 NDK のさまざまな hwcap.h ヘッダーで、arm64 の SHA512 命令の HWCAP_SHA512 や、arm の Thumb 整数除算命令の HWCAP_IDIVT など、比較対象となる定数を確認してください。

Google cpu_features ライブラリ

AT_HWCAP の問題の 1 つとして、端末が誤って解釈されることがあります。 たとえば、一部の古い端末では、整数除算命令があると示されますが、実際にはありません。

Google の cpu_features ライブラリでは、特定の SoC に関する独自のナレッジを(/proc/cpuinfo を解析し、問題となる SoC を判別して)適用し、このような問題を回避します。

別の回避策には、SIGILL のシグナル ハンドラをインストールし、問題の命令を単に試行するというものもあります。 たとえば、BoringSSL / OpenSSL ではこのテクニックを使用します。

NDK cpufeatures ライブラリ

NDK には、getauxval(3) と同様の機能を備えた cpufeatures という小さなライブラリが含まれていますが、これは 18 より前の API レベルでも動作します。 他の cpu_features ライブラリとは異なり、これには特定の SoC に関する追加のナレッジはありません。

NDK cpufeatures API

uint64_t android_getCpuFeatures();

ビットフラグのセットを返します。各フラグは 1 つの CPU ファミリー固有の機能を表します。 このセクションの残りでは、各ファミリーの機能について説明します。

32 ビット ARM CPU ファミリー

32 ビット ARM CPU ファミリーでは、次のフラグを使用できます。

ANDROID_CPU_ARM_FEATURE_VFPv2
端末の CPU で、VFPv2 命令セットがサポートされることを示します。 ほとんどの ARMv6 CPU はこの命令セットをサポートしています。
ANDROID_CPU_ARM_FEATURE_ARMv7
端末の CPU で、armeabi-v7a ABI の場合と同じように、ARMv7-A 命令セットがサポートされることを示します。 この命令セットは、Thumb-2 命令と VFPv3-D16 命令の両方をサポートします。 この戻り値は、VFPv3 ハードウェア FPU 命令セットの拡張機能がサポートされることも示します。
ANDROID_CPU_ARM_FEATURE_VFPv3
端末の CPU で、VFPv3 ハードウェア FPU 命令セットの拡張機能がサポートされることを示します。

この値は VFPv3-D16 命令セットと同等であり、16 ビット ハードウェア倍精度 FP レジスタのみを提供します。

ANDROID_CPU_ARM_FEATURE_VFP_D32
端末の CPU で、16 ビットレジスタではなく、32 ビット ハードウェア倍精度 FP レジスタがサポートされることを示します。 32 ビット ハードウェア倍精度 FP レジスタがあっても、32 ビット単精度レジスタのみが同じレジスタバンクにマッピングされます。
ANDROID_CPU_ARM_FEATURE_NEON
端末の CPU で、ARM Advanced SIMD(NEON)ベクター命令セットの拡張機能がサポートされることを示します。 ARM では、このような CPU で VFPv3-D32 も実装することが必須であることに注意してください。VFPv3-D32 は 32 ビット ハードウェア FP レジスタ(NEON ユニットと共有される)を提供します。
ANDROID_CPU_ARM_FEATURE_VFP_FP16
端末の CPU で、16 ビットレジスタで浮動小数点演算を実行するための命令がサポートされることを示します。 この機能は VFPv4 仕様の一部です。
ANDROID_CPU_ARM_FEATURE_VFP_FMA
端末の CPU で、VFP 命令セットの融合積和演算拡張機能がサポートされることを示します。 この機能は VFPv4 仕様の一部です。
ANDROID_CPU_ARM_FEATURE_NEON_FMA
端末の CPU で、NEON 命令セットの融合積和演算拡張機能がサポートされることを示します。 この機能は VFPv4 仕様の一部です。
ANDROID_CPU_ARM_FEATURE_IDIV_ARM
端末の CPU で、ARM モードの整数除算がサポートされることを示します。 Cortex-A15 などの新型 CPU でのみ使用できます。
ANDROID_CPU_ARM_FEATURE_IDIV_THUMB2
端末の CPU で、Thumb-2 モードの整数除算がサポートされることを示します。 Cortex-A15 などの新型 CPU でのみ使用できます。
ANDROID_CPU_ARM_FEATURE_iWMMXt
端末の CPU で、MMX レジスタおよび命令を追加する命令セットの拡張機能がサポートされることを示します。 この機能は、少数の XScale ベースの CPU でのみ使用できます。
ANDROID_CPU_ARM_FEATURE_LDREX_STREX
端末の CPU で、ARMv6 以降で使用できる LDREX および STREX 命令がサポートされることを示します。これらの命令により、排他的モニタを活用してメモリ上のアトミック アップデートが実行されます。

64 ビット ARM CPU ファミリー

64 ビット ARM CPU ファミリーでは、次のフラグを使用できます。

ANDROID_CPU_ARM64_FEATURE_FP
端末の CPU に、浮動小数点演算ユニット(FPU)があることを示します。 すべての Android ARM64 端末はこの機能をサポートする必要があります。
ANDROID_CPU_ARM64_FEATURE_ASIMD
端末の CPU に、Advanced SIMD(ASIMD)ユニットがあることを示します。 Android ARM64 端末にはこの機能が必要です。
ANDROID_CPU_ARM64_FEATURE_AES
端末の CPU で、AES 命令がサポートされることを示します。
ANDROID_CPU_ARM64_FEATURE_CRC32
端末の CPU で、CRC32 命令がサポートされることを示します。
ANDROID_CPU_ARM64_FEATURE_SHA1
端末の CPU で、SHA1 命令がサポートされることを示します。
ANDROID_CPU_ARM64_FEATURE_SHA2
端末の CPU で、SHA2 命令がサポートされることを示します。
ANDROID_CPU_ARM64_FEATURE_PMULL
端末の CPU で、64 ビット PMULL および PMULL2 命令がサポートされることを示します。

32 ビット x86 CPU ファミリー

32 ビット x86 CPU ファミリーでは、次のフラグを使用できます。

ANDROID_CPU_X86_FEATURE_SSSE3
端末の CPU で、SSSE3 命令の拡張機能セットがサポートされることを示します。
ANDROID_CPU_X86_FEATURE_POPCNT
端末の CPU で、POPCNT 命令がサポートされることを示します。
ANDROID_CPU_X86_FEATURE_MOVBE
端末の CPU で、MOVBE 命令がサポートされることを示します。 この命令は、Atom などの一部の Intel IA-32 CPU に固有のものです。

android_getCpuFeatures() は、拡張機能がリストされていない CPU ファミリーに対して 0 を返します。

int android_getCpuCount(void);

システム内の CPU コアの数を返しますが、これは実際にオンラインであるコアの数より多い場合があります。

AndroidCpuFamily android_getCpuFamily();

端末がサポートする CPU ファミリー / アーキテクチャを表す次のいずれかの定数を返します。

  • ANDROID_CPU_FAMILY_ARM
  • ANDROID_CPU_FAMILY_X86
  • ANDROID_CPU_FAMILY_ARM64
  • ANDROID_CPU_FAMILY_X86_64

64 ビットシステムの 32 ビット実行ファイルの場合、この関数は 32 ビット アーキテクチャを返します。

ndk-build での NDK cpufeatures の使用

cpufeatures ライブラリはインポート モジュールとして使用できます。 使用手順は次のとおりです。

  • cpufeaturesLOCAL_STATIC_LIBRARIES に追加します。

  • ソースコードに #include <cpu-features.h> を追加します。

  • android/cpufeaturesAndroid.mk の末尾にインポートします。

cpufeatures をインポートする Android.mk の例を次に示します。

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE := your-module-name
LOCAL_SRC_FILES := ...
LOCAL_STATIC_LIBRARIES := cpufeatures
include $(BUILD_SHARED_LIBRARY)

$(call import-module,android/cpufeatures)