並列計算の効果検証用プログラム

並列化の試行やJITの効果テストなどのために,Forをたくさん回す計算例が必要になる。 そのような例としてモンテカルロ法を置いておく。

ToDo 並列計算のテスト用としては,モンテカルロ法のような単純に並列化される(データ共有が無い)ものだけでなく,適時データ共有が必要となる例を別途置いておく。

モンテカルロ法による円周率計算

  • モンテカルロ法の例題でよく見る計算。[0,1]の範囲の乱数を生成して,その点が半径1の円の中に入るか否か?(点が円の中か否かは,点の距離dがsqrt(x2+y2)で計算できるから,円周率piを知らなくても判定できる)をランダムに試行して,N回サンプリングすると,円の中に入る比率が1:pi/4になることから推定する(円の面積がpirrなのは知っている)
# monte_carlo.py
import random

def calc_pi(iter):
    cnt = 0
    for _ in range(iter):
        x, y = random.random(), random.random()
        if x*x + y*y < 1:
            cnt += 1
    return (cnt*4.0)/iter
  • 全く同じ書き方でC言語でも。
#include <stdio.h>
#include <stdlib.h>

double calc_pi(int iter)
{
  int cnt=0;
  double x, y;
  
  for (int i=0; i<iter; i++) {
    x = (double)rand()/RAND_MAX;
    y = (double)rand()/RAND_MAX;
    if ((x*x + y*y) < 1)
      cnt++;
  }
  return cnt*4.0/iter;
}

int main(int argc, char** argv) {
  int iter;
  double pi;
  
  iter = atoi(argv[1]);
  pi = calc_pi(iter);
  printf("pi:%f", pi);

  return 0;
}
  • ちなみに,生のPythonは20倍くらい遅い。
# Python
$ time python3 monte_carlo.py 10000000 # 10M
real 0m3.838s                          # 0.4us/iter

# C(Clang, -O3)
$ time ./a.out 10000000                # 10M
real 0m0.214s                          # 0.02us/iter