Buscar
Social
Ofertas laborales ES
« Ganador del concurso Concurso de JavOsize: @jorgezazo | Main | Java 7: leyendo ficheros indicando el encoding »
viernes
ago142015

Java 7, divide y vencerás.

El siguiente ejemplo ejecuta el rellenado de un array de bytes de un tamaño importante de dos maneras:

  1. La primera de ellas, de manera secuencial. Recorre todas las posiciones, y rellena cada una de ellas con un número aleatorio
  2. En la segunda de ellas, realiza el mismo algoritmo en paralelo. Divide el bloque grande en bloques más pequeños, y cada uno de ellos forma parte de una tarea global (comparten memoria, cada uno de ellos tiene conocimientos de su tarea específica...). Se aprovecha entonces, en el caso del que escribe, los dos procesadores del núcleo de la CPU.

Muy interesante este concepto, a tener en cuenta para tareas grandes susceptibles de ser divididas en tareas más pequeñas.

Me recordó un poco al principio inicial de MapReduce (divide una tarea grande en tareas pequeñas.... y vencerás.

La salida, en el caso del que escribe, fue la siguiente:

Sequential processing time: 1683 ms

Sequential processing time: 1662 ms

Number of processor available: 2

Parallel processing time: 930 ms

Parallel processing time: 851 ms

Number of steals: 598

Saludos cordiales y gracias por su atención, como siempre un gusto

01.package com.sprunck.sample;
02. 
03.import static java.util.Arrays.asList;
04. 
05.import java.util.Random;
06.import java.util.concurrent.ForkJoinPool;
07.import java.util.concurrent.RecursiveAction;
08. 
09.public class ForkJoinRandomFillAction {
10.    Random random = new Random();
11. 
12.    public void loadArray(int[] array) {
13.        for (int i = 0; i < array.length; i++) {
14.            array[i] = random.nextInt(10000); // Generates numbers from 0 to
15.                                                // 10000
16.        }
17.    }
18. 
19.    public static void main(String[] args) {
20.        ForkJoinRandomFillAction sort = new ForkJoinRandomFillAction();
21. 
22.        int arrayLength = 1_00_00_0000;
23.        int array[] = new int[arrayLength];
24. 
25.        // No. of times sequential & Parallel operation should be performed to
26.        // warm up HotSpot JVM
27.        final int iterations = 2;
28. 
29.        for (int i = 0; i < iterations; i++) {
30.            long start = System.currentTimeMillis();
31.            sort.loadArray(array);
32. 
33.            System.out.println("Sequential processing time: "
34.                    + (System.currentTimeMillis() - start) + " ms");
35. 
36.        }
37. 
38.        System.out.println("Number of processor available: "
39.                + Runtime.getRuntime().availableProcessors());
40. 
41.        ForkJoinPool fjpool = new ForkJoinPool(64); // Default parallelism level
42.                                                    // =
43.                                                    // Runtime.getRuntime().availableProcessors()
44. 
45.        for (int i = 0; i < iterations; i++) {
46.            // Create a task with the complete array
47.            RecursiveAction task = new RandomFillAction(array, 0, array.length);
48.            long start = System.currentTimeMillis();
49.            fjpool.invoke(task);
50. 
51.            System.out.println("Parallel processing time: "
52.                    + (System.currentTimeMillis() - start) + " ms");
53.        }
54. 
55.        System.out
56.                .println("Number of steals: " + fjpool.getStealCount() + "\n");
57.    }
58.}
59. 
60.class RandomFillAction extends RecursiveAction {
61.    private static final long serialVersionUID = 1L;
62.    final int low;
63.    final int high;
64.    private int[] array;
65.    final int splitSize = 40000; // Some threshold size to spit the task
66. 
67.    public RandomFillAction(int[] array, int low, int high) {
68.        this.low = low;
69.        this.high = high;
70.        this.array = array;
71.    }
72. 
73.    @Override
74.    protected void compute() {
75.        if (high - low > splitSize) {
76.            // task is huge so divide in half
77.            int mid = (low + high) / 2;
78.            invokeAll(asList(new RandomFillAction(array, low, mid),
79.                    new RandomFillAction(array, mid, high)));
80.        } else {
81.            // Some calculation logic
82.            Random random = new Random();
83.            for (int i = low; i < high; i++) {
84.                array[i] = random.nextInt(10000);
85.            }
86.        }
87.    }
88.}

PrintView Printer Friendly Version

EmailEmail Article to Friend

References (1)

References allow you to track sources for this article, as well as articles that were written in response to this article.

Reader Comments (1)

Muy interesante, la verdad que son capacidades que podemos usar en el día a día de la programación pero las ignoramos.

Estas librerías de java.util.concurrent.ForkJoinPool y RecursiveAction sólo están en Java 7 ¿verdad?

Muy útil!!!

agosto 28, 2015 | Registered Commenterantuansoft

PostPost a New Comment

Enter your information below to add a new comment.

My response is on my own website »
Author Email (optional):
Author URL (optional):
Post:
 
Some HTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>