Java 对12个项目进行排序的最佳算法是什么
我需要对Java 对12个项目进行排序的最佳算法是什么,java,performance,algorithm,sorting,Java,Performance,Algorithm,Sorting,我需要对startIndex到startIndex+12之间的整数数组进行排序。这个操作对我的表现至关重要 你建议我使用什么算法 现在我正在使用,但效果不太好 更新:很抱歉,缺少详细信息。我正在使用随机数组。我经常做这个动作,我在Java中工作 更新2:我不确定插入排序是否是个好主意,因为我使用的是本机数组而不是ArrayList。因此,我需要自己实现插入,或者将其与气泡搜索结合起来。对于12项,可能是插入排序。它通常具有O(n^2)排序算法中最好的经验性能。对于这样一个小的集合,O(n log
startIndex
到startIndex+12
之间的整数数组进行排序。这个操作对我的表现至关重要
你建议我使用什么算法
现在我正在使用,但效果不太好
更新:很抱歉,缺少详细信息。我正在使用随机数组。我经常做这个动作,我在Java中工作
更新2:我不确定插入排序是否是个好主意,因为我使用的是本机数组而不是ArrayList。因此,我需要自己实现插入,或者将其与气泡搜索结合起来。对于12项,可能是插入排序。它通常具有O(n^2)排序算法中最好的经验性能。对于这样一个小的集合,O(n logn)算法可能是杀伤力过大,算法的复杂性通常意味着它们在你要排序的集合变大之前不会有回报 当然,如果您真的想挤出最后一点性能,您可能需要编写一些程序集,并在寄存器或其他地方执行
如果您知道它们是有界的,则基数排序也是一种很好的方法。您可以尝试以下排序网络: 这是12个项目的最佳配置。这意味着,最小化必要的比较器和操作深度(如果可以并行工作,则为连续步骤)
要利用并行化的优势,请使用SIMD(请参阅)指令。我不知道如何使用Java实现这一点。我还将尝试硬编码的合并排序。 首先用硬代码(无索引变量)对每个连续的3组进行排序。 这是3次比较乘以4=12 然后合并前两组(共3组)。 这是3次比较乘以2=6 然后合并两组6人。 这是6个比较 总共24次比较(和数据移动) 这可能比72次比较和可能的互换更快
我会在汇编程序中逐步检查它,看看是否有任何指令没有发挥作用。我实现了一个小测试,一次使用
数组。sort
,一次使用自己的基于中@ypnos引用的排序网络的排序实现
但是,不要把这种比较看得太严重。它不是一个非常复杂的微基准,当然还有许多影响因素尚未考虑。我想到的一个问题是:12个元素段是线性排序的吗?也就是说,您是先对元素[0,12]排序,然后是[12,24]等等,还是将段分散在数组中?这可能会由于缓存而对性能产生影响。对于所有方法,这种影响都是相同的,但仍应予以考虑
在任何情况下,使用这样的排序网络(或通常的“展开”排序方法)似乎都有可能挤出一点点性能
但是,为了比较,我添加了一种并行的方法,其中对12个元素段集合进行排序的任务分布在所有可用的内核中,并且似乎可以以这样的方式实现显著的加速。因此,一般来说,您应该考虑对该任务进行某种并行化。 (从
-Xmx2000m
开始,为大型阵列提供足够的内存)
import java.util.ArrayList;
导入java.util.array;
导入java.util.List;
导入java.util.Random;
导入java.util.concurrent.Callable;
导入java.util.concurrent.ExecutorService;
导入java.util.concurrent.Executors;
导入java.util.concurrent.TimeUnit;
公共类SmallSortTest
{
公共静态void main(字符串[]args)
{
随机数=新随机数(0);
对于(int size=8000000;size快速排序和合并排序对于如此小的数组大小无效。
我会使用insertionSort,我测量它比bubbleSort快
private static void insertionSort(int[]intArray){
对于(int i=1;i=0&&temp您使用的是什么数据结构以及如何填充它?您使用的是什么语言和平台?当然冒泡是不好的,但对于12项来说并不重要。请提供更多的上下文,您需要多久做一次?数组的排序/大小如何?为什么?可能相关:如何对12项进行排序可能很关键?@Ilya_Gazm只要你看到一个有输入i和j的比较器,你就会写一行代码,比如:if(a[i]>a[j]){int t=a[i];a[i]=a[j];a[j]=t;}
基本上你可以看到哪些元素需要比较(取决于值,交换)。您还可以看到它分为几个步骤。因此,请完成第一行,然后继续第二行。现在,如果您可以同时执行多个操作(理论上可以同时执行一行中的所有比较/交换),您可以获得巨大的速度增益。为此,您需要使用向量计算,这是CPU上的特定指令(SSE或AVX用于现代CPU)。@davidisenstat所以基本上这些是我需要检查和交换的数组索引对(如果需要的话),并且每一行可以并行运行?实际上有一个本机植入:Arrays.sort()。看起来有点死板。我刚完成@ypnos建议的实现,速度更快。@Ilya:排序网络可能是最快的,但我打赌硬编码方法的性能会优于数组。sort()很好的一点,就是通过避免方法调用之类的。呵呵,实际上这正是我要做的。我马上分享我的源代码。要恢复排序顺序,你需要镜像所有索引。i0=startIndex+11;i1=startIndex10;…i11=startIndex+0;
。网络本身,包括比较,保持不变。我不是100%确定,但是非常确定!回复:-)@ypons我想我试过这个,将比较从
更改为code>
,以及两者的组合,并且认为这些都没有达到预期的效果,但此时可能还有其他错误。我必须再次测试它
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;
}
}