/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package parallelnbody; import java.awt.Color; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.util.Locale; import java.util.Scanner; /** * * @author alefrag */ public class ParallelNBody { //Set value to simulate seconds of the bodies static final int execTime = 100; static final boolean draw = false; public static void main(String[] args) throws FileNotFoundException { //Make sure we are at the correct format for input PA Locale.setDefault(new Locale("en", "US")); //Allow for reading from args[0] PA String fname = args[0]; int numThreads = 1; // default if (args.length > 1) { try { numThreads = Integer.parseInt(args[1]); if (numThreads < 1) numThreads = 1; } catch (NumberFormatException e) { numThreads = 1; } } java.util.concurrent.ExecutorService executor = java.util.concurrent.Executors.newFixedThreadPool(numThreads); FileInputStream is = new FileInputStream(new File(fname)); System.setIn(is); Scanner console = new Scanner(System.in); final double dt = 0.1; // time quantum int N = console.nextInt(); // number of particles double radius = console.nextDouble(); // radius of universe // turn on animation mode and rescale coordinate system PA if (draw) { StdDraw.show(0); StdDraw.setXscale(-radius, +radius); StdDraw.setYscale(-radius, +radius); } // read in and initialize bodies Body[] bodies = new Body[N]; // array of N bodies for (int i = 0; i < N; i++) { double px = console.nextDouble(); double py = console.nextDouble(); double vx = console.nextDouble(); double vy = console.nextDouble(); double mass = console.nextDouble(); int red = console.nextInt(); int green = console.nextInt(); int blue = console.nextInt(); Color color = new Color(red, green, blue); bodies[i] = new Body(px, py, vx, vy, mass, color); } // Store time after IO long startTime = System.nanoTime(); // simulate the universe for (double t = 0.0; t < execTime; t = t + dt) { Quad quad = new Quad(0, 0, radius * 2); BHTree tree = new BHTree(quad); // build the Barnes-Hut tree (serial) for (int i = 0; i < N; i++) { if (bodies[i].in(quad)) { tree.insert(bodies[i]); } } // parallel update: χωρίζουμε τα bodies σε chunks, ένα Runnable ανά thread java.util.List> tasks = new java.util.ArrayList<>(numThreads); final int chunkSize = (N + numThreads - 1) / numThreads; // ceil for (int ti = 0; ti < numThreads; ti++) { final int start = ti * chunkSize; final int end = Math.min(N, start + chunkSize); tasks.add(new java.util.concurrent.Callable() { @Override public Void call() throws Exception { for (int i = start; i < end; i++) { bodies[i].resetForce(); tree.updateForce(bodies[i]); // read-only on tree bodies[i].update(dt); } return null; } }); } try { // invokeAll θα μπλοκάρει μέχρι να ολοκληρωθούν όλα τα tasks executor.invokeAll(tasks); } catch (InterruptedException ex) { Thread.currentThread().interrupt(); break; } // If draw is enabled update picture if (draw) { StdDraw.clear(StdDraw.BLACK); for (int i = 0; i < N; i++) { bodies[i].draw(); } StdDraw.show(0); } } //Terminating the executor executor.shutdown(); try { if (!executor.awaitTermination(5, java.util.concurrent.TimeUnit.SECONDS)) { executor.shutdownNow(); } } catch (InterruptedException ex) { executor.shutdownNow(); Thread.currentThread().interrupt(); } //Print execution time and exit long endTime = System.nanoTime(); long totalTime = endTime - startTime; System.out.println("Simulation time: " + ((double) totalTime) / 1E9); System.exit(0); } }