インテル® アーキテクチャー・ベースのプラットフォームで NDK ベースの Android* ゲーム・アプリケーションを開発および最適化する

同カテゴリーの次の記事

インテル® アーキテクチャー上の Android* エミュレーターを高速化する

この記事は、インテル® デベロッパー・ゾーンに掲載されている「Development and Optimization for NDK-based Android Game Application on Platforms based on Intel® Architecture」の日本語参考訳です。


Android* Native Development Kit (NDK) は、C/C++ のようなネイティブコード言語を使ってアプリの一部を実装できるようにする Android* SDK のコンパニオン・ツールです。http://developer.android.com/tools/sdk/ndk/index.html (英語) からダウンロードできます。

x86 命令セット・アーキテクチャー向けの NDK

Android* は、Google* によって開発されたオープンソースのオペレーティング・システムです。現在、ARM、x86、MIPS の 3 つの命令セット・アーキテクチャー上で実行できます。x86 は、1978 年に登場したインテル® 8086 CPU ベースの命令セット・アーキテクチャーを指します。x86 (インテル® アーキテクチャーまたは IA とも呼ぶ) と Android* が動作するほかのチップセットの違いについて、アプリケーションの観点から見てみましょう。

Android* アプリケーションは、次の 2 種類に分類できます。

  • Dalvik アプリケーション。Java* コードを含み、Android* SDK の API のみを使用し、xml や png などの必要なリソースファイルが APK ファイルにコンパイルされています。
  • Android* NDK アプリケーション。Java* コード、リソースファイル、C/C++ ソースコード、そして (場合によっては) アセンブリー・コードを含んでいます。すべてのネイティブコードはダイナミック・リンク・ライブラリー (.so ファイル) にコンパイルされ、JNI メカニズムによりメインプログラムから Java* 経由で呼び出されます。

Android* ゲームエンジン

ゲーム・アプリケーションにとって、ゲームエンジンは最も重要なモジュールです。オープンソースや商用の 2D/3D エンジンなど、Android* で動作するエンジンはいくつかあります。そのため、IA プラットフォームで実行する Android* ベースのゲームの移植と開発は簡単ではありません。Android* プラットフォーム向けゲームエンジンとして最も人気があるのは、Cocos2d-x と Unity* 3D です。

Cocos2d-x は、Cocos2d-iPhone をベースに対応プラットフォームが拡張されており、共通の 1 つの API 構造が複数のプログラミング言語により使用されます。2010 年 7 月のリリース以来、Cocos2d-x のダウンロード数は 5 億を超えています。モバイルゲーム業界大手の Zynga*、Glu*、GREE*、DeNA*、Konami*、TinyCo*、Gamevil*、HandyGames*、Renren Games*、4399*、HappyElements*、SDO*、Kingsoft* などが Cocos2d-x を採用しています。

Unity* 3D は、Unity Technologies* によって開発されたビルトイン IDE を備えるクロスプラットフォームのゲームエンジンです。100 万を超える開発者が、Web プラグイン、デスクトップ・プラットフォーム、ゲーム機、モバイルデバイス向けビデオゲームの開発に Unity* 3D を利用しています。2005 年に OS X* 対応のゲーム開発ツールとしてリリースされ、その後マルチプラットフォームのゲームエンジンに成長しました。最新のアップデート Unity* 4.3 は、2013 年 11 月にリリースされました。現在、iOS*、Android*、Windows*、Blackberry* 10、OS X*、Linux*、Web ブラウザー、Flash*、PlayStation* 3、Xbox 360*、Windows Phone*、Wii* 向けの開発をサポートしています。

IA プラットフォームで Android* NDK ベースのゲームを開発する

ゲーム開発について述べる前に、Android* プラットフォーム全般について説明します。ご存知のように、ゲームにはさまざまなスタイルがあります。ゲームのスタイルが異なれば、その設計方針も変更する必要があります。通常、プロジェクトを開始するときにゲームのジャンルを決定します。全く新しいものや、これまでに見たこともないようなものでない限り、ゲームのアイデアは現在ある広範なジャンルの 1 つに当てはめることができるでしょう。ほとんどのジャンルでは、ゲームデザインの基準 (制御方式や特定の目標など) が確立されています。ゲームでは常に新しいものが求められているため、これらの基準を変更することがゲームの大ヒットにつながります。以下は、一般的なジャンルの一例です。

  • アーケード & アクション
  • 脳トレ & パズル
  • カード & カジノ
  • カジュアル
  • ライブ壁紙
  • レース
  • スポーツ
  • ウィジェット

