sábado, 15 de diciembre de 2007

Java 1.5/1.6 es Multi-core, ejemplo

Se dijo anteriormente que Java es multi-core, para probar esta aseveración primeramente vamos a definir una tarea que pueda se corrida en paralelo, el siguiente código es simplemente la definición de esta tarea que no tiene nada de extraño en cuanto a la programación multi-thread:

  1  package multicore;
  2  
  3  public class ParallelTask implements Runnable {
  4  
  5     double result = 0 ;
  6  
  7     double taskNo = Math.random()*100 ;
  8  
  9     public void run() {
 10         System.out.println("Starting task No " + Math.floor(taskNo)) ;
 11        
 12         for(int i=0;i<20000000;i++)
 13             result = Math.sin(i) ;
 14         System.out.println("finishing task No " + Math.floor(taskNo)) ;
 15     }
 16  }

Al ser ejecutada la tarea (run) se efectuará la operación trigonométrica seno, unos 20 millones de veces. La idea es esta tarea sea lo suficientemente larga para detectar varias instancias de esta clase ejecutándose en paralelo.

El siguiente código, nuevo para las versiones 1.5 y posteriores, efectivamente crea 6 tareas (pt1, pt2, ...) y las ejecuta en paralelo.

  1  package multicore;
  2 
  3  import java.util.concurrent.Executors ;
  4  import java.util.concurrent.ExecutorService ;
  5 
  6  public class Main {
  7  
  8     public static void main(String[] args) {
  9  
 10         ParallelTask pt1 =new ParallelTask() ;
 11         ParallelTask pt2 =new ParallelTask() ;
 12         ParallelTask pt3 =new ParallelTask() ;
 13         ParallelTask pt4 =new ParallelTask() ;
 14         ParallelTask pt5 =new ParallelTask() ;
 15         ParallelTask pt6 =new ParallelTask() ;
 16 
 17         ExecutorService es =  Executors.newFixedThreadPool(4) ;
 18 
 19         es.execute(pt1) ;
 20         es.execute(pt2) ;
 21         es.execute(pt3) ;
 22         es.execute(pt4) ;
 23         es.execute(pt5) ;
 24         es.execute(pt6) ;
 25 
 26         es.shutdown() ;
 27     } 
 28  
 29  }

Para ejecutar en paralelo primeramente se define el número de cores (newFixedThreadPool(4)), en este caso estamos definiendo 4 cores, si se definen menos cores entonces la aplicación se ejecutará únicamente es ese número de cores quedando los restantes disponibles. Si se definen más de los existentes, algunas tareas simularán multiprocesamiento.

En este caso se han definidos más tareas que cores, en tal caso las tares que “no alcancen en la camioneta” esperarán a que uno de los cores quede dispoble.

La pregunta natural es: ¿como me aseguro que utilizo todos los cores?, yo prefiero utilizar el utilitario “no oficial” de unix/linux “mpstat”. El siguiente es un ejemplo de utilización

$ mpstat -P ALL 10 3

Este comando dará un resumen del desempeño de cada core (CPU), 3 veces cada 10 segundos.