『パフォーマンス・チューニング』と言われると、何を想像されるであろうか?
OSやサーバー製品のパラメータ・チューニングを想像する人が多いであろうし、Ruby等のインタプリッタでは最新版の実行環境をインストールすることもチューニングになる。ソフトウェア開発では、適切なライブラリ、適切なコーディング、高速な言語、適切なアルゴリズムなどがパフォーマンス向上のポイントになるが、近年はマルチコア化に対応するのも大きなポイントになって来ている。
そんなマルチコア対応によるパフォーマンス・チューニングを、画像ぷるぷるするJava/Swingアプリに試みてみたので、適用以前の問題点と、適用による改善程度をまとめておく。
1. 画像ぷるぷるが微妙に遅い
先日紹介した写真の一部をぷるんと揺らすミニアプリだが、同時に5箇所以上の点を震わすと、大きくパフォーマンスが低下するという問題があった。フレームレートが大きく低下し、しかも乱高下するため、ぱたぱたとした動きになってしまうのだ。
ドット単位に演算を行う画像フィルターを連続してかけているのだが、この画像フィルターの処理がフレームレートに間に合わなくなるためだ。これでは快適に写真で遊ぶことができない。
2. 画像ぷるぷるはマシン・パワーを活かしていなかった
駄目な点は色々あるのだが、CPUを利用尽くせていない事が、悪いパフォーマンスの原因だ。ビットマップを取得設定するJavaのAPIに9割の処理時間がかかっているため、ユーザー・プログラムからは改善のしようがない。
以下はシンプル・モデルのCPU使用状況だ。10箇所を揺らしたときのCPU使用状況だが、25%にとどまっている。5箇所の指定ぐらいからCPU使用状況が25%ぐらいになっており、見ての通り頭打ちになっている。
CPUリソースを1/4しか使っていない状況でフレームレートは3~4であり、実用に耐えない状況だ。
せめて100%、CPUパワーを使う事ができれば、フレームレートが10を超え、ぱらぱらアニメ程度のクオリティーを維持することができるのだが、資源を使いきれていない勿体無い状況だ。
3. 最近のCPUでも速くならないアプリなんて・・・いっぱいある
画像ぷるぷるだけが駄目なわけではない。画像ぷるぷるだけが駄目なのであれば、『Java並行処理プログラミング ―その「基盤」と「最新API」を究める―』というような書籍は公刊されないであろう。
もともと高速に動いているので目立たないが、最近のCPUでも速くならないアプリはいっぱいある。理由は簡単で、最近のCPUは複数コアによる高速化を図っているのだが、教科書的に組んだアプリケーションでは1コアしか使わないからだ。
4. 画像ぷるぷるの基本構造は、単一コアに最適化
画像ぷるぷるの基本構造は、以下のように単純な2スレッド・モデルになっている。単純スレッド・モデルと言える構造だ。このモデルを採用した理由は、バックグラウンドに演算を全て押し付けるため、処理がすっきりする上に、演算処理が滞っても画面が固まったりしないからだ。シングルコアの時代は、とても実用的なモデルであった。
ただし、スレッド#1と#2は同時には稼動しないため、ほとんどCPUコアを一つしか動かさない。つまり、フィルタ演算部分の処理量が多く、スレッド#2を処理するコアの処理能力の限界が、アプリケーションの速度を決定してしまっている。
5. 画像ぷるぷるのマルチコア最適化を試みる
そこでコンカレント・プログラミングの手法を、画像ぷるぷるに適応させてみる。とは言え、適用したのは1994年にWindowsNTが発売された時期のマルチスレッド本に書いてある構成と基本的には同じものだ。ここではワーカースレッド・モデルと呼ぶ事にする。
処理の少ない(楕円の)座標計算、タイマー、描画部分は、それぞれ1スレッドを割り当てた。処理の重たいフィルタ演算部分は多数のワーカースレッドが稼動するように、コア数に応じて動的に設定するようにした。座標計算、フィルタ演算、タイマー間のデータ受け渡しはリング・バッファを用いて、セマフォによって制御を行った。
6. 画像ぷるぷるマルチコア版のパフォーマンスは大きく改善
今回は4コアのPCを用いて計測を行ったが、10箇所を同時に振るわせた時のフレームレートは10~14に向上し、格段に動きが良くなった。以前が3~4であったので、3~4倍のパフォーマンス向上と言えるであろう。CPU使用状況は以下のようになっており、92%まで有効に使う事ができた。なお、CPU使用状況の改善により、PCのファンは豪快に回ることになる。
追記(2011/3/3 23:00):後日、あるAPIの利用回数を見直す事で、50以上のフレームレートとなった
7. メモリの利用状況は悪化する
ワーカースレッド・モデルでは、単純スレッド・モデルよりも複雑だ。ヒープメモリに割り当てに、その特徴が現われている。最大メモリ利用量は大差ないが、ワーカースレッド・モデルの方が利用メモリの増減が大きい。
これはスレッド内部でオブジェクトの作成と廃棄を繰り返しているためだ。リング・バッファの構造を改良すればガーベッジ・コレクタが働かずに、もっと落ち着いたグラフになるとは思うが、複雑になると駄目プログラマの馬脚が現われると言う自戒の念をこめて掲載しておく。
8. 3倍速くなったと捉えるべきか、3倍しかと捉えるべきか
今後もマルチコア化は進んでいくと思われるので、画像ぷるぷるのようなワーカースレッドを用いる構造はカジュアルなプログラミングからも一般化していくと思われる。近年になって発表されたプログラミング言語Goでは、コンカレント・プログラミングが強力にサポートされている。
しかし、プログラミング言語を変えると10倍以上の速度的改善が受けられるケースもあるし、マルチコア対応にすると適切なアルゴリズムを適用しづらくなる場合もある。データ量によっては、適切なアルゴリズムとそうでないものでは数千倍の速度差が出ることもありえるわけで、そう考えると3倍の速度向上は大きくは無い。それなり手間暇もかかるため、最初からマルチコア対応でプログラミングを行うのは、インセンティブに欠けるかも知れない。
0 コメント:
コメントを投稿