aki.の月記 このページをアンテナに追加 RSSフィード

2006 | 08 | 09 | 10 | 11 | 12 |
2007 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 12 |
2008 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2009 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2010 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2011 | 01 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2012 | 01 | 03 | 04 | 05 |

2011-11-13

[] 疑似乱数を利用したdf-pn探索の簡易分散並列計算  疑似乱数を利用したdf-pn探索の簡易分散並列計算を含むブックマーク  疑似乱数を利用したdf-pn探索の簡易分散並列計算のブックマークコメント

GPWで見た保木さんの発表がお手軽で面白そうだったのでやってみました。

https://ipsj.ixsq.nii.ac.jp/ej/?action=pages_view_main&active_action=repository_view_main_item_detail&item_id=78266&item_no=1&page_id=13&block_id=8

要はdf-pnにちょろっと乱数を加えた複数のクライアントがそれぞれ探索してみて、一番早く結果が返ってきたのを採用、という感じです。

C#版のBlunderでの実装は、↓こんな感じになりました。


とりあえずテーブルを用意しまして、、

[Blunder/SearchMate/AndOrTree.cs]

        public struct RandEntry { public int P, D; }
        /// <summary>
        /// 乱数テーブル
        /// </summary>
        /// <remarks>
        /// 疑似乱数を利用したdf-pn探索の簡易分散並列計算
        /// https://ipsj.ixsq.nii.ac.jp/ej/?action=pages_view_main&amp;active_action=repository_view_main_item_detail&amp;item_id=78266&amp;item_no=1&amp;page_id=13&amp;block_id=8
        /// </remarks>
        public RandEntry[] RandTable = new RandEntry[1024];

新規節点で固定深さ探索をした結果のp, dに対して、ハッシュ値で表を引いてpかdを1bitシフトする感じに。

[Blunder/SearchMate/AndOrTree.FDS.cs]

            // 乱数を加算
            if (minD < Infinity) {
                var t = RandTable[context.HistoricalHashValue & 1023];
                p <<= t.P;
                d <<= t.D;
            }

乱数テーブルを埋めるところは↓こんな感じです。

    for (int j = 0; j < randTable.Length; j++) {
        uint rand1024 = rand.NextUInt() & 1023;
        if (rand1024 <= 50) { // 5%くらいの確率でP=1, D=0
            randTable[j].P = 1;
        } else if (rand1024 <= 100) { // もう5%くらいの確率でP=0, D=1
            randTable[j].D = 1;
        } else {
            // P=0, D=0 (乱数無し)
        }
    }

そしてコレをコア数分だけスレッド作って実行する処理をUSIEngine.csのgo mateのところに実装して、将棋所の「詰」ボタンで動くようにしてみました。

そして6コアで6並列で、そのうち1個は乱数無しにしていて、それ(オリジナル)と、6並列のうち1番早く答えが出たもの(最小)について、節点数と実時間を出力するようにしてみまして、試しに将棋図巧の1〜20番を解かせてみたところ、こんな感じに。

作品オリジナル節点数最小節点数節点数比オリジナル時間[ms]最小時間[ms]時間比
図巧2番3,4952,78579%12812597%
図巧3番125,263114,76491%74370194%
図巧5番1,9271,80393%141141100%
図巧7番48,47132,27066%36328478%
図巧9番481,022344,84771%2,6321,92873%
図巧10番62,82946,37173%40632680%
図巧11番1,3801,35798%129129100%
図巧12番76,23468,89590%54550993%
図巧13番1,9161,86097%118118100%
図巧14番1,407,60722,2851%8,1552402%
図巧15番34,62333,51996%32029391%
図巧16番14,94513,85092%18818497%
図巧17番2,429,6112,028,48783%17,95914,75782%
図巧18番5,4684,37880%15315198%
図巧19番216,129198,81591%1,4451,34292%
図巧20番2,544,9321,801,71870%20,92013,48364%

1,4,6,8は解けそうになかったので諦めました。_no

そして14番が凄い事になってますが、乱数の種を固定していなかったので再現性のないデータになってしまいました。(まぁ、オリジナルが回り道しすぎているだけの気もしますが)


最後に、無駄にフルセットな実行ファイル・ソース一式はこちらに。

http://tqzh.tk:24497/site/blunder/Blunder-EasyDistrDFPN.zip

かず@なのはかず@なのは 2011/11/14 12:46 論文読んでいませんが、あまり実戦向きではなさそうですか?
リソースがふんだんにあればよさそう?
ところで今回はC#版ですが、C++版はさらに3倍以上速いとか?!

ak11ak11 2011/11/15 01:47 マシンが余ってたら分散で1局面読むより沢山の局面を読んでいった方が良かったり、スレッド並列ならもっと効率良くやれるようだったりするものの、それすらGPS将棋のクラスタが暇なときに使うくらいだったりしてるようなので、まぁ実戦には役立たないけど「簡単に分散処理できたよ!」という感じっぽいです。

C++版はまだdf-pnまでは出来てないです。_no

OgaOga 2011/12/10 01:45 今回のバージョンは評価関数が少し変わってるような・・・
気のせいですかね?

ak11ak11 2011/12/11 09:14 なんかバージョンアップするごとに弱くなってしまっていたので、色々試行錯誤してます。

OgaOga 2011/12/30 12:13 質問なのですが、今回のと2011バージョンはランダムでアルゴリズムが変更されているような?
ある局面で検討させると、検討ボタンを押す度に解答が変更になったり?
2010と連続対局させてると評価値が似たようなグラフになる時と、全く違った形になったり?4・5種類の癖が有るように思うのですが…
もしかして、指し手がタンパクになったりするのは、コレが影響してるのでしょうか?
アルゴリズムを指定しても、固定しきれてないような?

ak11ak11 2011/12/31 11:53 将棋所で時間を無制限にした場合以外(対局時も含む)では、少し乱数を入れているので、読み筋が変わる場合があります。
あと並列探索をしている場合も、タイミングによって読み筋が変わる場合があります。

並列探索なし(スレッド数1)で時間無制限の検討でなら毎回同じ読み筋になると思います。…バグってなければ。

トラックバック - http://d.hatena.ne.jp/ak11/20111113