The easiest Parallelism in Java could be achieved by the java.util.stream.Stream utility.
As a good coding exercise, the following Java code will compute the Math PI constant based on the Monte Carlo simulation.
We use Arrays.stream([T]).sequential() or parallel, which will be type of Stream<T> and then can be invoked with .forEach().
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | import java.util.stream.Stream; import java.util.Arrays; import java.time.LocalTime; public class MonteCarloPISimulationUsingParallelForInJava { private final static Object lock = new Object(); private final static int TotalSamples = 10000; private static int total = 0; private static Stream<integer> prepare(int threadNumber) { Integer[] Samples = new Integer[threadNumber]; Arrays.fill(Samples, TotalSamples/threadNumber); if (threadNumber > 1) return Arrays.stream(Samples).parallel(); return Arrays.stream(Samples).sequential(); } public static void main (String[] args) { System.out.println("-------\nRunning sequential\n-------"); run(prepare(1)); System.out.println("-------\nRunning parallel\n-------"); run(prepare(10)); } public static void run (Stream<integer> stream) { long startTime = System.nanoTime(); total = 0; stream.forEach(s -> { // System.out.println(LocalTime.now() + " - value: " + s + " - thread: " + Thread.currentThread().getName()); int n = 0; for (int i = 0; i < s; ++ i) { double x = Math.random(); double y = Math.random(); if (x * x + y * y <= 1) { n ++; // count the points that fall in the circle } } synchronized(lock) { // race condition protection total += n; } }); long endTime = System.nanoTime(); long duration = (endTime - startTime); //divide by 1000000 to get milliseconds. System.out.println((duration / 1000000) + " ms"); System.out.println("PI = " + total * 4.0 / TotalSamples); } } |
import java.util.stream.Stream; import java.util.Arrays; import java.time.LocalTime; public class MonteCarloPISimulationUsingParallelForInJava { private final static Object lock = new Object(); private final static int TotalSamples = 10000; private static int total = 0; private static Stream<integer> prepare(int threadNumber) { Integer[] Samples = new Integer[threadNumber]; Arrays.fill(Samples, TotalSamples/threadNumber); if (threadNumber > 1) return Arrays.stream(Samples).parallel(); return Arrays.stream(Samples).sequential(); } public static void main (String[] args) { System.out.println("-------\nRunning sequential\n-------"); run(prepare(1)); System.out.println("-------\nRunning parallel\n-------"); run(prepare(10)); } public static void run (Stream<integer> stream) { long startTime = System.nanoTime(); total = 0; stream.forEach(s -> { // System.out.println(LocalTime.now() + " - value: " + s + " - thread: " + Thread.currentThread().getName()); int n = 0; for (int i = 0; i < s; ++ i) { double x = Math.random(); double y = Math.random(); if (x * x + y * y <= 1) { n ++; // count the points that fall in the circle } } synchronized(lock) { // race condition protection total += n; } }); long endTime = System.nanoTime(); long duration = (endTime - startTime); //divide by 1000000 to get milliseconds. System.out.println((duration / 1000000) + " ms"); System.out.println("PI = " + total * 4.0 / TotalSamples); } }
Let’s run the code and the parallel version seems slightly faster.
——-
Running sequential
——-
62 ms
PI = 3.1504
——-
Running parallel
——-
10 ms
PI = 3.1092
However, if we slightly change the number of samplings, we might have the opposite results.
——-
Running sequential
——-
122 ms
PI = 3.140424
——-
Running parallel
——-
162 ms
PI = 3.141008
According to StackOverFlow, the Streams parallelism has overheads and we should always start with the .sequential() unless it has performance issues.
The concurrent code has been implemented as an anonymous function. The elements in the Array are processed in parallel. The elements in the array represent the number of the sub-samplings in the above Monte Carlo simulation.
In a concurrent block of code, we need to protect the variable if we want to change the value. In Java, we use the lock to be synchronized.
Monte Carlo Simulation Algorithms to compute the Pi based on Randomness:
- Using Parallel For in Java to Compute PI using Monte Carlo Algorithm
- Monte Carlo solution for Mathematics × Programming Competition #7
- R Programming Tutorial – How to Compute PI using Monte Carlo in R?
- C++ Coding Exercise – Parallel For – Monte Carlo PI Calculation
- Area of the Shadow? – The Monte Carlo Solution in VBScript
- VBScript Coding Exercise – Compute PI using Monte Carlo Random Method
- Computing Approximate Value of PI using Monte Carlo in Python
- How does the 8-bit BASIC perform on Famicom Clone – Subor SB2000 – FBasic – Compute PI approximation using Monte-Carlo method
- GoLang: Compute the Math Pi Value via Monte Carlo Simulation
- BASH Script to Compute the Math.PI constant via Monte Carlo Simulation
–EOF (The Ultimate Computing & Technology Blog) —
loading...
Last Post: 3 Types of Coding Languages That Will Intrigue & Educate Youngsters
Next Post: Bash Command to Find Out the IPs that Hit Your Server