一般的な Android* ゲームの開発プロセスは、ほかの Android* アプリケーションに似ています。最初に、Google* の Web サイトから Android* SDK と NDK をダウンロードし、インストールします。

ここでは、すでにインストールと必要な準備が完了していることを前提にしています。それでは、Cocos2d-x ゲームエンジンを例に、インテル® アーキテクチャー向けのゲームを作成する方法を見ていきましょう。

Cocos2D-x をダウンロードする

http://www.cocos2d-x.org/download (英語) から、Cocos2D-x の最新の安定したバージョンをダウンロードします。

バッチを実行する

ダウンロードした zip を展開し、Windows* エクスプローラーで展開したフォルダー内を参照し、バッチを実行します。プロジェクトの場所を聞かれたら、com.yourproject.something などに設定し、プロジェクト名とターゲット ID を指定します。cocos2dx インストール・フォルダー内に指定したプロジェクト名のフォルダーが作成されます。そして、次のように、スクリプトがエラーなしで実行されることを確認します。

NDK_ROOT の環境変数を設定する

home\\.bash_profile ファイル (この例では、c:\cygwin\home\user\.bash_profile にあります) の最後に、次の環境変数を追加します。

NDK_ROOT=/cygdrive//
export NDK_ROOT
 

Cygwin を再起動して cd $NDK_ROOT を実行すると、画面に次のように表示されます。

build_native.sh ファイルを実行する

デフォルトの設定は ARM です。ここでは x86 向けにコンパイルするため、この設定を変更します。\helloworld\proj.android \build_native.sh ファイルを開き、ndk-build コマンドの最後に APP_ABI=x86 パラメーターを追加します。このファイルを Cygwin で実行すると、次のような出力が表示されます。

プロジェクトを Eclipse* にインポートする

Eclipse* を起動して、新しいプロジェクトを作成し、既存のプロジェクトからインポートします。

ビルドと実行

この時点では、Eclipse* にいくつかの問題があります。

The import org.cocos2dx.lib cannot be resolved HelloWorld.java

/HelloWorld/src/com/young40/test line 26 Java Problem Cocos2dxActivity cannot be resolved to a type HelloWorld.java

/HelloWorld/src/com/young40/test line 30 Java Problem Cocos2dxActivity cannot be resolved to a type HelloWorld.java

/HelloWorld/src/com/young40/test line 33 Java Problem

次のライブラリーをプロジェクトとして Eclipse* にインポートする必要があります。

cocos2d-2.1beta3-x-2.1.1/cocos2dx/platform/android/java

[Project] > [Build] を選択してから、[Run] > [Run As] > [Android Application] を選択します。

これで、cocos2dx ゲームエンジン向けにゲームフレームワークがビルドされます。このプロジェクトにゲームのロジック、音声、画像などのリソースを追加して、ゲームを完成させます。

IA プラットフォームで Android* NDK ベースのゲームを最適化する

インテル® System Studio は、Android* プラットフォーム上でアプリケーションのプロファイルと最適化を行うツール群です。もちろん、ゲームの最適化にも利用することができます。 次のツールが含まれています。

  • インテル® C++ コンパイラー
  • インテル® グラフィックス・パフォーマンス・アナライザー (インテル® GPA)
  • インテル® VTune™ Amplifier
  • インテル® JTAG デバッガー

ここでは、各ツールについては詳しく述べません。代わりに、インテルのツールがどのように動作するか例を使って見てみましょう。

最初に、Bounding Ball アプリケーションをインテル® Atom™ プロセッサー Z2460 (開発コード名: Medfield) で実行してみます。このゲームは、800 個を超えるボールがランダムな速度で動き回り、ボール同士が不規則に衝突します。最適化なしの FPS は 6 で、パフォーマンスが悪いことが分かります。

インテル® グラフィックス・パフォーマンス・アナライザー (インテル® GPA) を使って、ボトルネックとなっているモジュールを特定し、CPU によって制限されているのか、GPU によって制限されているのかを判断します。

