Android* 向けの信頼できるツールによる最適化手法 – インテル® SSE 組込み関数とインテル® Cilk™ Plus

同カテゴリーの次の記事

Android* のシステムレベルの Java*/C++ コードのデバッグ

この記事は、インテル® デベロッパー・ゾーンに掲載されている「Trusted Tools in the New Android* World: Optimization Techniques – from Intel® SSE Intrinsics to Intel® Cilk™ Plus」(http://software.intel.com/en-us/android/articles/trusted-tools-in-the-new-android-world-optimization-techniques-from-intel-sse-intrinsics-to) の日本語参考訳です。


はじめに

ほとんどの Android* アプリケーションは、スクリプト言語やマネージド言語 (Java*、HTML5 など) ベースであっても、ミドルウェア機能を使用しています。ミドルウェア機能は、最適化による恩恵を受けられます。

この記事では Android* で必要な最適化とそのアプローチを紹介し、ケーススタディーを例にマルチメディア拡張現実アプリケーションを最適化する方法を示します。

インテルでは、Android* プラットフォーム (スマートフォンとタブレット) 向けに、インテル® ストリーミング SIMD 拡張命令 3 補足命令 (インテル® SSSE3) 以上のベクトル化機能を備え、(通常) ハイパースレッディングが有効な 2 つのコアを搭載したインテル® Atom™ プロセッサーを提供しています。

この記事を参考に、ぜひこれらの最適化機能をお試しください。

iOnRoad* ケーススタディー

iOnRoad* は、コンピューター・ビジョン・アルゴリズムによる衝突警告などの機能をスマートフォン上で提供し、リアルタイムで運転を補助する拡張現実アプリケーションです。

リアルタイムで動作するため、スマートフォンのカメラで生成される YUV420/NV21 形式の各入力フレームを、処理する前に RGB 形式に変換する必要があります。

オリジナルの変換コードは CPU 実行時間の約 40% を占め、これによりイメージ処理が制限されるため、最適化が不可欠でした。

唯一利用可能な最適化ソフトウェアは、インテル® インテグレーテッド・パフォーマンス・プリミティブ (インテル® IPP) の YUV420ToRGB ルーチンでしたが、iOnRoad アプリケーションに必要な入力形式と出力形式の組み合わせに対応していませんでした。また、このルーチンはマルチスレッド化されていませんでした。

そのため、変換コードを新たに作成することになりました。

YUV420/NV21 から RGB への変換

YUV420/NV21 形式には、8 ビットの輝度 (白黒) Y と 2 つのクロミナンス (色) 成分 U と V があります。

1 ピクセルが 3 つの色成分で構成される標準の RGB 形式を生成するには、4 つの Y 成分ごとに、1 つの V 成分と U 成分のペアが必要です。

上の図は、適切な 4 つの Y 成分とそれに対応する V 成分と U 成分のペアを同じ色で示しています。

この形式 (一般に YUV と呼ばれる) は、RGB と比べると圧縮率が 2 倍になります。

YUV から RGB への変換 – 整数ルックアップ・テーブルを用いるアプローチ

YUV から RGB への変換には、単純な線形式を使用します。

float への型変換を回避するため、ここでは一般的な次の整数近似式を使用します。

これらの式の中間結果は >216 になります。詳しくは、ベクトル化の説明で述べます。

iOnRoad は、スカラー計算でルックアップ・テーブル (LUT) アプローチを採用していました。Y、U、V は 8 ビットなので、上記の式の乗算は 32 ビットの 256 エントリーから成る 5 つの LUT としてあらかじめ計算することができます。

YUV から RGB への変換 – インテル® SSE を使用する固定小数点アプローチ

インテル® SSE には、ベクトル化に対応した LUT (ギャザー) 命令がありません。通常、16 ビットのパックド乗算のほうが、スカラー LUT 操作とパック操作の組み合わせよりも高速です。

しかし、中間結果が >216 のため、インテル® SSE の 16 ビット乗算 (PMULLW) は使用できません。

インテル® SSSE3 の _mm_mulhrs_epi16() 命令は、16 ビット乗算を行い 32 ビットの結果を右へシフトするため、最終的に丸められた 16 ビットの結果が得られます。

最終結果で有効なビット数を最大にするには、オリジナルの乗算オペランドを左へシフトします (この例では 13 ビットの最終結果が得られます。)

YUV から RGB への変換 – インテル® SSE を使用する固定小数点アプローチの実装

最初に、16×8 ビットの Y を 2 セットと、8×8 ビットの (U、V) ペアをロードします。

最終的に、このデータは (FRGB 形式で、最上位バイトが 0xff の) 16×32 ビットの RGB ピクセルに変換されます。

8 ビットの飽和処理される減算により 16×8 ビットの Y から 16 が引かれるため、結果が負数でないかどうかの確認と補正を行わなくて済みます。

8 つの (U、V) ペアは、2 セットの Y (各セットは 16 個) に対応します。

入力データのアンパックにはバイトシャッフル操作が使用され、次の組み合わせが 2 つ生成されます。

  • 8×16 ビットの Y が 2 セット
  • 4×16-ビットに拡張された U が 1 セット
  • 4×16-ビットに拡張された V が 1 セット

以下は、このスキームの詳しい図解です。

U と V を使用する前に、16 ビットのパックド _mm_sub_epi16() 命令により 128 が引かれます。

その後、8×16 ビットの Y、U、V のパックドデータが、_mm_mulhrs_epi16() 命令に最適に収まるように左にシフトされます。この命令は、適切にパックされた係数とともに使用されます。

注: 上記の前処理 (減算とシフト) は、スカラー・アルゴリズムの LUT 操作の代わりに実行されます。

乗算結果は合計され、_mm_min_epi16() と _mm_max_epi16() により最終結果は 16 ビットのパックド値 ( 0 ~ 213-1 (8191) の範囲) になります。

すべての計算が完了すると、結果は 13/16-ビットのパックド R、G、B 値で表されます。

これらの値から FRGB 形式への再パック (iOnRoad アプリケーションの要求に応じて、F はすべて 1 のアルファチャネル) は 2 つのフェーズで行われます。

第 1 フェーズでは、16 ビットの <0xff00> 値が格納されたレジスターを使って、13/16 ビットの R、G、B 値を 16 ビットのペア FR と GB に再パックします。

以下の図に示すように、このフェーズでは論理左シフト、論理右シフト、論理 OR/AND 操作を行います。

第 2 フェーズでは、_mm_unpacklo_epi16() 命令と _mm_unpackhi_epi16() 命令により中間結果 FR と GB を FRGB にパックします。

インテル® SSE 組込み関数を使用して YUV から RGB へ変換するコードは、オリジナルのスカラー LUT コードと比べて 4 倍も高速になりました。

インテル® Cilk™ Plus による並列化

スマートフォンやタブレットで使用されているほとんどのインテル® Atom™ プロセッサーには、少なくとも 2 つの論理コアがあります (デュアルコアやハイパースレッディング対応モデルもあります)。コア数は今後確実に増えるため、アルゴリズムの並列化が重要になります。

最も簡単な並列化アプローチは、インテル® コンパイラーに含まれる C/C++ コード向けのインテル® Cilk™ Plus を使用することです (インテル® スレッディング・ビルディング・ブロック (インテル® TBB) は C++ でのみ利用できます)。

インテル® Cilk™ Plus のシンプルな並列化キーワード “cilk_for” ( YUV から RGB へ変換する外側のループで C/C++ の “for” の代わりに使用) により、デュアルコア インテル® Atom™ プロセッサー Z2760 (開発コード名 Clover Trail) ベースのデバイスでは、パフォーマンスがさらに 2 倍向上しました。

インテル® Cilk™ Plus による並列化とインテル® SSE 組込み関数によるベクトル化を併用することで、全体のパフォーマンスは 8 倍向上しました。

性能に関するテストに使用されるソフトウェアとワークロードは、性能がインテル® マイクロプロセッサー用に最適化されていることがあります。SYSmark* や MobileMark* などの性能テストは、特定のコンピューター・システム、コンポーネント、ソフトウェア、操作、機能に基づいて行ったものです。結果はこれらの要因によって異なります。製品の購入を検討される場合は、他の製品と組み合わせた場合の本製品の性能など、ほかの情報や性能テストも参考にして、パフォーマンスを総合的に評価することをお勧めします。

構成: [デュアルコア インテル® Atom™ プロセッサー Z2760 (開発コード名 Clover Trail) ベースの開発用サンプルシステム、1GB RAM、Android* 4.1.2 (Jelly Bean*) OS、テスト用 iOnRoad アプリケーション]。
詳細については、http://www.intel.com/performance/resources/benchmark_limitations.htm (英語) を参照してください。

まとめ

インテル® SSE 組込み関数 (インテル® SSSE3 以上) は大幅なパフォーマンスの向上をもたらし、インテル® Cilk™ Plus はインテル® Atom™ プロセッサー・ベースの Android* デバイス向けの並列化に最適です。

インテル® Atom™ プロセッサー・ベースの Android* デバイス向けにマルチメディア・アプリケーションやゲームを開発する場合は、インテル® SSE とインテル® Cilk™ Plus を利用して最適化することを推奨します。これらの信頼できるツールにより、大幅なパフォーマンス向上が得られるでしょう。

iOnRoad について

詳細は、iOnRoad の Web サイト (http://www.ionroad.com/ (英語)) を参照してください。

Intel、インテル、Intel ロゴ、Intel Atom は、アメリカ合衆国および / またはその他の国における Intel Corporation の商標です。
© 2014 Intel Corporation. 無断での引用、転載を禁じます。
* その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

関連記事