爲了確保線程具有「相似」的工作負載,找到均勻的分佈很重要。當線程數量與元素數量相比「高」時,這一點尤爲重要。對於這種情況,應該確保線程負責的元素數相差至多1。
爲了達到這個目的,你可以計算除以元素數量(在你的情況下數組長度)除以線程數量的餘數,並在任務中逐個分配這個餘數。
前段時間我有同樣的問題。實際上,我試圖以稍微更一般的形式解決它,對於某些類需要計算開始和結束任意範圍的間隔的指數(其不需要以索引0
)。下面從這個類是「提取」:
import java.util.Arrays;
public class EvenTaskDistribution
{
public static void main(String[] args)
{
test(22, 4);
test(21, 4);
test(100, 3);
test( 3, 4);
}
private static void test(int numElements, int parallelism)
{
int taskSizes[] = computeTaskSizes(parallelism, 0, numElements);
System.out.printf("Distributing %4d elements among %4d threads: %s\n",
numElements, parallelism, Arrays.toString(taskSizes));
}
public static int[] computeTaskSizes(
int parallelism, int globalMin, int globalMax)
{
if (parallelism <= 0)
{
throw new IllegalArgumentException(
"Parallelism must be positive, but is " + parallelism);
}
if (globalMin > globalMax)
{
throw new IllegalArgumentException(
"The global minimum may not be larger than the global " +
"maximum. Global minimum is "+globalMin+", " +
"global maximum is "+globalMax);
}
int range = globalMax - globalMin;
if (range == 0)
{
return new int[0];
}
int numTasks = Math.min(range, parallelism);
int localRange = (range - 1)/numTasks + 1;
int spare = localRange * numTasks - range;
int currentIndex = globalMin;
int taskSizes[] = new int[numTasks];
for (int i = 0; i < numTasks; i++)
{
final int min = currentIndex;
final int max = min + localRange - (i < spare ? 1 : 0);
taskSizes[i] = max - min;
currentIndex = max;
}
return taskSizes;
}
}
輸出是
Distributing 22 elements among 4 threads: [5, 5, 6, 6]
Distributing 21 elements among 4 threads: [5, 5, 5, 6]
Distributing 100 elements among 3 threads: [33, 33, 34]
Distributing 3 elements among 4 threads: [1, 1, 1]
(最後一個顯示的極端案例一個一個可能要考慮到例如,一個可能。期望[1,1,1,0]
,但這可以根據應用情況輕鬆調整)。
事實上,你這樣做是爲了在線程之間分割工作,這在很大程度上是不相關的 - 你似乎在問如何將一個數組分割成N個大致相同大小的塊。 –