I am teaching a class on parallel computation and am looking for a simple example that illustrate the speed gains from using “CompletableFuture”s in Java. Currently my example problem is very simple: calculate the sum of an array. Each CompletableFuture calculates the sum of about 1/4 of the array, and when all of them finish, the main program calculates the total sum.
The line “sum += Math.pow(Math.pow(Math.pow(array[i],0.3),0.4),0.5);” was initially just “sum += array[i]”; I added all the “pow”s just to make the serial computation appear longer.
Currently, on my machine with 4 cores, when I put “NUM_OF_THREADS = 1” the sum is calculated in 4 seconds, while with “NUM_OF_THREADS = 4” the sum is calculated in 5.5 seconds, so this is not a good example – it does not show that parallel computation is more efficient.
what should I change in the example, to demonstrate the advantage of parallel computation?
public class ConcurrencyTest { static final int SIZE = 10000000; static final int NUM_OF_THREADS = 1; static int iThread; @SuppressWarnings("unchecked") public static void main(String[] args) throws InterruptedException, ExecutionException { int[] array = new int[NUM_OF_THREADS*SIZE]; Arrays.fill(array, 1); ExecutorService executor = Executors.newCachedThreadPool(); Instant startTime = Instant.now(); CompletableFuture<Integer>[] futures = new CompletableFuture[NUM_OF_THREADS]; for (iThread=0; iThread<NUM_OF_THREADS; ++iThread) { final int iThreadLocal = iThread; futures[iThread] = CompletableFuture.supplyAsync( () -> { int sum=0; int start = iThreadLocal*SIZE; int end = (iThreadLocal+1)*SIZE; for (int i=start; i<end; ++i) { Thread.yield(); sum += Math.pow(Math.pow(Math.pow(array[i],0.3),0.4),0.5); } System.out.println(iThreadLocal+": "+sum + " "+Duration.between(startTime, Instant.now()).toMillis()+" [ms]"); return sum; }, executor); } CompletableFuture.allOf(futures).thenRun( () -> { try { Arrays.stream(new int[] {1,2,3}).sum(); int totalSum = 0; for (iThread=0; iThread<NUM_OF_THREADS; ++iThread) totalSum += futures[iThread].get(); System.out.println("Total: "+totalSum+ " "+Duration.between(startTime, Instant.now()).toMillis()+" [ms]"); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } } ); executor.shutdown(); } }