使用 Monte Carlo 方法并行计算 Pi
Calculating Pi using Monte Carlo method in parallel
我一直在尝试并行使用 Monte Carlo 模拟来计算 pi 的值。
到目前为止,我已经创建了线程,并生成了随机点,但是我无法 return 那些生成的点从线程返回到 main 线程。
如何解决这个问题?
下面是我写的代码
import java.util.*;
class MyThread extends Thread{
int points;
int insidePoints;
public MyThread(int insidePoints, int points){
this.points = points;
this.insidePoints = insidePoints;
}
// simulating monte carlo to generate points and check which are inside the circle
public void run(){
int prec = 1000000;
Random rand = new Random();
for( int i=0 ; i < points ; ++i){
double x = (double)rand.nextInt(prec+1)/(double)prec;
double y = (double)rand.nextInt(prec+1)/(double)prec;
if( (x*x + y*y) <= 1){
++insidePoints;
}
}
System.out.println("Thread " + Thread.currentThread().getId() + " running and Inside points are" + insidePoints);
}
public int getCount(){
return this.insidePoints;
}
}
public class A{
public static void main(String[] args){
int totalPoints = 1000000;
int insidePoints = 0;
int threadsToBeUsed = 1;
Scanner scan = new Scanner(System.in);
System.out.println("Enter the value of Threads : ");
threadsToBeUsed = scan.nextInt();
try{
int eachThreadPoints = totalPoints/threadsToBeUsed;
Thread[] thread = new Thread[threadsToBeUsed];
for(int i = 0; i < threadsToBeUsed ; ++i){
if( i == (threadsToBeUsed-1)){
eachThreadPoints += (totalPoints)%eachThreadPoints ;
}
MyThread myT = new MyThread(insidePoints, eachThreadPoints);
thread[i] = new Thread(myT);
thread[i].start();
}
for( int i=0; i < threadsToBeUsed; ++i)
thread[i].join();
System.out.println("Number of inside points :" + insidePoints);
System.out.println("Pi/4 = " + (double)insidePoints/(double)totalPoints);
System.out.println("Pi = " + 4*(double)insidePoints/(double)totalPoints);
} catch(Exception e){
System.out.println(e);
System.exit(1);
}
}
}
作为替代方法,您可以使用Java Executor Interface, which offers a higher-level abstraction than handling the threads explicitly. Moreover, you might consider the use of the ThreadLocalRandom:
A random number generator isolated to the current thread. Like the
global Random generator used by the Math class, a ThreadLocalRandom is
initialized with an internally generated seed that may not otherwise
be modified. When applicable, use of ThreadLocalRandom rather than
shared Random objects in concurrent programs will typically encounter
much less overhead and contention. Use of ThreadLocalRandom is
particularly appropriate when multiple tasks (for example, each a
ForkJoinTask) use random numbers in parallel in thread pools.
回到你的问题:
but I'm not able to return those generated points back from thread to
main function.
您可以利用 Executor
界面并提交 returns a Java Future:
的任务
A Future represents the result of an asynchronous computation. Methods
are provided to check if the computation is complete, to wait for its
completion, and to retrieve the result of the computation. The result
can only be retrieved using method get when the computation has
completed, blocking if necessary until it is ready.
每个线程计算里面的点数和returns那个值作为main 线程。 main 线程依次对其他 threads.
返回的所有值求和
所以在代码方面,我们会创建一个 线程池
ExecutorService pool = Executors.newFixedThreadPool(threadsToBeUsed);
然后是收集结果的列表
List<Future<Integer>> results = new ArrayList<>(threadsToBeUsed);
然后并行提交要完成的工作
for(int i = 0; i < threadsToBeUsed; i++){
Future<Integer> insidePointsThr = pool.submit(new task(eachThreadPoints));
results.add(insidePointsThr);
}
使 main 线程对其他线程的所有结果求和:
int insidePoints = results.stream().mapToInt(f -> f.get()).sum();
打印结果,并关闭 线程池:
pool.shutdown();
一个运行代码示例(基于您提供的代码):
import java.util.*;
import java.util.concurrent.*;
class task implements Callable<Integer> {
final int points;
public task(int points){
this.points = points;
}
@Override
public Integer call() {
int insidePoints = 0;
int prec = 1000000;
for( int i=0 ; i < points ; ++i){
double x = (double)ThreadLocalRandom.current().nextInt(prec + 1)/(double)prec;
double y = (double)ThreadLocalRandom.current().nextInt(prec + 1)/(double)prec;
if( (x*x + y*y) <= 1){
++insidePoints;
}
}
System.out.println("Thread " + Thread.currentThread().getId() + " running and Inside points are " + insidePoints);
return insidePoints;
}
}
class A{
public static void main(String[] args){
int totalPoints = 1000000;
Scanner scan = new Scanner(System.in);
System.out.println("Enter the value of Threads : ");
int threadsToBeUsed = scan.nextInt();
int eachThreadPoints = totalPoints/threadsToBeUsed;
ExecutorService pool = Executors.newFixedThreadPool(threadsToBeUsed);
List<Future<Integer>> results = new ArrayList<>(threadsToBeUsed);
for(int i = 0; i < threadsToBeUsed; i++){
Future<Integer> insidePointsThr = pool.submit(new task(eachThreadPoints));
results.add(insidePointsThr);
}
int insidePoints = results.stream().mapToInt(A::getFutureResult).sum();
System.out.println("Number of inside points :" + insidePoints);
System.out.println("Pi/4 = " + (double)insidePoints/(double)totalPoints);
System.out.println("Pi = " + 4*(double)insidePoints/(double)totalPoints);
pool.shutdown();
}
private static int getFutureResult(Future<Integer> f) {
try {
return f.get();
} catch (InterruptedException | ExecutionException e) {
// handle the error
}
return 0;
}
}
输出(4 个线程):
Enter the value of Threads :
4
Thread 16 running and Inside points are 196447
Thread 17 running and Inside points are 196147
Thread 15 running and Inside points are 196076
Thread 14 running and Inside points are 196795
Number of inside points :785465
Pi/4 = 0.785465
Pi = 3.14186
我一直在尝试并行使用 Monte Carlo 模拟来计算 pi 的值。
到目前为止,我已经创建了线程,并生成了随机点,但是我无法 return 那些生成的点从线程返回到 main 线程。
如何解决这个问题?
下面是我写的代码
import java.util.*;
class MyThread extends Thread{
int points;
int insidePoints;
public MyThread(int insidePoints, int points){
this.points = points;
this.insidePoints = insidePoints;
}
// simulating monte carlo to generate points and check which are inside the circle
public void run(){
int prec = 1000000;
Random rand = new Random();
for( int i=0 ; i < points ; ++i){
double x = (double)rand.nextInt(prec+1)/(double)prec;
double y = (double)rand.nextInt(prec+1)/(double)prec;
if( (x*x + y*y) <= 1){
++insidePoints;
}
}
System.out.println("Thread " + Thread.currentThread().getId() + " running and Inside points are" + insidePoints);
}
public int getCount(){
return this.insidePoints;
}
}
public class A{
public static void main(String[] args){
int totalPoints = 1000000;
int insidePoints = 0;
int threadsToBeUsed = 1;
Scanner scan = new Scanner(System.in);
System.out.println("Enter the value of Threads : ");
threadsToBeUsed = scan.nextInt();
try{
int eachThreadPoints = totalPoints/threadsToBeUsed;
Thread[] thread = new Thread[threadsToBeUsed];
for(int i = 0; i < threadsToBeUsed ; ++i){
if( i == (threadsToBeUsed-1)){
eachThreadPoints += (totalPoints)%eachThreadPoints ;
}
MyThread myT = new MyThread(insidePoints, eachThreadPoints);
thread[i] = new Thread(myT);
thread[i].start();
}
for( int i=0; i < threadsToBeUsed; ++i)
thread[i].join();
System.out.println("Number of inside points :" + insidePoints);
System.out.println("Pi/4 = " + (double)insidePoints/(double)totalPoints);
System.out.println("Pi = " + 4*(double)insidePoints/(double)totalPoints);
} catch(Exception e){
System.out.println(e);
System.exit(1);
}
}
}
作为替代方法,您可以使用Java Executor Interface, which offers a higher-level abstraction than handling the threads explicitly. Moreover, you might consider the use of the ThreadLocalRandom:
A random number generator isolated to the current thread. Like the global Random generator used by the Math class, a ThreadLocalRandom is initialized with an internally generated seed that may not otherwise be modified. When applicable, use of ThreadLocalRandom rather than shared Random objects in concurrent programs will typically encounter much less overhead and contention. Use of ThreadLocalRandom is particularly appropriate when multiple tasks (for example, each a ForkJoinTask) use random numbers in parallel in thread pools.
回到你的问题:
but I'm not able to return those generated points back from thread to main function.
您可以利用 Executor
界面并提交 returns a Java Future:
A Future represents the result of an asynchronous computation. Methods are provided to check if the computation is complete, to wait for its completion, and to retrieve the result of the computation. The result can only be retrieved using method get when the computation has completed, blocking if necessary until it is ready.
每个线程计算里面的点数和returns那个值作为main 线程。 main 线程依次对其他 threads.
返回的所有值求和所以在代码方面,我们会创建一个 线程池
ExecutorService pool = Executors.newFixedThreadPool(threadsToBeUsed);
然后是收集结果的列表
List<Future<Integer>> results = new ArrayList<>(threadsToBeUsed);
然后并行提交要完成的工作
for(int i = 0; i < threadsToBeUsed; i++){
Future<Integer> insidePointsThr = pool.submit(new task(eachThreadPoints));
results.add(insidePointsThr);
}
使 main 线程对其他线程的所有结果求和:
int insidePoints = results.stream().mapToInt(f -> f.get()).sum();
打印结果,并关闭 线程池:
pool.shutdown();
一个运行代码示例(基于您提供的代码):
import java.util.*;
import java.util.concurrent.*;
class task implements Callable<Integer> {
final int points;
public task(int points){
this.points = points;
}
@Override
public Integer call() {
int insidePoints = 0;
int prec = 1000000;
for( int i=0 ; i < points ; ++i){
double x = (double)ThreadLocalRandom.current().nextInt(prec + 1)/(double)prec;
double y = (double)ThreadLocalRandom.current().nextInt(prec + 1)/(double)prec;
if( (x*x + y*y) <= 1){
++insidePoints;
}
}
System.out.println("Thread " + Thread.currentThread().getId() + " running and Inside points are " + insidePoints);
return insidePoints;
}
}
class A{
public static void main(String[] args){
int totalPoints = 1000000;
Scanner scan = new Scanner(System.in);
System.out.println("Enter the value of Threads : ");
int threadsToBeUsed = scan.nextInt();
int eachThreadPoints = totalPoints/threadsToBeUsed;
ExecutorService pool = Executors.newFixedThreadPool(threadsToBeUsed);
List<Future<Integer>> results = new ArrayList<>(threadsToBeUsed);
for(int i = 0; i < threadsToBeUsed; i++){
Future<Integer> insidePointsThr = pool.submit(new task(eachThreadPoints));
results.add(insidePointsThr);
}
int insidePoints = results.stream().mapToInt(A::getFutureResult).sum();
System.out.println("Number of inside points :" + insidePoints);
System.out.println("Pi/4 = " + (double)insidePoints/(double)totalPoints);
System.out.println("Pi = " + 4*(double)insidePoints/(double)totalPoints);
pool.shutdown();
}
private static int getFutureResult(Future<Integer> f) {
try {
return f.get();
} catch (InterruptedException | ExecutionException e) {
// handle the error
}
return 0;
}
}
输出(4 个线程):
Enter the value of Threads :
4
Thread 16 running and Inside points are 196447
Thread 17 running and Inside points are 196147
Thread 15 running and Inside points are 196076
Thread 14 running and Inside points are 196795
Number of inside points :785465
Pi/4 = 0.785465
Pi = 3.14186