NDKを使うとどんくらい速くなるのか試す

とても実装が簡単なフィボナッチ数列の第N項を求めるだけの関数を使って,NDKを使った場合と使わなかった場合でどんくらい差が出るのか試した.

NDKを使う手順

  1. Androidプロジェクトの作成
  2. 右クリックして,AndroidTools->Add Native Support
  3. .javaファイルの方に,native指定子を付けてメソッドを宣言
  4. プロジェクトのビルド(これをしないと.classファイルがないと怒られる)
  5. jni以下にヘッダファイルを生成(javahを使う)
  6. 生成されたヘッダから宣言部分をコピペしてcppファイルに実装
前回も書いたけどこういう感じでNDKを使用します.

fibonacci

Androidバイトコードの方はこっち

private long fibo(int n) {
	if (n < 3) {
		return 1;
	}
	return fibo(n-1) + fibo(n-2);
}

ネイティブコードの方はこっち

private native long fiboCpp(int n);//宣言
static {
	System.loadLibrary("fibo");//読み込み
}
#include <jni.h>
#include "fibo.hpp"

long fibo( int n ) {
	if ( n < 3 ) {
		return 1;
	}
	return fibo(n-1) + fibo(n-2);
}

JNIEXPORT jlong JNICALL Java_com_example_hellondk_MainActivity_fiboCpp
  (JNIEnv *env, jobject obj, jint n) {
	return fibo( n );
}

ボタンを押したらスタートして,実行が終わったらTextViewに実行時間を表示するようにした.

実行結果

大体10倍くらいネイティブコードの方が速かった.

考察

やっぱ機械語は速いんですねー.

AsyncTaskを使って,onPreExecute()で開始時間を測り,onPostExecute()で終了時間を測った場合は,Nを小さくした場合でも10ms前後の時間がかかった

開始時間と終了時間の計測を,doInBaskground()内で行った場合は,Nが小さいとどちらの場合も0msになったので,メソッドを呼び出す分のロスだったのかなーと思われる.

また,Nの値にかかわらず実行時間の振れ幅がかなり大きいのも気になった.ガベージコレクションか,それとも他のプロセスが優先して実行されたのか.よくわからない.

実行結果に振れ幅が大きかったので,もっと大量にデータが欲しかったんだけど,ボタン押して画面で確認するのが辛いので諦めた.

_人人人人人人人人人人人人人人人人_
> GUIで操作しようとしたのが悪い <
 ̄Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y ̄

何回か試行してそのデータをグラフとして表示とかできるようにしたい…

コードはhttps://github.com/crakaC/NDK_sampleにおいているので煮るなり焼くなりしてください.