複数のアーキテクチャ向けに最適化された NDK コードを作成しますか? 質問する

複数のアーキテクチャ向けに最適化された NDK コードを作成しますか? 質問する

Android 用の C コードがあり、低レベルの数値計算を大量に行っています。生成されたコードが現在のすべての Android デバイスで実行され、特定のチップセットの最適化も利用できるように、(たとえば Android.mk ファイルや Application.mk ファイルなどの) どのような設定を使用すればよいかを知りたいです。適切なデフォルトの Android.mk および Application.mk 設定を探しており、C コードに #ifdef ブランチが散らかるのを避けたいと思っています。

たとえば、ARMv7 には浮動小数点命令があり、一部の ARMv7 チップは NEON 命令をサポートしており、デフォルトの ARM はどちらもサポートしていないことは承知しています。NEON 付き ARMv7、NEON なし ARMv7、およびデフォルトの ARM ビルドをビルドできるようにフラグを設定することは可能ですか? 後者の 2 つは実行方法を知っていますが、3 つすべては知りません。現在のデフォルト設定が最も安全な設定であり、他のオプションにはどのようなリスクがあるかを想定しているため、使用する設定には慎重です。

GCC 固有の最適化のために、次のフラグを使用しています。

LOCAL_CFLAGS=-ffast-math -O3 -funroll-loops

これら 3 つすべてをチェックして、コードの速度を向上しました。他に追加できる一般的なものはありますか?

もう 1 つのヒントは、Android.mk に「LOCAL_ARM_MODE := arm」を追加して、新しい ARM チップでの速度向上を有効にすることです (ただし、これが正確に何を実行し、古いチップで何が起こるのかはわかりません)。

ベストアンサー1

ARM プロセッサには、サポートされる一般的な命令セットが 2 つあります。「ARM」と「Thumb」です。どちらも種類は異なりますが、ARM 命令はそれぞれ 32 ビットで、Thumb 命令は 16 ビットです。この 2 つの主な違いは、ARM 命令では 1 つの命令で Thumb よりも多くの処理を実行できることです。たとえば、1 つの ARM 命令で、2 番目のレジスタを左シフトしながら、1 つのレジスタを別のレジスタに加算できます。Thumb では、1 つの命令でシフトを実行し、2 番目の命令で加算を実行する必要があります。

ARM 命令は 2 倍優れているわけではありませんが、特定のケースではより高速になることがあります。これは特に、手作業で行われる ARM アセンブリに当てはまります。このアセンブリでは、斬新な方法で調整して、「無料のシフト」を最大限に活用できます。Thumb 命令には、サイズだけでなく、バ​​ッテリーの消耗が少ないという独自の利点があります。

とにかく、これが LOCAL_ARM_MODE の機能です。つまり、コードを Thumb 命令ではなく ARM 命令としてコンパイルするということです。Thumb へのコンパイルは NDK のデフォルトです。これは、Thumb の方がバイナリが小さくなる傾向があり、ほとんどのコードでは速度の違いがそれほど目立たないからです。コンパイラは ARM が提供する追加の「パワー」を常に利用できるとは限らないので、結局は多かれ少なかれ同じ数の命令が必要になります。

ARMまたはThumbにコンパイルされたC/C++コードから得られる結果は同一です(ただし、コンパイラのバグ)。

これだけで、現在入手可能なすべての Android スマートフォンの新旧 ARM プロセッサ間で互換性があります。これは、NDK がデフォルトで ARMv5TE 命令セットをサポートする ARM ベースの CPU の「アプリケーション バイナリ インターフェース」にコンパイルされるためです。この ABI は「armeabi」と呼ばれ、 を記述することで Application.mk に明示的に設定できますAPP_ABI := armeabi

新しいプロセッサは、と呼ばれるAndroid固有のABIもサポートしておりarmeabi-v7a、これはarmeabiを拡張して、Thumb-2命令セットそして、VFPv3-D16 と呼ばれるハードウェア浮動小数点命令セットもあります。armeabi-v7a 互換 CPU は、オプションで NEON 命令セットをサポートすることもできます。これは実行時に確認し、使用できる場合と使用できない場合のコード パスを提供する必要があります。NDK/samples ディレクトリに、これを実行する例があります (hello-neon)。内部的には、Thumb-2 は、1 つの命令でより多くの処理を実行できるという点で「ARM に似ています」が、それでも占有スペースが少ないという利点があります。

armeabi ライブラリと armeabi-v7a ライブラリの両方を含む「ファット バイナリ」をコンパイルするには、Application.mk に次のコードを追加します。

APP_ABI := armeabi armeabi-v7a

.apk ファイルがインストールされると、Android パッケージ マネージャーはデバイスに最適なライブラリをインストールします。したがって、古いプラットフォームでは armeabi ライブラリがインストールされ、新しいデバイスでは armeabi-v7a ライブラリがインストールされます。

実行時に CPU 機能をテストする場合は、NDK 関数を使用してプロセッサでサポートされている機能を取得できます。これは、ハードウェア浮動小数点がサポートされている場合、および高度な SIMD 命令がサポートされている場合に、v7a プロセッサuint64_t android_getCpuFeatures()のビット フラグを返します。ARM は、VFPv3 なしでは NEON を使用できません。ANDROID_CPU_ARM_FEATURE_ARMv7ANDROID_CPU_ARM_FEATURE_VFPv3ANDROID_CPU_ARM_FEATURE_NEON

要約: デフォルトでは、プログラムの互換性が最も高くなります。LOCAL_ARM_MODE を使用すると、ARM 命令の使用によりバッテリー寿命が短くなりますが、デフォルトのセットアップと同等の互換性があり、わずかに高速化される可能性があります。このAPP_ABI := armeabi armeabi-v7a行を追加すると、新しいデバイスでのパフォーマンスが向上し、古いデバイスとの互換性が維持されますが、.apk ファイルのサイズは大きくなります (ライブラリが 2 つあるため)。NEON 命令を使用するには、実行時に CPU の機能を検出する特別なコードを記述する必要があります。これは、armeabi-v7a を実行できる新しいデバイスにのみ適用されます。

おすすめ記事