2012-06-27 2 views
10

iOS의 경우 OpenCV을 사용하여 컴퓨팅 집약적 인 앱을 완료했습니다. 물론 그것은 느렸다. 하지만 그것은 내 PC 프로토 타입보다 200 배 더 느린 것과 같았다. 그래서 나는 그것을 최적화하고 있었다. 매우 처음 15 초에서 나는 0.4 초의 속도를 얻을 수 있었다. 나는 모든 것을 발견하고 다른 사람들이 나누고 싶어하는 것이 있을지 궁금합니다. 내가 무슨 짓을 :IOS/iPad/iPhone의 최대 속도

  1. 대체 "double"데이터 유형은 OpenCV의 내부에 "float". 더블은 64 비트이고 32 비트 CPU는 쉽게 처리 할 수 ​​없기 때문에 플로트는 나에게 약간의 속도를 주었다. OpenCV는 자주 double을 사용합니다.

  2. "-mpfu=neon"을 컴파일러 옵션에 추가했습니다. 부작용은 에뮬레이터 컴파일러가 더 이상 작동하지 않고 모든 것이 네이티브 하드웨어에서만 테스트 될 수 있다는 새로운 문제였습니다.

  3. cos()을 90 개의 값 찾아보기 테이블로 대체했습니다. 속도 향상은 엄청났습니다! 이러한 최적화가 어떤 속도 향상도주지 않는 PC와는 다소 반대입니다. 각도로 작업하는 코드가 있었고이 값은 sin() 및 에 대한 라디안으로 변환되었습니다. 이 코드도 삭제되었습니다. 그러나 조회 테이블은 일을했다.

  4. 사용 설정 "thumb optimizations". 일부 블로그 게시물은 정확히 반대를 권장하지만 엄지 손가락은 일반적으로 armv6에서 느리게 진행되기 때문입니다. armv7은 문제가 없으며 빠르고 작게 만듭니다.

  5. 엄지 손가락 최적화와 -mfpu=neon이 잘 작동하고 충돌이 발생하지 않도록하기 위해 armv6 타겟을 완전히 제거했습니다. 내 코드는 모두 armv7으로 컴파일되며 앱 스토어의 요구 사항으로도 나와 있습니다. 즉, 최소 iPhone3GS이됩니다. 나이 든 것을 버리는 것이 좋습니다. 어쨌든 이전 버전은 느린 CPU를 사용하고 CPU 집약적 인 앱은 오래된 장치에 설치하면 나쁜 사용자 환경을 제공합니다. 물론

  6. 은 내가 OpenCV의에서 "dead code"을 삭제

  7. -O3 flag을 사용합니다. OpenCV를 최적화 할 때 종종 프로젝트에 필요하지 않은 코드가 있음을 알았습니다. 예를 들어 종종 여분의 픽셀 크기가 8 비트인지 32 비트인지를 확인하기 위해 "if()"이 있으며, 8 비트 만 필요하다는 것을 알고 있습니다. 이렇게하면 일부 코드가 제거되고 최적화 프로그램이 더 많은 것을 제거하거나 상수로 대체 할 수있는 기회를 제공합니다. 또한 코드는 캐시에 더 잘 들어 맞습니다.

다른 트릭과 아이디어가 있습니까? 엄지 손가락을 사용하고 삼각법을 조회로 대체하는 나를 위해 나를지지하는 사람이 나를 놀라게했습니다. 어쩌면 더 많은 것을 할 수있는 응용 프로그램을 만들 수 있을지 알고 있습니까?

답변

13

많은 부동 소수점 계산을 수행하는 경우 Apple의 Accelerate 프레임 워크를 사용하면 큰 도움이됩니다. 부동 소수점 하드웨어를 사용하여 벡터에 대한 계산을 병렬로 수행하도록 설계되었습니다.

나는 또한 당신의 포인트를 하나 하나 해결됩니다

1)이없는 때문에 CPU이며, 그것은 때문에 부동 소수점 연산 32 비트 부동에서 계산됩니다는 ARMv7-시대로입니다 포인트 프로세서 하드웨어 (사과가 하드웨어를 대체했기 때문에). 64 비트 값은 소프트웨어 대신 계산됩니다. 교환으로 32 비트 연산이 훨씬 빨라졌습니다.

2) 네온 예,이 공지의 방법)

3 세트 새로운 부동 소수점 프로세서 명령의 이름이다. 대안은 위에서 언급 한 Apple 프레임 워크를 사용하는 것입니다. 이 함수는 4 개의 값을 병렬로 계산하는 sin 및 cos 함수를 제공합니다. 알고리즘은 어셈블리 및 NEON에서 미세 조정되어 최소한의 배터리를 사용하면서 최대 성능을 제공합니다.

4) 새로운 armv7 구현의 thumb에는 armv6의 단점이 없습니다. 비활성화 권장 사항은 v6에만 적용됩니다.

5) 그렇습니다. 사용자의 80 %가 iOS 5.0 이상을 사용하고있는 것으로 간주합니다 (armv6 장치는 4.2.1에서 지원 종료 됨). 이는 대부분의 경우 완벽하게 수용됩니다.

