/* * This file is part of the X10 project (http://x10-lang.org). * * This file is licensed to You under the Eclipse Public License (EPL); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.opensource.org/licenses/eclipse-1.0.php * * (C) Copyright IBM Corporation 2006-2010. */ import x10.util.Random; import x10.util.concurrent.AtomicLong; /** * A parallel version of the Monte Carlo estimate for pi that uses * several Places and several threads at each place. */ public class MontePiCluster { /** * At the current Place, spawn some threads, each of which * generates n random points and return the total number * (combining all of the threads results) that fell inside * the circle. * @param pId: this process's id: used to create the seed for the * random number generator. * @param threads: how many threads to use at this Place * @param n: how many points for each thread to generate * @return the total for all the threads of the number of points * that landed inside the circle. */ public static def countAtP(pId: Int, threads: Int, n: Long) { var count: Long = 0; finish for (var j: Int = 1; j<= threads; j++) { val jj = j; async { val r = new Random(jj*Place.MAX_PLACES + pId); val rand = () => r.nextDouble(); val jCount = countPoints(n, rand); atomic count += jCount; } } return count; } /** * Generate n points at random in the unit square, and return * the number that fell within the unit circle. * @param n the number of points to generate * @param rand the function generating the random numbers * @return the number of points that landed in the circle */ public static def countPoints(n:Long, rand:()=>Double) { var inCircle: Long = 0; for (var j: Long=1; j<=n; j++) { val x = rand(); val y = rand(); if (x*x +y*y <= 1.0) inCircle++; } return inCircle; } /** * There are three optional command line arguments: args(0) is the * number of points to generate, and args(1) is the number of * parallel activities to use, and args(2) is the number of * threads to use at each Place. */ public static def main(args: Array[String](1)) { val N = args.size() > 0 ? Long.parse(args(0)) : 1000000L; val places = args.size() > 1 ? Int.parse(args(1)) : Place.MAX_PLACES; val tPerP = args.size() > 2 ? Int.parse(args(2)) : 4; val nPerT = N/(places * tPerP); val inCircle = new Array[Long](1..places); finish for(var k: Int = 1; k<=places; k++) { val kk = k; val pk = Place.place(k-1); async inCircle(kk) = at(pk) countAtP(kk, tPerP, nPerT); } var totalInCircle: Long = 0; for(var k: Int =1; k<=places; k++) { totalInCircle += inCircle(k); } val pi = (4.0*totalInCircle)/N; Console.OUT.println("The value of pi is " + pi); } }