2012-06-27 17 views
10

iOSOpenCVを使用して、コンピューティングを強化したアプリを完成しました。もちろんそれは遅かったです。しかし、それは私のPCプロトタイプよりも200倍遅いものでした。だから私はそれを最適化していた。非常に最初の15秒から、私は0.4秒のスピードを得ることができました。私はすべてのものと他の人が分かち合うことができるものを見つけたのだろうかと思います。私が何をしたか:IOS/iPad/iPhoneからの最大速度

  1. 置き換え "double" データ型は、OpenCVの内側に "float"。ダブルは64ビットで32ビットCPUは簡単に処理できないので、フロートはいくらかスピードを出しました。 OpenCVは非常に頻繁に二重を使用します。

  2. "-mpfu=neon"をコンパイラオプションに追加しました。副作用は、エミュレータコンパイラがもう動作せず、ネイティブハードウェアのみで何かをテストできるという新しい問題でした。

  3. cos()の実装を90値ルックアップテーブルで置き換えました。スピードアップは巨大でした!これは、そのような最適化がスピードアップをもたらさないPCとは幾分反対である。コードは度で作業していましたが、この値はsin()cos()のラジアンに変換されました。このコードも削除されました。しかし、ルックアップテーブルは仕事をしました。

  4. 有効"thumb optimizations"。いくつかのブログ記事は正反対のものを推奨していますが、これは、親指が普通遅くなるからです。armv6です。 armv7には問題がなく、速くて小さくなります。

  5. 親指の最適化と-mfpu=neonがうまく機能し、クラッシュを引き起こさないように、私はarmv6ターゲットを完全に削除しました。私のコードはすべてarmv7にコンパイルされており、これもアプリケーションストアの要件として記載されています。つまり、iPhone3GSとなります。私は古いものを落とすことはOKだと思います。とにかく古いものはCPUが遅く、CPU使用量の多いアプリケーションは古いデバイスにインストールされていると悪いユーザエクスペリエンスを提供します。もちろん

  6. 私はOpenCVのから"dead code"を削除-O3 flag

  7. を使用しています。 OpenCVを最適化すると、私のプロジェクトには必要ないコードが明らかです。たとえば、ピクセルサイズが8ビットか32ビットかをチェックするために余分にある"if()"があります。私は8ビットしか必要ないことを知っています。これによりコードが削除され、オプティマイザは何かを削除したり、定数で置き換えたりすることができます。また、コードはキャッシュに適しています。

その他のトリックとアイデアはありますか?私の親指を有効にし、三角法をルックアップに置き換えることはメーカーを増強し、私を驚かせました。アプリを動かすためにもっとや​​るべきことが分かっているのでしょうか?

答えて

13

多くの浮動小数点計算を行っている場合は、AppleのAccelerateフレームワークを使用すると大きなメリットがあります。浮動小数点ハードウェアを使用してベクトルの計算を並列に行うように設計されています。

Iはまた、1つずつあなたの点に対処します:

1)これはのARMv7時代のように、32ビット浮動小数点演算は、浮動で算出されるので、それがある、なぜならCPUではありません(Appleがハードウェアを交換したため)。 64ビットのものはソフトウェアで計算されます。それと引き換えに、32ビット操作はずっと高速になりました。

2)NEONはい、これは周知の方法である)

3設定された新たな浮動小数点プロセッサ命令の名前です。代わりに、私が上記のアップルのフレームワークを使用することです。これは、4つの値を並列に計算するsin関数とcos関数を提供します。アルゴリズムはアセンブリとNEONで微調整されているため、バッテリを最小限に抑えながら最大のパフォーマンスを発揮します。

4)新しいarmv7の実装では、armv6の欠点はありません。無効化の推奨事項はv6のみに適用されます。

5)はい、ユーザーの80%がiOS 5.0以降(armv6デバイスは4.2.1でサポートを終了しました)を考慮すると、これはほとんどの状況では問題ありません。

6)これは、リリースモードでビルドすると自動的に発生します。

7)はい、これは上記の方法ほどの効果はありません。

私はAccelerateをチェックすることをお勧めします。そうすれば、浮動小数点プロセッサの能力を最大限に引き出すことができます。

+0

このアクセラレーションは私にとって初めてのものでした。アセンブリレベルの思考が必要なので、まだ使いにくいです。しかし、それでも可能で、おそらく試してみるつもりです。私はここでより有用なヒントを得るかどうかを知りたいので、後で受け入れているとマークします。 –

+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"); 

は今、私は「製品 - >出力を生成 - >アセンブリファイル」を押し、私が取得することである:

@ 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 

は、オプティマイザは、アイデアを持って、コードがはるかに短くなりました。これをベクトル化することができました。ポイントは、コンパイラは、ウェブカメラのカメラサイズやピクセルの深さのようなものであれば、どの入力が定数であるのかを常に知っていませんが、実際には私の状況では常に一定であり、気にするのはスピードです。

私はまたして3行を置き換えることを示唆して加速しようとした:

__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よりも高速である場合。私の文脈では、この部分は時間がかかりませんし、2つの亜種が同じスピードで動作するようです。

もう一つ学んだことは、GPUを使用していることです。詳細はこちらhttp://www.sunsetlakesoftware.com/2012/02/12/introducing-gpuimage-framework

関連する問題