簡體   English   中英

對數組的每個元素進行並行遞歸函數調用(使用ForkJoinPool)

[英]Parallelizing recursive function calls on each element of an array (with ForkJoinPool)

請考慮以下情形:

public void processArray(int a, SomeType array) {
    for (int i = 0; i < array.length; ++i) {
        recFunction(a, array[i]);
    }
}
private void recFunction(int a, SomeType element){
     ...
     recFunction(a + x, element);
     recFunction(a + y, element);
     ...
}

processArray在數組的每個元素上調用recFunction。 如何使用Java創建該程序的並行版本? 請注意,要處理的數組可能非常大(最多10,000個元素)。 我的第一個想法是使用ForkJoinPool,但是我絕對不能為每個數組元素創建RecursiveTask,因為那樣會創建10,000個新對象。

另外,我將不得不處理不同的數組,因此必須多次調用processArray。 我想避免每次都創建新線程並使用現有線程。 有什么想法可以使用Executor或ForkJoinPool實現嗎?

這是一個快速排序的示例,無論如何都不是最佳選擇,但應為您與遞歸版本進行比較提供基礎。

import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveAction;

public class ParallelSort {
    // default, Creates a ForkJoinPool with parallelism equal to Runtime.availableProcessors()
    private ForkJoinPool pool = new ForkJoinPool();

    public void sort(int[] elements) {
        pool.invoke(new SortAction(elements, 0, elements.length-1));
    }

    public class SortAction extends RecursiveAction {
        private static final long serialVersionUID = 3060427288506544983L;

        final int[] elements;
        int low;
        int high;

        SortAction(int[] elements, int low, int high) {
            this.elements = elements;
            this.low = low;
            this.high = high;
        }

        protected void compute() {
            if (low < high) {
                int pivotIndex = (low + high) >>> 1;
                pivotIndex = partition(pivotIndex);

                invokeAll(new SortAction(elements, low, pivotIndex - 1),
                          new SortAction(elements, pivotIndex + 1, high));
            }
        }

        private int partition(int pivotIndex) {
            int pivotValue = elements[pivotIndex];

            swap(elements, pivotIndex, high);
            int storeIndex = low;

            for (int i = low; i < high; i++) {
                if (elements[i] < pivotValue) {
                    swap(elements, i, storeIndex);
                    storeIndex++;
                }
            }

            swap(elements, storeIndex, high);
            return storeIndex;
        }

        private void swap(int[] elements, int i, int j) {
            if (i != j) {
                int temp = elements[i];
                elements[i] = elements[j];
                elements[j] = temp;
            }
        }
    }
}

快速注意事項:

  • 不需要來聲明排序類中的ForkJoinPool,我只是做了在這里所以調用者不必去想池。

  • 如果分區大小很小,這種快速排序如果回落到串行排序,則性能會更好。 我在這里沒有打擾。

在數百萬個元素上運行都沒有問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM