fork(1) download
  1. 4状態2記号のビジービーバーマシンの最大シフト数 N が与えられたとき
  2. ( シフト数と状態数と記号数のみで、ルール表は教えてもらっていないとき )
  3. 4状態2記号のチューリングマシンを全て N ステップまで実行し
  4. Nを越えたものは無限ループするチューリングマシンと確定するので
  5. ちょうどNで停止するもののルール表をみつけるプログラム
  6.  
  7. 4状態2記号での N は 107 なので2記号のテープを32ビット整数8つの256ビットで表わして
  8. GPU上で全て試行する
  9. ( 256ビットの真ん中を初期位置にすることでどんなマシンを実行したとしても
  10. 107ステップ以内では範囲外に出ることが無い )
  11.  
  12.  
  13. GPGPUにはOpenCLを使う
  14.  
  15.  
  16. 4状態2記号のルール表は
  17. 4つの各状態で0か1を読み取った場合の 4x2 の表に
  18. 次の状態が(停止状態を含めて)5通り
  19. 書き込む記号が2通り
  20. ヘッドの移動する方向が2通り
  21.  
  22. なので (5x2x2) の 8乗 通りある
  23.  
  24. ルール表を表す変数の名前の規則は
  25. aの後の1-8の数字が状態と読み取った記号の8通りの場合で
  26. そのあとに n とつく ( a1n 等 ) ものは 次の状態を表し、
  27. wd とつく ( a1wd 等 ) ものは 2ビットで書き込む記号と ヘッドの移動方向を表す
  28.  
  29.  
  30. OpenCLのカーネルでは
  31. CPUからGPUへのワークの発行1回で
  32. ルール表の 4x2 の 3つの部分は ワーク内の全てのスレッドで固定して ( この3つは発行1回ごとにCPUで順に切り替える )
  33. 残りのうち3つは 1度に発行した 20の3乗 = 8000 個のスレッドのIDを
  34. あらかじめ作っておいた 8000要素の配列の添え字で切り替えて
  35. 残りの2つの部分は 各スレッドで 20の2乗 回のループで切り替える
  36.  
  37. 8000要素の配列はその前のワーク内全てで固定した部分をCPUでのループで書き換えてもそのまま使えるようになっている
  38.  
  39.  
  40. カーネル内でチューリングマシンを実行するとき GPGPUでの実行なので、
  41. テープを大きな配列で表わしてヘッドの位置を添え字で指定する方法は( *コアレスアクセス* にならないので)使えないので
  42. 長さ256ビットの2記号のテープを32ビット整数8つで表わし、
  43. 8回の短いループだけで1ビットを読み出し (こうすればGPUの演算機のグループは揃ったメモリアクセスをしてくれる)
  44. 状態遷移後も同様のループで1ビットを書き出す
  45.  
  46.  
  47. Wikipediaのビジービーバー関数の記事にはこの答えとなるルール表が載っているが、
  48. このプログラムの実行結果で最初に表示されるものが正しいかどうかの記事との比較のときは
  49. 状態とルールの並び順をそのままに比較しても一致しているとは限らない
  50. 記事でのルール表の状態の番号が違うだけの同型の結果を最初に表示している可能性があることに注意
  51.  
  52.  
  53. 自分のPCでこのプログラムを実行した結果
  54.  
  55. 25600000000通り ( 256億通り ) のルール表が存在するが、
  56. 10~20分程度で実行完了して正解のルール表に一致していた
  57.  
  58.  
  59. ビジービーバー関数は本来、プログラム等で指定した状態数記号数のものの 最大シフト数を求めたりはできないが、
  60. ( 全てのルール表について、そのルールだと無限ループする場合、そうなることの証明が必要 、
  61. 有限ステップをシミュレートしただけでは その先残りの有限ステップ実行すれば停止するのか、
  62. それともそのまま無限ループするかの判定はできない )
  63. 今回は最大シフト数から逆にルール表をみつける問題なのでコンピュータで探索することができた
  64.  
  65.  
  66. GPGPUではなく、CPUでマルチコアを利用して解いた場合、上記のスペックだとどれくらいの時間がかかるかの確認が必要
  67. そのためにはCPUでの実行に特化したコードを新たに書く必要がある
  68.  
  69.  
  70. P.S.
  71.  
  72. 遅れてました
Not running #stdin #stdout 0s 0KB
stdin
Standard input is empty
stdout
Standard output is empty