PCクラスタでの擬似乱数列の具合(Rでの例)
- PCクラスタでLAMを起動して、R内から、複数のslavesにアクセスして、それぞれで乱数を用いた処理をする場合を考える。
- 5個のslavesを発生させ、それぞれで、runif関数により、一様乱数を5つずつ発生させてみる
> clusterApply(cl,c(5,5,5,5,5),runif)
[[1]]
[1] 0.07626168 0.86739662 0.08542570 0.69068869 0.73321858[[2]]
[1] 0.07626168 0.86739662 0.08542570 0.69068869 0.73321858[[3]]
[1] 0.56498224 0.08485308 0.06428090 0.43612980 0.95207290[[4]]
[1] 0.56498224 0.08485308 0.06428090 0.43612980 0.95207290[[5]]
[1] 0.57652898 0.71699250 0.55145098 0.06442884 0.69536823
- というように、第1slaveと第2slave(いずれも第1ノード), 第3slaveと第4slave(いずれも第2ノード)で全く同じ長さ5の乱数列が得られた。それぞれのノードの2 slavesが同一のseedから(擬似)乱数列を発生させたためである。これが不都合な場合があることは当然で、それぞれで異なる、ばらばらな値を作りたい。また、場合によっては、各slaveで全く同一の(擬似)乱数列を使いたいかも知れない。
- まず、全slavesで擬似乱数列をそろえてみる。
- g<-function(n,m){set.seed(i);runif(m)}、なる関数を用意する。内容は、擬似乱数列用のseed n を指定して、その上で、m 個の一様乱数を発生させるものである。次のコマンドで、各slaveに同じseedを作らせて、一様乱数列を表示させてみる。n=1234,m=5である。
> clusterApply(cl,c(1234,1234,1234,1234,1234),g,5)
[[1]]
[1] 0.1137034 0.6222994 0.6092747 0.6233794 0.8609154[[2]]
[1] 0.1137034 0.6222994 0.6092747 0.6233794 0.8609154[[3]]
[1] 0.1137034 0.6222994 0.6092747 0.6233794 0.8609154[[4]]
[1] 0.1137034 0.6222994 0.6092747 0.6233794 0.8609154[[5]]
[1] 0.1137034 0.6222994 0.6092747 0.6233794 0.8609154
- 次に各slaveでばらばらにする。並列環境に擬似乱数列を使うSPRNGを用いる
> clusterSetupSPRNG(cl)
> clusterApply(cl,c(5,5,5,5,5),runif)
[[1]]
[1] 0.014266542 0.749391854 0.007316102 0.152742874 0.113462114[[2]]
[1] 0.8390032 0.8424790 0.8896625 0.2256776 0.8981241[[3]]
[1] 0.2724742 0.5006002 0.4281134 0.2371450 0.5090693[[4]]
[1] 0.7296370 0.8640611 0.7465838 0.6676175 0.5823375[[5]]
[1] 0.3054607 0.5639488 0.6168621 0.6351189 0.7749574
- 現在参照中のこのページでは、このほかに "a quick and (very) dirty)"な方法として、まず、各slaveに対して、親ノードで発生させたslaveの個数分の乱数を、set.seed関数を用いて、それぞれのslaveのseedとして登録してやる方法も紹介している。dirtyかもしれないけれど、SPRNGのインストールに難航したりすることを思えば、合理的な汚さかもしれない。一度、乱数でset.seedしてしまえば、そのセッションが終了するまでは、そのseedから始まった乱数列が出てくるので、次回の起動・クラスタ結合のときまでは、(だいたい)大丈夫。ただし、この一見異なる乱数列は、同一の乱数列をいろんなところから使いはじめているだけなので、壮大なレベルでは、同一の擬似乱数列を使っていることになり、気持ちが悪いのは確かである。