1

NEON アセンブリ コードを含むいくつかのファイルを含む Android 用のネイティブ ライブラリがあります。私はこのコードを他のコーダーから継承しましたが、控えめに言っても、NEON アセンブリ コーディング (またはその他のアセンブリ) に関する私の知識は不十分です。とにかく、次の問題に気付きました:「ndk-build NDK_DEBUG=1」でコンパイルすると、すべて問題ありません。リリース用に 'ndk-build NDK_DEBUG=0' をコンパイルすると、コンパイラはアセンブリ コードを最適化します。ndk ビルド スクリプトをハッキングし、ライブラリを 2 つに分割することで問題を回避することができました。1 つのライブラリにはすべてのアセンブリ ファイルが含まれています。このライブラリでは、非常にハックな方法で最適化を「-O0」に設定しました。 . 問題は、特定のファイルの最適化レベルを指定するにはどうすればよいかということです。APP_OPTIM の設定は Application.mk で行います。コンパイルされたすべてのファイルに影響します。NDK_DEBUG フラグも同様です。

編集: アレックスの要求に従って、これが私が最終的に使用した Android.mk であり、lib を 2 つに分割します: 1 つの部分はアセンブリ コード (および -O0) を含み、もう 1 つの部分は通常の C コード (および -O2) を含みます:

LOCAL_PATH := $(call my-dir)

# assembly_neon_code_here (neon) module - turn optimization off
include $(CLEAR_VARS)

LOCAL_MODULE := assembly_neon_code_here
LOCAL_SRC_FILES := assembly_neon_code_here.cpp
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
    LOCAL_ARM_NEON := true
endif

LOCAL_CFLAGS := -O0
LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog 
include $(BUILD_SHARED_LIBRARY)

# main module
include $(CLEAR_VARS)

LOCAL_MODULE    := complete_lib
LOCAL_SRC_FILES := regular_src1.cpp regular_src2.cpp regular_src3.cpp 
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
    LOCAL_ARM_NEON := true
endif

# allow logcat calls
LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog -lz
LOCAL_SHARED_LIBRARIES := assembly_neon_code_here
include $(BUILD_SHARED_LIBRARY)
4

2 に答える 2

3

GCC >= 4.4#pragma GCC optimizeでは、ファイルの途中で最適化レベルを変更したり、optimize関数ごとに設定する属性をサポートしているようです。

http://gcc.gnu.org/onlinedocs/gcc-4.4.7/gcc/Function-Specific-Option-Pragmas.html#Function-Specific-Option-Pragmasおよびhttp://gcc.gnu.org/onlinedocsを参照してください。 /gcc-4.4.7/gcc/Function-Attributes.html#Function-Attributes .

これらのリンクによると#pragma GCC optimize ("O0")、問題の原因となっているファイルの先頭に置くとうまくいくはずです。

于 2012-10-02T17:27:38.603 に答える
1

ファイルごとに最適化レベルを変更する方法はわかりませんが、変更するとアプリケーションのパフォーマンスが低下する可能性があるため、お勧めしません。アセンブリ コードはインライン アセンブリ ブロックの形式であると仮定します。つまり、アセンブリ コーダーのブロックが通常の C または C++ コードとインターリーブされます。それは次のように見えます

asm {
  .. assembly goes here, usually each line in double-quotes, often ending in \n\t
  : ... input operands. Might not be present ...
  : ... output operands. Might not be present ...
  : ... clobber operands. Might not be present ...
}

コンパイラがインライン アセンブリ ブロックを削除する最も可能性の高い理由は、出力オペランドが含まれていないか、出力オペランドがすべて未使用である場合です。volatileコンパイラに混乱しないように指示するインライン アセンブリ ブロックをマークすることで、try を回避できます。そのためには、キーワードvolatileの後に​​書くだけです。asm

コンパイラがインラインアセンブリブロックをいじるのを思いとどまらせるもう1つのことは、「メモリ」をクロバーリストに追加することです。これにより、アセンブリが任意のメモリ位置から読み取りまたは書き込みを行っていることがコンパイラに通知されます。そして、あなたがそれに取り組んでいる間、適切な測定のために「cc」も追加してください. これは、インライン アセンブリが条件コード レジスタに干渉していること、つまり、後の条件付き分岐命令の動作に影響を与えるテスト命令を実行することをコンパイラに通知します。

結論として、すべてのインラインアセンブリブロックを次のようにしてみてください

asm volatile {
  .. whatever ...
  : ... whatever ...
  : ... whatever ...
  : ... whatever ..., "cc", "memory"
}

that も綴られる可能性があり、 thatもasm綴られる可能性があることに注意してください。__asm__volatile__volatile__

于 2012-09-30T21:53:53.847 に答える