6) 이는 릴리스 모드에서 빌드 할 때 자동으로 발생합니다.

7) 예, 위의 방법과 큰 효과가 없습니다.

내 추천은 Accelerate를 확인하는 것입니다. 그렇게하면 부동 소수점 프로세서의 모든 기능을 활용할 수 있습니다.

+0

이 Accelerate는 나에게 처음 접했습니다. 어셈블리 수준의 사고가 필요하기 때문에 사용하기가 다소 어렵습니다. 그러나 여전히 가능하고 어쩌면 시도 할 것입니다. 나는 우리가 여기에서 더 유용한 힌트를 얻는 지보고 싶기 때문에 나중에 받아 들여야한다. –

+1

WWDC 2012 비디오에는 Accelerate 프레임 워크를 전적으로 다루는 세션이 있습니다. 너는 그것을 봐야한다 ^^ – borrrden

+0

http://adcdownload.apple.com//wwdc_2012/wwdc_2012_session_pdfs/session_708__the_accelerate_framework.pdf 과 https://developer.apple.com/videos/wwdc/2012/#708이 보인다. 그것에 대한 링크가 될 –

1

이전 게시물에 대한 피드백을 제공합니다. 이것은 제가 7 번 코드에서 죽은 코드를 제공하려고 시도한 아이디어를 설명합니다. 이것은 약간 더 넓은 아이디어를 의미합니다. 형식화가 필요하므로 주석 형식을 사용할 수 없습니다. 이러한 코드는 OpenCV에 있습니다.

for(kk = 0; kk < (int)(descriptors->elem_size/sizeof(vec[0])); kk++) { 
    vec[kk] = 0; 
} 

어셈블리에서 어떻게 보이는지보고 싶었습니다.

이제
__asm__("#start"); 
for(kk = 0; kk < (int)(descriptors->elem_size/sizeof(vec[0])); kk++) { 
    vec[kk] = 0; 
} 
__asm__("#stop"); 

I를 누르면 "-> 출력을 생성 - 제품> 어셈블리 파일을"하고 내가 얻을 것은 : 내가 어셈블리에서 찾을 수 있는지 확인하기 위해, 나는 이런 식으로 포장

@ InlineAsm Start 
    #start 
    @ InlineAsm End 
Ltmp1915: 
    ldr r0, [sp, #84] 
    movs r1, #0 
    ldr r0, [r0, #16] 
    ldr r0, [r0, #28] 
    cmp r0, #4 
    mov r0, r4 
    blo LBB14_71 
LBB14_70: 
Ltmp1916: 
    ldr r3, [sp, #84] 
    movs r2, #0 
Ltmp1917: 
    str r2, [r0], #4 
    adds r1, #1 
Ltmp1918: 
Ltmp1919: 
    ldr r2, [r3, #16] 
    ldr r2, [r2, #28] 
    lsrs r2, r2, #2 
    cmp r2, r1 
    bgt LBB14_70 
LBB14_71: 
Ltmp1920: 
    add.w r0, r4, #8 
    @ InlineAsm Start 
    #stop 
    @ InlineAsm End 

많은 코드. 나는 (int)(descriptors->elem_size/sizeof(vec[0]))의 값을 printf와-D와 항상 64 그래서 나는 64 수를 하드 코딩이었고, 어셈블러를 통해 다시 통과 : 당신은 지금 볼 수 있듯이

@ InlineAsm Start 
    #start 
    @ InlineAsm End 
Ltmp1915: 
    vldr.32 s16, LCPI14_7 
    mov r0, r4 
    movs r1, #0 
    mov.w r2, #256 
    blx _memset 
    @ InlineAsm Start 
    #stop 
    @ InlineAsm End 

는 옵티마이 저는 생각이있어 코드가 훨씬 짧은되었다. 이것을 벡터화 할 수있었습니다. 요점은 컴파일러가 웹캠 카메라 크기 나 픽셀 깊이와 같은 것이면 어떤 입력 값이 상수인지 항상 알지 못한다는 것입니다. 실제로는 내 컨텍스트에서 일반적으로 일정하며 걱정되는 것은 속도입니다.

__asm__("#start"); 
vDSP_vclr(vec,1,64); 
__asm__("#stop"); 

조립 지금 보이는 : 세 라인을 교체 제안

또한 가속화 시도

@ InlineAsm Start 
    #start 
    @ InlineAsm End 
Ltmp1917: 
    str r1, [r7, #-140] 
Ltmp1459: 
Ltmp1918: 
    movs r1, #1 
    movs r2, #64 
    blx _vDSP_vclr 
Ltmp1460: 
Ltmp1919: 
    add.w r0, r4, #8 
    @ InlineAsm Start 
    #stop 
    @ InlineAsm End 

확실이 비록 bzero보다 빠른 경우. 제 맥락에서이 부분은 시간이 많이 걸리지 않으며 두 가지 변종이 같은 속도로 작동하는 것처럼 보입니다.

내가 배운 것은 GPU를 사용하는 것입니다. 여기에 대한 자세한 내용 http://www.sunsetlakesoftware.com/2012/02/12/introducing-gpuimage-framework