2011-07-25 8 views
5

¿Cuál es la forma más sencilla de implementar un cálculo paralelo (por ejemplo, en un procesador central múltiple) utilizando Java. I.E. java equivalente a este código Scala¿Hay algo en Java cerca de las colecciones paralelas en Scala?

val list = aLargeList 
list.par.map(_*2) 

Hay this library, pero parece abrumadora.

+0

Desafortunadamente, Java = Scala –

+0

De acuerdo con la ecuación. Es cierto que Java es un * lenguaje * sensato))) Por ejemplo, de la pregunta de snappy a la respuesta a continuación en menos de unos pocos minutos leyendo el código fuente jsr (y la primera vez que mira este jsr). Java es * eminentemente legible *, y gracias a Dios por eso. – alphazero

+5

También hay [esta biblioteca] (http://www.scala-lang.org/api/current/index.html) para la JVM. ;) –

Respuesta

7

http://gee.cs.oswego.edu/dl/jsr166/dist/extra166ydocs/

No se rinda tan rápido, ágil!))

From the javadocs (con cambios para mapear a su f) la cuestión esencial es en realidad sólo esto:

ParallelLongArray a = ... // you provide 
a.replaceWithMapping (new LongOp() { public long op(long a){return a*2L;}};); 

es más o menos esto, ¿verdad?

val list = aLargeList 
list.par.map(_*2) 

& Si usted está dispuesto a vivir con un poco menos concisión, lo anterior puede ser una razonablemente limpia y clara 3 forro (y, por supuesto, si vuelve a utilizar las funciones, entonces es exactamente lo mismo como Scala - funciones en línea):.

ParallelLongArray a = ... // you provide 
LongOp f = new LongOp() { public long op(long a){return a*2L;}}; 
a.replaceWithMapping (f); 

[editado por encima de mostrar la forma completa concisa ala variante Scala de OP]

y aquí está en forma prolija máxima donde empezamos desde cero para la demostración:

import java.util.Random; 
import jsr166y.ForkJoinPool; 
import extra166y.Ops.LongGenerator; 
import extra166y.Ops.LongOp; 
import extra166y.ParallelLongArray; 

public class ListParUnaryFunc { 
    public static void main(String[] args) { 

     int n = Integer.parseInt(args[0]); 
     // create a parallel long array 
     // with random long values 
     ParallelLongArray a = ParallelLongArray.create(n-1, new ForkJoinPool()); 
     a.replaceWithGeneratedValue(generator); 

     // use it: apply unaryLongFuncOp in parallel 
     //   to all values in array 
     a.replaceWithMapping(unaryLongFuncOp); 

     // examine it 
     for(Long v : a.asList()){ 
      System.out.format("%d\n", v); 
     } 
    } 

    static final Random rand = new Random(System.nanoTime()); 
    static LongGenerator generator = new LongGenerator() { 
     @Override final 
     public long op() { return rand.nextLong(); } 
    }; 

    static LongOp unaryLongFuncOp = new LongOp() { 
     @Override final public long op(long a) { return a * 2L; } 
    }; 
} 

final Edit y notas:

También tenga en cuenta que una clase simple como la siguiente (que se puede reutilizar a través de sus proyectos):

/** 
* The very basic form w/ TODOs on checks, concurrency issues, init, etc. 
*/ 
final public static class ParArray { 
    private ParallelLongArray parr; 
    private final long[] arr; 
    public ParArray (long[] arr){ 
     this.arr = arr; 
    } 
    public final ParArray par() { 
     if(parr == null) 
      parr = ParallelLongArray.createFromCopy(arr, new ForkJoinPool()) ; 
     return this; 
    } 
    public final ParallelLongArray map(LongOp op) { 
     return parr.replaceWithMapping(op); 
    } 
    public final long[] values() { return parr.getArray(); } 
} 

y algo así como que le permitirá escribir código Java sea más fluida (si concisión importa a usted):

long[] arr = ... // you provide 
LongOp f = ... // you provide 

ParArray list = new ParArray(arr); 
list.par().map(f); 

Y el enfoque anterior sin duda puede ser empujado para que sea aún más limpio.

0

Usando hilos, Java no tiene este tipo de cosas incorporadas.

1

Hacer eso en una máquina es bastante fácil, pero no tan fácil como lo hace Scala. Esa biblioteca que ha publicado ya está separada de Java 5 y más allá. Probablemente lo más simple de usar es un ExecutorService. Eso representa una serie de subprocesos que se pueden ejecutar en cualquier procesador. Usted le envía tareas y esas cosas devuelven resultados.

http://download.oracle.com/javase/1,5.0/docs/api/java/util/concurrent/ThreadPoolExecutor.html

http://www.fromdev.com/2009/06/how-can-i-leverage-javautilconcurrent.html

me gustaría sugerir el uso de ExecutorService.invokeAll() que devolverá una lista de futuros. Luego puedes verificarlos para ver si están listos.

Si está utilizando Java7, entonces podría usar el marco fork/join que podría ahorrarle algo de trabajo. Con todo esto puedes construir algo muy similar a las matrices paralelas de Scala, por lo que su uso es bastante conciso.

Cuestiones relacionadas