Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there anything in Java close to the parallel collections in Scala?

What is the simplest way to implement a parallel computation (e.g. on a multiple core processor) using Java. I.E. the java equivalent to this Scala code

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

There is this library, but it seems overwhelming.

like image 341
snappy Avatar asked Jul 25 '11 18:07

snappy


People also ask

Why do we use parallel collection classes in Scala?

Parallel collections were included in the Scala standard library in an effort to facilitate parallel programming by sparing users from low-level parallelization details, meanwhile providing them with a familiar and simple high-level abstraction.

Is Scala parallel programming?

Scala programming language already brings us a collection to quickly implement parallel computing, the Parallel Collections. In this tutorial, we'll check out some concepts of parallelism with Scala and the usage of parallel collections.


2 Answers

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

Don't give up so fast, snappy! ))

From the javadocs (with changes to map to your f) the essential matter is really just this:

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

is pretty much this, right?

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

& If you are willing to live with a bit less terseness, the above can be a reasonably clean and clear 3 liner (and of course, if you reuse functions, then its the same exact thing as Scala - inline functions.):

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

[edited above to show concise complete form ala OP's Scala variant]

and here it is in maximal verbose form where we start from scratch for demo:

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 and notes:

Also note that a simple class such as the following (which you can reuse across your projects):

/**
 * 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(); }
}

and something like that will allow you to write more fluid Java code (if terseness matters to you):

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

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

And the above approach can certainly be pushed to make it even cleaner.

like image 70
alphazero Avatar answered Nov 15 '22 00:11

alphazero


Doing that on one machine is pretty easy, but not as easy as Scala makes it. That library you posted is already apart of Java 5 and beyond. Probably the simplest thing to use is a ExecutorService. That represents a series of threads that can be run on any processor. You send it tasks and those things return results.

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

I'd suggest using ExecutorService.invokeAll() which will return a list of Futures. Then you can check them to see if their done.

If you're using Java7 then you could use the fork/join framework which might save you some work. With all of these you can build something very similar to Scala parallel arrays so using it is fairly concise.

like image 36
chubbsondubs Avatar answered Nov 14 '22 23:11

chubbsondubs