余白の書きなぐり

aueweのブログ

OpenMPIで乱数を使う

普通の(並列計算でない)プログラムで乱数を使用する際に、 プログラムを実行するたびに異なる系列で擬似乱数を発生させるには seed に現在時刻を使用するのが一般的だ。 要するに

srand((unsigned) time(NULL));

とすればよい。詳細は以下のページにまとまっている。

srand 擬似乱数の発生系列を変更する


OpenMPIで乱数を使用する際はどうすればよいか? さきほどと同じように設定すると、 myrank==0でもmyrank==1でも同じseedを使用することになる。

サンプルコード

// single_seed.c
#include <stdio.h>
#include <time.h>
#include <mpi.h>

int main(int argc, char **argv){
  MPI_Init(&argc, &argv);

  int myrank, allrank;
  MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
  MPI_Comm_size(MPI_COMM_WORLD, &allrank);

  srand((unsigned)time(NULL));

  int random = rand();
  printf("myrank=%d/%d rand=%d \n", myrank, allrank, random);
  MPI_Finalize();
}

コンパイルと実行結果

$ mpicc single_seed.c 
$ mpirun -np 4 a.out
myrank=3/4 rand=508085506 
myrank=0/4 rand=508085506 
myrank=2/4 rand=508085506 
myrank=1/4 rand=508085506 

myrank==0とmyrank==1で異なるseedを使用したければ、

srand((unsigned)(time(NULL)+myrank));

とすればよい

サンプルコード

// different_seed.c
#include <stdio.h>
#include <time.h>
#include <mpi.h>

int main(int argc, char **argv){
  MPI_Init(&argc, &argv);

  int myrank, allrank;
  MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
  MPI_Comm_size(MPI_COMM_WORLD, &allrank);

  //srand(time(NULL)+myrank);
  srand((unsigned)(time(NULL)+myrank));

  int random = rand();
  printf("myrank=%d/%d rand=%d \n", myrank, allrank, random);
  MPI_Finalize();
}

コンパイルと実行結果

$ mpicc different_seed.c 
$ mpirun -np 4 a.out
myrank=0/4 rand=2096907971 
myrank=1/4 rand=1802318349 
myrank=3/4 rand=116611292 
myrank=2/4 rand=1487240429