programing

여러 아키텍처에 최적화 된 NDK 코드를 생성하고 계십니까?

copysource 2021. 1. 17. 11:48
반응형

여러 아키텍처에 최적화 된 NDK 코드를 생성하고 계십니까?


저수준 숫자 처리를 많이하는 Android 용 C 코드가 있습니다. 생성 된 코드가 현재의 모든 Android 기기에서 실행될뿐만 아니라 특정 칩셋에 대한 최적화를 활용할 수 있도록 어떤 설정 (예 : Android.mk 및 Application.mk) 파일을 사용해야하는지 알고 싶습니다. 사용할 좋은 기본 Android.mk 및 Application.mk 설정을 찾고 있는데 #ifdef 브랜치로 내 C 코드를 흩 뜨리는 것을 피하고 싶습니다.

예를 들어 ARMv7에는 부동 소수점 명령어가 있고 일부 ARMv7 칩은 NEON 명령어를 지원하며 기본 ARM은 이들 중 어느 것도 지원하지 않는다는 것을 알고 있습니다. NEON이있는 ARMv7, NEON이없는 ARMv7 및 기본 ARM 빌드를 빌드 할 수 있도록 플래그를 설정할 수 있습니까? 후자의 두 가지를 수행하는 방법을 알고 있지만 모두는 아닙니다. 3. 현재 기본값이 가장 안전한 설정이라고 가정하고 다른 옵션에 어떤 위험이 있는지에 따라 어떤 설정을 사용하는지 신중하게 생각합니다.

GCC 특정 최적화를 위해 다음 플래그를 사용하고 있습니다.

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

이 세 가지를 모두 확인하여 코드 속도를 높였습니다. 추가 할 수있는 다른 공통 항목이 있습니까?

내가 가진 또 다른 팁은 Android.mk에 "LOCAL_ARM_MODE : = arm"을 추가하여 최신 arm 칩에서 속도를 높이는 것입니다 (정확히 이것이 수행되는 작업과 이전 칩에서 발생하는 작업에 대해 혼란 스럽지만).


ARM 프로세서에는 "ARM"및 "Thumb"이라는 두 가지 일반 명령어 세트가 있습니다. 둘 다 다른 종류가 있지만 ARM 명령어는 각각 32 비트이고 Thumb 명령어는 16 비트입니다. 이 둘의 주요 차이점은 ARM 명령어는 Thumb보다 단일 명령어에서 더 많은 작업을 수행 할 수 있다는 것입니다. 예를 들어 단일 ARM 명령어는 두 번째 레지스터에서 왼쪽 시프트를 수행하는 동안 하나의 레지스터를 다른 레지스터에 추가 할 수 있습니다. Thumb에서는 하나의 명령어가 시프트를 수행해야하고 두 번째 명령어가 더하기를 수행해야합니다.

ARM 명령어는 두 배나 좋지는 않지만 어떤 경우에는 더 빠를 수 있습니다. 이는 특히 "무료 시프트"를 최대한 활용하기 위해 새로운 방식으로 조정할 수있는 수동식 ARM 어셈블리에 해당됩니다. Thumb 명령어는 크기뿐 아니라 고유 한 장점도 있습니다. 배터리 소모가 적습니다.

어쨌든 이것은 LOCAL_ARM_MODE가하는 일입니다. 즉, 코드를 Thumb 명령어 대신 ARM 명령어로 컴파일한다는 의미입니다. Thumb으로 컴파일하는 것은 더 작은 바이너리를 생성하는 경향이 있고 대부분의 코드에서 속도 차이가 눈에 띄지 않기 때문에 NDK의 기본값입니다. 컴파일러는 ARM이 제공 할 수있는 추가 "oomph"를 항상 활용할 수는 없으므로 어쨌든 동일한 수의 명령어가 필요합니다.

ARM 또는 Thumb으로 컴파일 된 C / C ++ 코드에서 보는 결과는 동일합니다 ( 컴파일러 버그 제외 ).

이것은 그 자체로 현재 사용 가능한 모든 Android 휴대폰의 새 ARM 프로세서와 이전 ARM 프로세서간에 호환됩니다. 이는 기본적으로 NDK가 ARMv5TE 명령어 세트를 지원하는 ARM 기반 CPU 용 "애플리케이션 바이너리 인터페이스"로 컴파일되기 때문입니다. 이 ABI는 "armeabi"로 알려져 있으며을 넣어 Application.mk에서 명시 적으로 설정할 수 있습니다 APP_ABI := armeabi.

최신 프로세서는 또한 armeabi-v7aarmeabi를 확장하여 Thumb-2 명령어 세트 와 VFPv3-D16이라는 하드웨어 부동 소수점 명령어 세트 를 추가하는 이라는 Android 전용 ABI를 지원합니다 . armeabi-v7a 호환 CPU는 또한 선택적으로 NEON 명령어 세트를 지원할 수 있습니다.이 명령어 세트는 런타임에 확인하고 사용 가능할 때와 그렇지 않은 경우에 대한 코드 경로를 제공해야합니다. NDK / samples 디렉토리에이를 수행하는 예제가 있습니다 (hello-neon). 내부적으로 Thumb-2는 명령어가 단일 명령어에서 더 많은 작업을 수행 할 수있는 반면 여전히 적은 공간을 차지한다는 장점이 있다는 점에서 "ARM과 유사"합니다.

armeabi 및 armeabi-v7a 라이브러리를 모두 포함하는 "fat 바이너리"를 컴파일하려면 Application.mk에 다음을 추가합니다.

APP_ABI := armeabi armeabi-v7a

.apk 파일이 설치되면 Android 패키지 관리자가 기기에 가장 적합한 라이브러리를 설치합니다. 따라서 이전 플랫폼에서는 armeabi 라이브러리를 설치하고 최신 장치에서는 armeabi-v7a 라이브러리를 설치합니다.

런타임에 CPU 기능을 테스트하려는 경우 NDK 기능 uint64_t android_getCpuFeatures()사용 하여 프로세서에서 지원하는 기능 을 얻을 수 있습니다 . 하드웨어 부동 소수점이 지원되고 고급 SIMD 명령어가 지원되는 경우 ANDROID_CPU_ARM_FEATURE_ARMv7v7a 프로세서 의 비트 플래그를 반환합니다 . ARM은 VFPv3없이 NEON을 가질 수 없습니다.ANDROID_CPU_ARM_FEATURE_VFPv3ANDROID_CPU_ARM_FEATURE_NEON

요약하면 기본적으로 프로그램이 가장 호환됩니다. LOCAL_ARM_MODE를 사용하면 ARM 명령어를 사용하기 때문에 배터리 수명이 줄어드는 대신 작업 속도가 약간 빨라질 수 있으며 기본 설정만큼 호환됩니다. APP_ABI := armeabi armeabi-v7a줄을 추가하면 최신 장치에서 성능이 향상되고 이전 장치와의 호환성을 유지하지만 .apk 파일이 더 커집니다 (라이브러리가 2 개 있기 때문에). NEON 명령어를 사용하려면 런타임에 CPU의 기능을 감지하는 특수 코드를 작성해야하며 이는 armeabi-v7a를 실행할 수있는 최신 장치에만 적용됩니다.


좋은 대답, 당신이 사용해야하는 것을 추가하는 것처럼

APP_ABI := all

이것은 4 개의 바이너리, armv5, armv7, x86 및 mips를 컴파일합니다.

새 버전의 ndk가 필요할 수 있습니다.

참조 URL : https://stackoverflow.com/questions/5089783/producing-optimised-ndk-code-for-multiple-architectures

반응형