invokeAll 如何确切地工作?(ForkJoin)

5
我已经写了下面这段代码:
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);

我看到invokeAll()自动分叉了我传递的两个RecursiveActionTry对象之一。我的笔记本只有2个核心...如果我有4个核心并启动4个任务,invokeAll(right, left, backward, forward);是否会使用所有4个核心?由于我只有2个核心,无法知道。我还想知道,invokeAll(right, left)在幕后是否为第一个参数(right)调用compute(),并为第二个参数(left)调用fork + join(就像递归任务扩展应该是的那样)。否则它不会使用并行处理,对吗?顺便问一下,如果有超过2个参数,它会在第一个参数上调用compute()并在其他所有参数上进行分叉吗?谢谢。
2个回答

5
invokeAll() 调用多个任务,在不同的线程上独立执行。这并不需要为每个线程使用一个不同的核心,但如果可用,则可以允许为每个线程使用不同的核心。详细信息由底层机器处理,但基本上(简化地说),如果可用的线程比核心少,则对线程进行时间片分配,以允许一个线程在一个核心上执行一定时间,然后执行另一个,再执行另一个(循环进行)。
顺便提一下,如果有超过2个参数...它会在第一个参数上调用compute(),并在所有其他参数上调用fork()吗?
它将对所有参数进行compute()操作,然后由compute()方法负责委派和分支,如果未达到工作阈值,则join计算结果。 (将其分成两部分以上是不寻常的- fork join通常通过每个递归根据需要将工作负载分成两部分来工作。)

0
任务和工作线程是不同的东西:
WorkerThreads由ForkJoinPool管理,如果使用默认构造函数,则根据Runtime.getRuntime().availableProcessors()启动WorkerThreads。
任务由您创建/管理。要让多个核心忙碌,必须启动多个任务。您可以将每个任务分成两个部分或N个部分。当一个部分直接执行时,其他部分被放入等待队列中。如果池中的任何其他WorkerThreads处于空闲状态并且没有工作要做,则应该从队列中“窃取”您的分叉挂起任务,并并行执行它们。
为了使8个核心/ WorkerThread忙碌,不需要一次调用8个任务。只需分叉至少两个任务即可,这些任务再次分叉(递归),直到所有WorkerThread饱和为止(假设您的整体问题分裂成那么多子任务)。 因此,如果您拥有更多或更少的核心,则无需调整代码,您的任务也不应担心WorkerThread管理。
最后,invokeAll()或join()在运行所有任务后返回。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接