我实现了小测试,一次使用Arrays.sort,一次使用基于@ypnos 在https://stackoverflow.com/a/22688819 中引用的排序网络的自己的排序实现。
但是,不要把这个比较看得太严肃。这不是一个非常复杂的微基准,当然还有很多影响因素还没有考虑。我想到的一个是:12 个元素的段是线性排序的吗?也就是说,您是先对元素进行排序 [0,12),然后是 [12,24),依此类推,还是这些段分散在数组中?由于缓存,这可能会对性能产生影响。这种影响可能对所有方法都相同,但仍应予以考虑。
无论如何,使用这种排序网络(或一般的“展开”排序方法)似乎可以挤出一点性能。
但只是为了比较,我添加了一种并行方法,其中对 12 元素段集进行排序的任务分布在所有可用内核中,并且似乎可以通过这种方式实现显着的加速。因此,一般来说,您可能应该考虑对该任务进行某种并行化。
(以-Xmx2000m 开头,以便为大型数组提供足够的内存)
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class SmallSortTest
{
public static void main(String[] args)
{
Random random = new Random(0);
for (int size=8000000; size<=8000000*10; size+=8000000)
{
int array[] = createRandomArray(size, 0, 1000, random);
int array0[] = array.clone();
testArrays(array0);
int array1[] = array.clone();
testOwn(array1);
int array2[] = array.clone();
testParallel(array2);
if (!Arrays.equals(array0, array1)) System.out.println("Error");
if (!Arrays.equals(array0, array2)) System.out.println("Error");
}
}
private static void testArrays(int array[])
{
long before = System.nanoTime();
for (int i=0; i<array.length/12; i++)
{
Arrays.sort(array, i*12, i*12+12);
}
long after = System.nanoTime();
System.out.println(
"Arrays size "+array.length+
" duration "+(after-before)*1e-6+
", some result "+array[array.length/2]);
}
private static void testOwn(int array[])
{
long before = System.nanoTime();
for (int i=0; i<array.length/12; i++)
{
sort(array, i*12);
}
long after = System.nanoTime();
System.out.println(
"Own size "+array.length+
" duration "+(after-before)*1e-6+
", some result "+array[array.length/2]);
}
private static void testParallel(final int array[])
{
int n = Runtime.getRuntime().availableProcessors();
ExecutorService executor = Executors.newFixedThreadPool(n);
int batchSize = (int)Math.ceil((double)array.length / 12 / n);
final List<Callable<Object>> tasks = new ArrayList<Callable<Object>>();
for (int i=0; i<n; i++)
{
final int minIndex = (i+0)*batchSize;
final int maxIndex = Math.min(array.length, (i+1)*batchSize);
Runnable runnable = new Runnable()
{
@Override
public void run()
{
for (int i=minIndex; i<maxIndex; i++)
{
Arrays.sort(array, i*12, i*12+12);
}
}
};
tasks.add(Executors.callable(runnable));
}
long before = System.nanoTime();
try
{
executor.invokeAll(tasks);
}
catch (InterruptedException e1)
{
Thread.currentThread().interrupt();
}
long after = System.nanoTime();
executor.shutdown();
try
{
executor.awaitTermination(5, TimeUnit.SECONDS);
}
catch (InterruptedException e)
{
Thread.currentThread().interrupt();
}
System.out.println(
"Parallel size "+array.length+
" duration "+(after-before)*1e-6+
", some result "+array[array.length/2]);
}
private static void sort(int array[], int startIndex)
{
int i0 = startIndex+11;
int i1 = startIndex+10;
int i2 = startIndex+9;
int i3 = startIndex+8;
int i4 = startIndex+7;
int i5 = startIndex+6;
int i6 = startIndex+5;
int i7 = startIndex+4;
int i8 = startIndex+3;
int i9 = startIndex+2;
int i10 = startIndex+1;
int i11 = startIndex+0;
if (array[i0] < array[i1]) swap(array, i0, i1);
if (array[i2] < array[i3]) swap(array, i2, i3);
if (array[i4] < array[i5]) swap(array, i4, i5);
if (array[i6] < array[i7]) swap(array, i6, i7);
if (array[i8] < array[i9]) swap(array, i8, i9);
if (array[i10] < array[i11]) swap(array, i10, i11);
if (array[i1] < array[i3]) swap(array, i1, i3);
if (array[i5] < array[i7]) swap(array, i5, i7);
if (array[i9] < array[i11]) swap(array, i9, i11);
if (array[i0] < array[i2]) swap(array, i0, i2);
if (array[i4] < array[i6]) swap(array, i4, i6);
if (array[i8] < array[i10]) swap(array, i8, i10);
if (array[i1] < array[i2]) swap(array, i1, i2);
if (array[i5] < array[i6]) swap(array, i5, i6);
if (array[i9] < array[i10]) swap(array, i9, i10);
if (array[i0] < array[i4]) swap(array, i0, i4);
if (array[i7] < array[i11]) swap(array, i7, i11);
if (array[i1] < array[i5]) swap(array, i1, i5);
if (array[i6] < array[i10]) swap(array, i6, i10);
if (array[i3] < array[i7]) swap(array, i3, i7);
if (array[i4] < array[i8]) swap(array, i4, i8);
if (array[i5] < array[i9]) swap(array, i5, i9);
if (array[i2] < array[i6]) swap(array, i2, i6);
if (array[i0] < array[i4]) swap(array, i0, i4);
if (array[i7] < array[i11]) swap(array, i7, i11);
if (array[i3] < array[i8]) swap(array, i3, i8);
if (array[i1] < array[i5]) swap(array, i1, i5);
if (array[i6] < array[i10]) swap(array, i6, i10);
if (array[i2] < array[i3]) swap(array, i2, i3);
if (array[i8] < array[i9]) swap(array, i8, i9);
if (array[i1] < array[i4]) swap(array, i1, i4);
if (array[i7] < array[i10]) swap(array, i7, i10);
if (array[i3] < array[i5]) swap(array, i3, i5);
if (array[i6] < array[i8]) swap(array, i6, i8);
if (array[i2] < array[i4]) swap(array, i2, i4);
if (array[i7] < array[i9]) swap(array, i7, i9);
if (array[i5] < array[i6]) swap(array, i5, i6);
if (array[i3] < array[i4]) swap(array, i3, i4);
if (array[i7] < array[i8]) swap(array, i7, i8);
}
private static void swap(int array[], int i0, int i1)
{
int temp = array[i0];
array[i0] = array[i1];
array[i1] = temp;
}
private static int[] createRandomArray(int size, int min, int max, Random random)
{
int array[] = new int[size];
for (int i=0; i<size; i++)
{
array[i] = min+random.nextInt(max-min);
}
return array;
}
}