[英]How to use ForkJoinPool to use multiple cores in java?
所以我試圖了解 ForkJoinPool 是如何工作的。 我試圖使用它來獲得更好的性能,用於大約 200 萬個元素的大型數組,然后添加它們的倒數。 我知道 ForkJoinPool.commpnPool().invoke(task); 調用計算(),如果任務不小,則將任務分叉為兩個任務,然后計算然后加入它們。 到目前為止,我們使用了兩個內核。
但是,如果我想在多個內核上執行此操作,我該如何做到這一點並獲得比通常的單線程運行高 4 倍的性能? 下面是我的默認 ForkJoinPool() 代碼:
@Override
protected void compute() {
// TODO
if (endIndexExclusive - startIndexInclusive <= seq_count) {
for (int i = startIndexInclusive; i < endIndexExclusive; i++)
value += 1 / input[i];
} else {
ReciprocalArraySumTask left = new ReciprocalArraySumTask(startIndexInclusive,
(endIndexExclusive + startIndexInclusive) / 2, input);
ReciprocalArraySumTask right = new ReciprocalArraySumTask((endIndexExclusive + startIndexInclusive) / 2,
endIndexExclusive, input);
left.fork();
right.compute();
left.join();
value = left.value + right.value;
}
}
}
protected static double parArraySum(final double[] input) {
assert input.length % 2 == 0;
double sum = 0;
// Compute sum of reciprocals of array elements
ReciprocalArraySumTask task = new ReciprocalArraySumTask(0, input.length, input);
ForkJoinPool.commonPool().invoke(task);
return task.getValue();
}
//Here I am trying to achieve with 4 cores
protected static double parManyTaskArraySum(final double[] input,
final int numTasks) {
double sum = 0;
System.out.println("Total tasks = " + numTasks);
System.setProperty("java.util.concurrent.ForkJoinPool.common.parallelism", String.valueOf(numTasks));
// Compute sum of reciprocals of array elements
int chunkSize = ReciprocalArraySum.getChunkSize(numTasks, input.length);
System.out.println("Chunk size = " + chunkSize);
ReciprocalArraySumTask task = new ReciprocalArraySumTask(0, input.length, input);
ForkJoinPool pool = new ForkJoinPool();
// pool.
ForkJoinPool.commonPool().invoke(task);
return task.getValue();
}
您想使用 4 個內核,但您提供的工作只需要兩個內核。 在以下示例中,getChunkStartInclusive 和 getChunkEndExclusive 方法給出了每個塊的開始和結束索引的范圍。 我相信以下代碼可以解決您的問題,並為您提供一些實現思路。
protected static double parManyTaskArraySum(final double[] input,
final int numTasks) {
double sum = 0;
System.setProperty("java.util.concurrent.ForkJoinPool.common.parallelism", String.valueOf(numTasks));
List<ReciprocalArraySumTask> ts = new ArrayList<ReciprocalArraySumTask>(numTasks);
int i;
for (i = 0; i < numTasks - 1 ; i++) {
ts.add(new ReciprocalArraySumTask(getChunkStartInclusive(i,numTasks,input.length),getChunkEndExclusive(i,numTasks,input.length),input));
ts.get(i).fork();
}
ts.add( new ReciprocalArraySumTask(getChunkStartInclusive(i, numTasks, input.length), getChunkEndExclusive(i, numTasks, input.length), input));
ts.get(i).compute();
for (int j = 0; j < numTasks - 1; j++) {
ts.get(j).join();
}
for (int j = 0; j < numTasks; j++) {
sum += ts.get(j).getValue();
}
return sum;
}
這是我的方法:
閾值是計算開始計算和停止堆棧遞歸調用時的限制,如果每個處理器使用兩次或更多次(當然有限制),這會numTask * 2
,那是因為我使用numTask * 2
。
protected static double parManyTaskArraySum(final double[] input, final int numTasks) { int start; int end; int size = input.length; int threshold = size / (numTasks * 2); List<ReciprocalArraySumTask> actions = new ArrayList<>(); for (int i = 0; i < numTasks; i++) { start = getChunkStartInclusive(i, numTasks, size); end = getChunkEndExclusive(i, numTasks, size); actions.add(new ReciprocalArraySumTask(start, end, input, threshold, I)); } ForkJoinTask.invokeAll(actions); return actions.stream().map(ReciprocalArraySumTask::getValue).reduce(new Double(0), Double::sum); }
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.