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

package com.sprunck.sample;

import static java.util.Arrays.asList;

import java.util.Random;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveAction;

public class ForkJoinRandomFillAction {
	Random random = new Random();

	public void loadArray(int[] array) {
		for (int i = 0; i < array.length; i++) {
			array[i] = random.nextInt(10000); // Generates numbers from 0 to
												// 10000
		}
	}

	public static void main(String[] args) {
		ForkJoinRandomFillAction sort = new ForkJoinRandomFillAction();

		int arrayLength = 1_00_00_0000;
		int array[] = new int[arrayLength];

		// No. of times sequential & Parallel operation should be performed to
		// warm up HotSpot JVM
		final int iterations = 2;

		for (int i = 0; i < iterations; i++) {
			long start = System.currentTimeMillis();
			sort.loadArray(array);

			System.out.println("Sequential processing time: "
					+ (System.currentTimeMillis() - start) + " ms");

		}

		System.out.println("Number of processor available: "
				+ Runtime.getRuntime().availableProcessors());

		ForkJoinPool fjpool = new ForkJoinPool(64); // Default parallelism level
													// =
													// Runtime.getRuntime().availableProcessors()

		for (int i = 0; i < iterations; i++) {
			// Create a task with the complete array
			RecursiveAction task = new RandomFillAction(array, 0, array.length);
			long start = System.currentTimeMillis();
			fjpool.invoke(task);

			System.out.println("Parallel processing time: "
					+ (System.currentTimeMillis() - start) + " ms");
		}

		System.out
				.println("Number of steals: " + fjpool.getStealCount() + "\n");
	}
}

class RandomFillAction extends RecursiveAction {
	private static final long serialVersionUID = 1L;
	final int low;
	final int high;
	private int[] array;
	final int splitSize = 40000; // Some threshold size to spit the task

	public RandomFillAction(int[] array, int low, int high) {
		this.low = low;
		this.high = high;
		this.array = array;
	}

	@Override
	protected void compute() {
		if (high - low > splitSize) {
			// task is huge so divide in half
			int mid = (low + high) / 2;
			invokeAll(asList(new RandomFillAction(array, low, mid),
					new RandomFillAction(array, mid, high)));
		} else {
			// Some calculation logic
			Random random = new Random();
			for (int i = low; i < high; i++) {
				array[i] = random.nextInt(10000);
			}
		}
	}
}

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>