сортировка 50 000 000 номеров - PullRequest
7 голосов
/ 27 ноября 2010

Предположим, что нам нужно отсортировать 50 000 000 чисел. Предположим, что числа хранятся в файле. Какой самый эффективный алгоритм для решения этой проблемы? Параллельный алгоритм сортировки ...

Как это сделать? Может быть полезная ссылка)

Я не могу использовать стандартный алгоритм

Поэтому я спрашиваю вас о методах и алгоритмах :)

Хорошо ... Я читал о параллельной сортировке слиянием ... Но для меня это не ясно.

решение, первая версия

код находится здесь

Ответы [ 7 ]

19 голосов
/ 27 ноября 2010

50 миллионов не особо велики.Я бы просто прочитал их в память.Сортируйте их и запишите.Это займет всего несколько секунд.Как быстро тебе это нужно?Насколько он вам нужен?

На моем старом labtop это заняло 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();
}
8 голосов
/ 27 ноября 2010

Сверху в голове, сортировка слиянием представляется наилучшим вариантом, когда речь идет о распараллеливании и распределении , поскольку в нем используется разделяй и властвуй подход.Для получения дополнительной информации, Google для " параллельная сортировка слиянием " и " распределенная сортировка слиянием ".

Для для одного компьютера, несколько ядер примерсм. Правильно ли многопоточный алгоритм быстрой сортировки или слияния в Java? .Если вы можете использовать Java 7 fork / join, тогда смотрите: « Java 7: больше параллелизма » и « Параллелизм с Fork / Join в Java 7 ».

Для распределяет его по многим машинам , см. Hadoop , имеет распределенную реализацию сортировки слиянием: см. MergeSort и MergeSorter Также интересно: Hadoop сортирует петабайт за 16.25 часов и терабайт за 62 секунды

4 голосов
/ 27 ноября 2010

Для сортировки множества элементов ваш лучший снимок - Слияние с сортировкой .Обычно это алгоритмы, используемые базами данных.Несмотря на то, что он не такой быстрый, как Быстрая сортировка , он использует промежуточное хранилище, поэтому вам не нужно огромное количество памяти для выполнения сортировки.

Кроме того, как указали sje397 и Скотт вВ комментариях сортировка слиянием очень распараллеливаема.

3 голосов
/ 27 ноября 2010

Это сильно зависит от проблемной области.Например, если все числа являются положительными целочисленными значениями, лучшим способом может быть создание массива 0-MAX_INT, а затем просто подсчитать, сколько раз встречается каждое число при чтении файла, а затем распечатать каждое целое сотсчет нуля, сколько раз это происходило.Это O (n) "сортировка".Есть официальное название для такого рода, но я забываю, что это такое.

Кстати, мне задали этот вопрос в интервью Google.Из ограничений проблемы я пришел к этому решению, и, похоже, это был ответ, который они искали.(Я отказался от работы, потому что не хотел двигаться.)

2 голосов
/ 27 ноября 2010

не бойтесь большого числа. На самом деле, 50 000 000 номеров не так уж и велики. таким образом, если числа были целыми числами, то каждое число имеет размер 4 байта, поэтому общая память, которую необходимо выделить для этого массива, составляет 50 000 000 * 4/1024/1024 = 190,7 мегабайт, что относительно мало. После выполнения математики вы можете приступить к быстрой сортировке, которая выполняется в O (nLogn). обратите внимание, что встроенный метод сортировки в массивах .net использует QuickSort, я не уверен, что это также относится и к Java.

сортировка 250 000 000 целых чисел на моей машине заняла около 2 минут, так что дерзайте:)

2 голосов
/ 27 ноября 2010

Их не так много.Например, если они расширены на 10 байт, то это будет массив из 500 Мбайт, он почти может остаться на моем телефоне!;) Так что я бы сказал, пойти на Quicksort, если это только так.

0 голосов
/ 29 января 2012

50e6 числа в наши дни очень малы, не усложняйте вещи, чем они должны быть ...

bash$ sort < file > sorted.file

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...