« グラフィック周りの処理 | メイン | デバッグしてたら »

2005年11月16日

Teaspire 開発日誌:: マルチスレッドの話

    

少し前に書いたけど、レンダリングを別スレッドにした。
現在のソースは元々吉里吉里のプラグインとして書いていたもので、描画の更新はTJSから呼び出されていた。
が、これが重い重い。
なので、何とか描画の更新は別スレッドにしたかった。
また、フレームごとに呼び出すような形にしたかったと言うのもある。
レンダリング時にV-Blank待ちがあるので、そこのレスポンスの改善という意味もある。

今後は出来るだけマルチスレッド化していかなければならないと言う流れのようだ。
HTが積まれ、デュアルコアになって……
クロックがひたすら上昇して勝手に処理速度が速くなっていくと言うのは期待できない。
CEDEC2005 - デュアルコアプロセッサのためのマルチスレッド対応ゲームの開発事例に、3Dゲームエンジンのマルチスレッド化についていろいろと書かれている。


マルチスレッドは難しい。
リソースの競合とデッドロックと同期。
タイミングによる発生頻度の低い不具合に悩まされる。

リソースの競合はファイルへの書き込みを考えるとわかりやすい。
スレッド1はファイルへ1234と書き込み、スレッド2はABCDと書き込む。
もし、ファイルへの書き込みが排他処理されていなければ、書き込み途中にスレッドが切り替わり、12ABC34Dなどと書き込まれてしまうかもしれない。
スレッド1は1234と書き込まれていることを期待し、スレッド2はABCDと書き込まれていることを期待しているとしたら、このように書き込まれてしまっては困る。
このような問題は何らかのリソースを共有する場合に起こる。
ファイルに限らず、特定のメモリ領域もありえる。
マルチスレッドを使う場合は、出来る限りリソースを共有しないようにした方が、不具合の発生を減らし、効率的に動作するようになる。(常にと言うわけではないが)

デッドロックはリソースの競合を避けるためにセマフォやクリティカルセクションなどの排他処理を行う機構を使用した場合などで起こる。
グラフィックリソースとサウンドリソースがあり、スレッド1がグラフィックリソース、サウンドリソースの順で確保して、スレッド2がサウンドリソース、グラフィックリソースの順で確保していたら、デッドロックする可能性がある。
これは、スレッド1がグラフィックリソースを確保した後にスレッドが切り替わり、スレッド2がサウンドリソースを確保するとはまる。
この後、スレッド2はグラフィックリソースを確保しようとするが、既にスレッド1が確保しているので、確保できない。スレッドが切り替わり、スレッド1になってサウンドリソースを確保しようとしたら、スレッド2が既に確保しているので、確保できない。
お互い確保出来なくて処理が停まってしまう。
これを避けるためには、リソースの確保順が常に同じになるようにすればいい。

同期をとるためにイベントやメッセージを使っていてもデッドロックはよく起こる。
イベントを投げ合ってたりするとどこかで投げられない状態が発生し、そのイベントを待っているスレッドがずっと動けないままになることがある。

これらをシステマティックに排除できればいいのだが、シーケンス図や状態遷移図を描いてよく検討していても洩れることがある。

過去に書いたことがあるデザインは、mixi Alertのエントリにも書いたコマンドとキューを使う方法と1つのスレッドに他のスレッドを管理させる方法 ( サーバー&クライアント的な方法になる )。
これらは、最終的に1対1で考えられるので、考えやすい。
3つ以上のものが様々な状態を持って、相互に関連しているものを考えるのは難しい。
あれがこうなっている時に、これがこうなってて、残りがこうで…… というのを漏れなく考えていくのは難しい。

そんなこんなでマルチスレッドの設計を楽に出来ないかと考えていて、デザインパターンの本が出ていたのを思い出した。
Java言語で学ぶデザインパターン入門 マルチスレッド編と言うやつだ。

Javaなので買わなかったけど、他になさげだったので注文した。
レビューの評価は妙にいい。



投稿者 Takenori : 2005年11月16日 01:19




comments powered by Disqus
Total : Today : Yesterday : なかのひと