排序5万个数字

时间:2010-11-27 12:30:36

标签: java algorithm sorting parallel-processing

假设我们需要对5 000 000个数字进行排序。假设,这些数字存储在一个文件中。解决此问题的最有效算法是什么?并行排序算法......

怎么做?也许有用的链接)

我无法使用标准算法

因此我问你方法和算法:)

好的..我读过有关并行合并的内容......但对我来说并不清楚。

解决方案,第一个版本

code is located here

7 个答案:

答案 0 :(得分:19)

千万不是特别大。我会把它们读进记忆中。对它们进行排序并将其写出来。它应该只需几秒钟。你需要多快?你需要它是多么复杂?

在我的旧实验室上花了28秒。如果我有更多的处理器,它可能会快一点,但是大部分时间花在读取和写入文件上(15秒),这不会更快。

其中一个关键因素是缓存的大小。如果数据在缓存中,则比较本身非常便宜。由于L3缓存是共享的,因此您需要一个线程来充分利用它。

public static void main(String...args) throws IOException {
    generateFile();

    long start = System.currentTimeMillis();
    int[] nums = readFile("numbers.bin");
    Arrays.sort(nums);
    writeFile("numbers2.bin", nums);
    long time = System.currentTimeMillis() - start;
    System.out.println("Took "+time+" secs to sort "+nums.length+" numbers.");
}

private static void generateFile() throws IOException {
    Random rand = new Random();
    int[] ints = new int[50*1000*1000];
    for(int i= 0;i<ints.length;i++)
        ints[i] = rand.nextInt();
    writeFile("numbers.bin", ints);
}

private static int[] readFile(String filename) throws IOException {
    DataInputStream dis = new DataInputStream(new BufferedInputStream(new FileInputStream(filename), 64*1024));
    int len = dis.readInt();
    int[] ints = new int[len];
    for(int i=0;i<len;i++)
        ints[i] = dis.readInt();
    return ints;
}

private static void writeFile(String name, int[] numbers) throws IOException {
    DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(name), 64*1024));
    dos.writeInt(numbers.length);
    for (int number : numbers)
        dos.writeInt(number);
    dos.close();
}

答案 1 :(得分:8)

并行化和分发方面,merge sort似乎是最好的选择,因为它使用分而治之做法。有关详细信息,请参阅“并行合并排序”和“分布式合并排序”。

对于单机,多核示例,请参阅Correctly multithreaded quicksort or mergesort algo in Java?。如果您可以使用Java 7 fork / join,请参阅:“Java 7: more concurrency”和“Parallelism with Fork/Join in Java 7”。

对于在多台计算机上分发,请参阅Hadoop,它有一个分布式合并排序实现:请参阅MergeSortMergeSorter。同样感兴趣:Hadoop Sorts a Petabyte in 16.25 Hours and a Terabyte in 62 Seconds

答案 2 :(得分:4)

对于排序而非许多元素,您的最佳镜头是Merge Sort。它通常是数据库使用的算法。尽管不如Quick Sort快,但它使用中间存储,因此您不需要大量内存来执行排序。

另外,正如sje397和Scott在评论中所指出的,Merge Sort是高度可并行化的。

答案 3 :(得分:3)

这在很大程度上取决于问题领域。例如,如果所有数字都是正数,则最好的方法是创建一个0-MAX_INT数组,然后计算每个数字在读取文件时出现的次数,然后用非打印出每个int零计数,但它发生了很多次。这是一个O(n)“排序”。这种官方名称,但我忘了它是什么。

顺便说一句,我在谷歌的一次采访中被问到了这个问题。从问题的限制我想出了这个解决方案,它似乎是他们正在寻找的答案。 (我拒绝了这份工作,因为我不想搬家。)

答案 4 :(得分:2)

他们不是那么多。如果它们是10字节长扩展,例如它将是500Mbytes的数组,它几乎可以留在我的手机上! ;) 所以,如果只是那样的话,我会去Quicksort。

答案 5 :(得分:2)

不要害怕大数。事实上,5亿个数字并不是那么大。因此,如果数字是整数,则每个数字的大小为4字节,因此需要为此数组分配的总内存为50 000 000 * 4/1024/1024 = 190.7兆字节,这相对较小。完成数学运算后,您可以继续执行在O(nLogn)中运行的QuickSort。请注意.net数组中的内置排序方法使用QuickSort,我不确定是否也是这种情况。

在我的机器上排序250 000 000个整数花了大约2分钟,所以去吧:)

答案 6 :(得分:0)

现在50e6的数字非常小,不要让事情变得比他们需要的更复杂......

bash$ sort < file > sorted.file