我需要对startIndex
到startIndex + 12
之间的整数数组进行排序。此操作对我的表现至关重要。
您建议我使用什么算法?
现在我正在使用Bubble sort并且表现不佳...
更新:很抱歉找不到详细信息。我正在使用随机数组。我经常这样做,我在Java工作。
更新2:我不确定插入排序是个好主意,因为我使用的是本机数组而不是ArrayList。所以我需要自己实现插入,或者将它与泡泡搜索结合起来。
答案 0 :(得分:8)
您可以尝试这种排序网络:
http://jgamble.ripco.net/cgi-bin/nw.cgi?inputs=12&algorithm=best&output=svg
这是12项的最佳配置。这意味着,最小化操作所需的比较器和深度(如果可以并行工作则可以连续执行)。
要利用并行化,请使用SIMD(SEE)指令。我不知道如何用Java做到这一点。
答案 1 :(得分:2)
对于12个项目,可能是插入排序。它通常具有O(n ^ 2)排序算法的最佳经验性能。对于如此小的集合,O(n log n)算法可能有点过分,算法的复杂性通常意味着它们不会得到回报,直到你排序的集合更大。
当然,如果你真的想要挤出最后一滴性能,你可能需要编写一些程序集并在寄存器或其他东西中进行。
如果你知道它们是有界的,基数排序也可能是一个很好的方法。
答案 2 :(得分:1)
我还会尝试硬编码的合并排序。 首先用硬代码(没有索引变量)对每个连续的3组进行排序。 这3次比较时间为4 = 12。
然后合并前两组3。 那3次比较时间2 = 6。
然后合并两组6。 这是6次比较。
总共24次比较(和数据移动)。
这个可能比72次比较和可能的互换更快。
我在汇编程序中逐步完成它,看看是否有任何说明没有减轻它们的重量。
答案 3 :(得分:1)
我实施了小测试,一次使用Arrays.sort
,一次使用自己的排序实现,基于https://stackoverflow.com/a/22688819中@ypnos引用的排序网络。
但是, NOT 这个比较太严肃了。它不是一个非常复杂的微基准标记,肯定还有很多影响因素尚未考虑。我想到的一个问题是:12个元素的片段是否线性排序?也就是说,您首先排序元素[0,12),然后排序[12,24],依此类推,还是分散在数组中的片段?由于缓存,这可能会对性能产生影响。对所有方法而言,这种影响可能相同,但仍应予以考虑。
在任何情况下,似乎都可以通过这样的分拣网络(或者#34;展开的"排序方法)来挤出一点点性能。
但为了进行比较,我添加了一种并行方法,其中对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;
}
}
答案 4 :(得分:1)
QuickSort和MergeSort对于如此小的阵列大小无效。 我会使用insertSort,我测量的速度比bubbleSort快。
private static void insertionSort(int[] intArray) {
for(int i=1; i<intArray.length; i++){
int temp = intArray[i];
int j;
for(j=i-1; j>=0 && temp<intArray[j]; j--){
intArray[j+1]=intArray[j];
}
intArray[j+1] = temp;
}
}