次のインテル® GPA のスクリーンショットは、Android* プラットフォーム上の GPA で収集された、このアプリケーションの詳細情報のグラフです。このグラフから、CPU がリソースの 52.5% を消費していることが分かります。これは 1 つのアプリケーションにしては非常に高い値です。一方、GPU 内で実行している ISP Load (ISP ロード)、TA Load (TA ロード)、TSP Load (TSP ロード)、USSE Total Load (USSE 総ロード) はすべて 10% 未満です。つまり、GPU ロードは通常どおりであることが分かります。このことから、CPU モジュールがボトルネックになっていると判断できます。この CPU ボトルネックの問題をさらに詳しく調査するには、インテル® VTune™ Amplifier でコードをプロファイルする必要があります。

ここでは、インテル® VTune™ Amplifier の使用法は省略し、使用した場合に得られる結果だけを説明します。このアプリケーションの hotspot は、libm.so 内の sin 関数と cos 関数です。なぜこの 2 つの関数の実行に多くの時間と CPU サイクルが費やされているのでしょうか?

アプリケーションのソースコードを確認すると、OpenGL* ES で各ボールをレンダリングするときにこの 2 つの hotspot である関数が呼び出されています。すべてのボールの形状は同じで、サイズだけが異なるため、OpenGL* 関数 glScale でボールを複製し、hotspot の関数で費やされる時間を大幅に軽減することができます。

コードを最適化したところ、パフォーマンスが 80% 向上し、FPS は 14 になりました。インテル® C/C++ コンパイラーでアプリケーションをコンパイルすると、インテル® アーキテクチャー・プラットフォームでさらにパフォーマンスを向上することができます。インテル® C/C++ コンパイラーには、IA プラットフォームでパフォーマンスを最適化するための多数のオプションがあります。ここでは、その一部を紹介します。

  • SSSE3_ATOM
    インテル® ストリーミング SIMD 拡張命令 3 補足命令 (インテル® SSSE3) は、インテルによって開発された SIMD 命令セットで、4 番目の SSE テクノロジーです。
  • IPO
    プロシージャー間の最適化 (IPO) は、関数呼び出しオーバーヘッドの軽減、不要コードの排除、定数の伝搬とプロシージャーの並べ替えを行います。
  • PGO
    プロファイルに基づく最適化 (PGO) は、次のような問題を解析し、最適化の可能性を高めます。
    • x > y になる頻度は?
    • カウントのサイズは?
    • どのコードがどの程度の頻度で実行されるか?

さらに、インテル® C/C++ コンパイラーは、次の機能も提供します。

  • より正確な分岐予測
  • 基本ブロックの移動による命令キャッシュ効率の向上
  • 効率良い関数のインライン展開 (IPO で役立ちます)
  • 効率良い関数の並べ替え
  • スイッチ文の最適化
  • 効率良いベクトル化

異なるコンパイラーとコンパイル引数を使用することで、アプリケーションのパフォーマンスは変わります。以下は、GCC コンパイラーとインテル® コンパイラー (ICC) を使用した場合のパフォーマンスの比較です。インテル® Atom™ プロセッサー Z2460 (開発コード名: Medfield) を搭載した Android* 端末で、Bounding Ball アプリケーションを実行してパフォーマンスを測定しました。青は GCC、赤は ICC のパフォーマンスを示します。ベースラインは、引数なしでコンパイルした結果です。2 つ目は arch=atom を指定してコンパイルした結果で、3 つ目はここで触れたすべての引数を指定して再コンパイルした結果です。グラフから、GCC よりも ICC でコンパイルしたアプリケーションのほうがパフォーマンスが 60% 高いことが分かります。

まとめ

この記事では、IA プラットフォーム上での Android* ゲーム開発と最適化の概要を説明しました。ゲームエンジンは、すべてのゲーム開発における最重要部分です。IA プラットフォームでゲームエンジンを最適に実行することができれば、ゲームも最適に実行できます。ここでは、広く利用されているゲームエンジン cocos2dx を例に、IA プラットフォームで開発する方法を紹介しました。インテルでは、Android* プラットフォームでゲーム・アプリケーションの最適化を支援するツール群を提供しています。ここでは、インテル® System Studio を使って、サンプル・アプリケーションを最適化する手順も示しました。

著者紹介

Tao Peng

インテル コーポレーションのソフトウェア & サービスグループのアプリケーション・エンジニア。x86 デバイス向け Android* アプリケーションの開発および最適化、Web HTML5 アプリケーション開発を含む、モバイル・アプリケーション・イネーブリングに取り組んでいます。

コンパイラーの最適化に関する詳細は、最適化に関する注意事項を参照してください。

関連記事