[英]How to use ForkJoinPool to use multiple cores in java?
So I am trying to understand about how ForkJoinPool works.所以我试图了解 ForkJoinPool 是如何工作的。 I am trying to achieve better performance using this for a large array of about 2 million elements and then adding their reciprocal.
我试图使用它来获得更好的性能,用于大约 200 万个元素的大型数组,然后添加它们的倒数。 I understand that ForkJoinPool.commpnPool().invoke(task);
我知道 ForkJoinPool.commpnPool().invoke(task); calls compute() which forks the task in two tasks if it is not smaller and then computes and then joins them.
调用计算(),如果任务不小,则将任务分叉为两个任务,然后计算然后加入它们。 So far, we are using two cores.
到目前为止,我们使用了两个内核。
But if I want to xecute this on multiple cores, how do I do that and achieve 4 times better performance than the usual single thread run?但是,如果我想在多个内核上执行此操作,我该如何做到这一点并获得比通常的单线程运行高 4 倍的性能? Below is my code for default ForkJoinPool():
下面是我的默认 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();
}
You want to use 4 cores but you are giving a job which will need only two cores.您想使用 4 个内核,但您提供的工作只需要两个内核。 In the following example, getChunkStartInclusive and getChunkEndExclusive methods give the range for beginning and ending indexes of each chunk.
在以下示例中,getChunkStartInclusive 和 getChunkEndExclusive 方法给出了每个块的开始和结束索引的范围。 I believe the following code can solve your problem and give you some implementation idea.
我相信以下代码可以解决您的问题,并为您提供一些实现思路。
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;
}
This is my approach:这是我的方法:
Threshold is the limit when the compute starts to calculate and stops to stack recursive calls, this works better if each processor is used twice or more (there is a limit of course), that's because I use numTask * 2
.阈值是计算开始计算和停止堆栈递归调用时的限制,如果每个处理器使用两次或更多次(当然有限制),这会
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.