Android NDKで作業を説明するタスクを自分で設定するわけではありません-エクスペリエンス自体では十分ではありません。 興味のある方はこのリンクから始めてください。
この短い記事の目的は、Javaで記述されてからC ++で書き直された特定の関数の実行時間を比較することにより、経験的に得たいくつかの図を提供することです。 そして、おそらく、これらの数字は誰かがこの問題をより深く研究するように動機付けます。
私のアプリケーションは写真処理に関連しているため、ボトルネックは画像のピクセルとそれらに対する特定のアクションをバイパスするサイクルでした。 実際のデバイス-Nexus OneおよびNexus 7(2012)でテストしました。 実験結果(ミリ秒)を表にまとめます:
レイヤーオーバーレイ(発光モード、カラー描画)
ネクサスワン | Nexus 7 | ||
---|---|---|---|
SDK | Ndk | SDK | Ndk |
2563 | 120 | 4850 | 90 |
2122 | 100 | 4520 | 190 |
2162 | 110 | 4330 | 100 |
Nexus 7の場合、Nexus Oneの平均速度は21倍、36倍です。
レイヤーオーバーレイ(カラー覆い焼きモード、モノクロ)
ネクサスワン | Nexus 7 | ||
---|---|---|---|
SDK | Ndk | SDK | Ndk |
2673 | 30 | 5720 | 80 |
2572 | 20 | 6230 | 70 |
2573 | 20 | 6110 | 70 |
Nexus Oneの速度向上は平均で112倍、Nexus 7の場合は82倍です。
透明度のグラデーションをオーバーレイ
ネクサスワン | Nexus 7 | ||
---|---|---|---|
SDK | Ndk | SDK | Ndk |
1301 | 321 | 3010 | 470 |
1221 | 330 | 2670 | 620 |
1211 | 300 | 2770 | 610 |
Nexus Oneの速度向上は平均で4倍、Nexus 7の場合は5倍です。
ご覧のとおり、結果は1桁または2桁も異なります。 NDKの使用による作業の実際の加速を確認できるように、数値を絶対値で具体的に引用しました。 最後のテストの比較的控えめな結果は、非常に最適化されたOpenCVライブラリの標準関数がオーバーレイの計算に使用されたためです。 したがって、このテストは、アプリケーション全体の実際の加速を明確に示しています。
OpenCVライブラリのアプリケーションに触れます。 予想どおり、ライブラリのJava部分はNDKの通常のラッパーです。 それでも、彼は上記の実験をかなり重くて長時間のアルゴリズムで実行しました-画像の特徴点を見つける、グラブカット-などの方法。 JavaとNDKの速度の違いは最大10%でしたが、これはエラーが原因である可能性があります。その時点ではまったく同じ画像を取得できなかったためです。
更新する 自分の間違いを認めるのはやや不快ですが、どうすればいいのでしょう。
そこで、OpenCVライブラリのJava実装のパフォーマンスを評価したサンプルコードを次に示します。
for (int i=0; i<mat.rows(); i++){ for (int j=0; j<mat.cols(); j++) { double[] matPix = mat.get(i, j); double[] topPix = top.get(i, j); if (matPix[0]+topPix[0]>255){ matPix[0] = 255.; } else { matPix[0] = (255. * matPix[0]) / (256. - topPix[0]); } mat.put(i, j, matPix); } }
同じサイズの2つのマトリックスをピクセルごとに渡し、一方と他方のマトリックスの対応するピクセルの値に応じて、結果のピクセルを計算します。
記事へのコメント内のコメントのおかげで、コードは次のように最適化されました(図は単色です)。
int size = mat.cols(); byte[] matPix = new byte[size]; byte[] topPix = new byte[size]; for (int i=0; i<mat.rows(); i++){ mat.get(i, 0, matPix); top.get(i, 0, topPix); for (int j=0; j<size; j++) { int mp = (matPix[j] & 0xFF); int tp = (topPix[j] & 0xFF); if (mp+tp>255){ mp = 255; } else { mp = (255 * mp) / (256 - tp); } matPix[j] = (byte) mp; } mat.put(i, 0, matPix); }
テストでは、実際のNexus OneおよびNexus 7デバイスを再び使用しましたが、どちらの場合も3メガピクセルの写真を入力に送りました。デバイスのパフォーマンスを一緒に比較したかったのです。 結果(平均、ミリ秒)は、表にまとめられています。
ネクサスワン | Nexus 7 | |||
---|---|---|---|---|
SDK | Ndk | SDK | Ndk | |
最適化なし | 35404 | 245 | 22755 | 160 |
最適化あり | 340 | 205 | 210 | 120 |
誰もが自分で結論を出すことができます。 C ++のコード最適化は、Javaと同じ原理で実行されました。 コードは提供していませんが、上記と同じです。