8/20の日記の補足
id:streakeagle:20070820:1187623564で書いた三目並べのマルチスレッドの件です。
http://d.hatena.ne.jp/Gasyou/20070820/1187623564
http://d.hatena.ne.jp/mkomiya/20070822/p1
GA将!さんが、三目並べを並列処理で試しているらしい。
強化学習かな。
強化学習でマルチスレッドなんですが、高速化を狙ったものではありません。
まず、前提として、強化学習のエージェントは以下の様に行動します。
while( 飽きるまで ) { while( 対局終了まで ) { // 今の状態を環境(盤面+相手プレイヤーをまとめたもの)から取得 State state = this.environment.getState(); // 今の状態で取れる行動から一つ選択 Action action = this.selectOne( state.getActionList() ); // 環境に対して自分がとる行動を伝え、報酬を取得する final double returns = this.environment.play( action ); // 学習する this.learn( returns ); }// while(...) }// while(...)
で、三目並べや将棋だとエージェントが先手と後手で2つになるのですが、それらをシングルスレッドで扱おうと思うと上記のループを適当に修正する必要が出てきます。
さらに、私はメタ強化学習*1を実装する予定なので、さらにエージェント数が増えます。
そうすると、全部で4つか5つのエージェントになるのですが、そうするとループの処理が結構面倒になります。
また、エージェント内部の実装はなるべく外に意識させたくないので、そういう意味でも(比較的メイン関数に近い位置にある)ループ内でエージェントの事を考えるのは避けたいところです。
なら、各エージェントに一つのスレッドを割り当てて、各自がてんでんばらばらに動く*2。ただし、environmentが適当にタイミングを調整してくれる、という実装にしようと思っています。
例えば、三目並べの場合だと先手エージェントがapply(Action)で行動した後に学習して、その後内側while()文の先頭に戻ってgetState()を呼びます。
この時、後手エージェントがまだ行動していなければ、getState()内で先手エージェントのスレッドの処理を停止ます。
例えば、三目並べの場合だと先手エージェントがapply()で行動します。すると、apply()メソッド内部で後手が指すのを待ちます。
で、後手エージェントは別スレッドで動いているのでそのうち行動し、そうすると今度は先手番になるので、その時に停止していた先手エージェントのスレッドを再開するし、apply()が報酬を返す、という感じです。
要するに、シングルスレッド版では全体のタイミングを調整する「指揮者」みたいな人がいたわけですけど、それをなくして各エージェントが好き勝手に動く。ただし、環境内部で適当にタイミングを調整してくれる、って事です。
・・・と、ここまで書いといてなんですが、高々5エージェント程度ならシングルスレッドでもいい気がしてきました。趣味の問題かなぁ。
8/22 22:40 間違えてたんで修正