invokeAll how it exactly work? (ForkJoin)
Asked Answered
W

2

6

I have written the following snippet:

static private int counter;

    public void compute()
    {
        if (array.length<=500)
        {

            for(int i = 0;i<array.length;i++){
                counter++;
                System.out.println("Ciao this is a recursive action number"+ counter+Thread.currentThread().getName()); 
            }
        }
        else{
        int split = array.length/2;
        RecursiveActionTry right = new RecursiveActionTry(split);
        RecursiveActionTry left = new RecursiveActionTry(split);
        invokeAll(right, left);

I see that invokeAll() automatically fork one of the two RecursiveActionTry object I pass to. My laptop has only 2 cores.. what if I had 4 cores and launched 4 tasks... invokeAll(right, left, backward, forward); would I use all the 4 cores? Cannot know as I have only 2 cores.

I would like also to know if invokeAll(right, left) behind the scenes call compute() for the first argument(right) and fork + join for the second argument (left). (as in a RecursiveTask extension is supposed to be). Otherwise it would not use parallelism, would it? And by the way, if there are more than 2 arguments.. does it call compute() on the first and fork on all the others?

Thanks in advance.

Whence answered 3/6, 2013 at 11:52 Comment(0)
S
5

invokeAll() calls a number of tasks which execute independently on different threads. This does not necessitate the use of a different core for each thread, but it can allow the use of a different core for each thread if they are available. The details are handled by the underlying machine, but essentially (simplistically) if fewer cores are available than threads it time slices the threads so as to allow one to execute on one core for a certain amount of time, then the other, then another (in a loop.)

And by the way, if there are more than 2 arguments.. does it call compute() on the first and fork on all the others?

It would compute() all the arguments, it's then the responsibility of the compute() method to delegate and fork if the worker threshold is not met, then join the computations when copmlete. (Splitting it more than two ways is unusual though - fork join usually works by each recursion splitting the workload in two if necessary.)

Smackdab answered 3/6, 2013 at 12:16 Comment(0)
V
0

The tasks and the worker threads are different things:

WorkerThreads are managed by the ForkJoinPool and if you use the default constructor it starts WorkerThreads according toRuntime.getRuntime().availableProcessors().

Task however are created/managed by you. To get multiple cores busy you must start several tasks. You may either split each into two parts or into N parts. While one part is executed directly, the other one(s) are put into a waiting queue. If any other WorkerThreads from the pool are idle and have no work to do, those are supposed to "steal" your forked pending task(s) from the queue and execute them in parallel.

To get 8 cores / WorkerThread busy it is not necessary to invoke 8 tasks at once. It will be sufficient to fork at least into two task which also fork again (recursively), until all WorkerThread get saturated (supposed your overall problem splits into that many subtasks). So, there is no need to adapt your code if you have more or less cores, and your Task should not worry about WorkerThread management at all.

Finally invokeAll() or join() returns after all tasks have been run.

Vulgate answered 5/6, 2013 at 12:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.