Я написал следующий скрипт для проверки скорости сортировки Python:
from sys import stdin, stdout
lines = list(stdin)
lines.sort()
stdout.writelines(lines)
Затем я сравнил это с командой coreutils sort
для файла, содержащего 10 миллионов строк:
$ time python sort.py <numbers.txt >s1.txt
real 0m16.707s
user 0m16.288s
sys 0m0.420s
$ time sort <numbers.txt >s2.txt
real 0m45.141s
user 2m28.304s
sys 0m0.380s
Встроенная команда использовала все четыре процессора (Python использовал только один), но для ее запуска потребовалось в 3 раза больше времени! Что дает?
Я использую Ubuntu 12.04.5 (32-разрядная версия), Python 2.7.3 и sort
8.13
--buffer-size
чтобы указать, чтоsort
использовать всю доступную физическую память и посмотреть, помогает ли это?Ответы:
Комментарий Изкаты выявил ответ: сравнение с конкретной локалью . Команда
sort
использует локаль, указанную средой, тогда как Python по умолчанию сравнивает порядок байтов. Сравнение строк UTF-8 сложнее, чем сравнение строк байтов.Как насчет этого.
источник
locale.strxfrm
для сортировки, скрипт занял ~ 32 секунды, все еще быстрее,sort
но гораздо меньше.cut
, как и другие. На нескольких машинах я теперьexport LC_ALL=C
в.bashrc
. Но будьте осторожны: это существенно ломаетwc
(кромеwc -l
), просто чтобы назвать пример. «Плохие байты» вообще не учитываются ...grep
: вы можете получить существенное улучшение производительности при сбрасывании больших файлов, отключив UTF-8, особенно при выполненииgrep -i
Это скорее дополнительный анализ, чем фактический ответ, но, похоже, он варьируется в зависимости от сортируемых данных. Во-первых, базовое чтение:
ОК, Python намного быстрее. Тем не менее, вы можете сделать coreutils
sort
быстрее, сказав, что он сортирует по численности:Это намного быстрее, но питон все еще выигрывает с большим отрывом. Теперь давайте попробуем еще раз, но с несортированным списком из 1М номеров:
Coreutils
sort -n
быстрее для несортированных числовых данных (хотя вы можете изменить параметр сортировки Python,cmp
чтобы сделать его быстрее). Coreutilssort
все еще значительно медленнее без-n
флага. Итак, что насчет случайных символов, а не чистых чисел?Python по-прежнему превосходит coreutils, но с гораздо меньшим отрывом, чем то, что вы показываете в своем вопросе. Удивительно, но это все еще быстрее, если смотреть на чисто алфавитные данные:
Также важно отметить, что эти два не производят одинаковый отсортированный вывод:
Как ни странно, эта
--buffer-size
опция, казалось, не имела большого (или какого-либо) значения в моих тестах. В заключение, предположительно из-за различных алгоритмов, упомянутых в ответе Златовласки, pythonsort
в большинстве случаев выглядит быстрее, но числовой GNUsort
превосходит его по несортированным числам 1 .ОП, вероятно, нашел основную причину, но для полноты изложения приведу окончательное сравнение:
1 Тот, у кого больше python-fu, чем я, должен попытаться проверить настройку,
list.sort()
чтобы увидеть ту же скорость, может быть достигнут путем указания метода сортировки.источник
sort
кажется, делает немного дополнительной работы для сравнения прописных / строчных букв.stdin
ввода. Преобразование тех чисел (lines = map(int, list(stdin))
) и обратно (stdout.writelines(map(str,lines))
) делает всю сортировку идти медленнее, вверх от 0.234s реально 0.720s на моей машине.Обе реализации находятся на C, так что ровного игрового поля нет. Coreutils,
sort
очевидно, использует алгоритм слияния . Mergesort выполняет фиксированное число сравнений, которое логарифмически увеличивается до размера ввода, то есть большое O (n log n).Сортировка Python использует уникальную гибридную сортировку слиянием / вставкой, timsort , которая будет выполнять различное число сравнений с наилучшим сценарием O (n) - предположительно, в уже отсортированном списке - но, как правило, логарифмическая (логически вы не может быть лучше, чем логарифмическая для общего случая при сортировке).
Учитывая два различных логарифмических сорта, один может иметь преимущество перед другим в некотором конкретном наборе данных. Традиционная сортировка слиянием не меняется, поэтому она будет работать одинаково независимо от данных, но, например, быстрая сортировка (также логарифмическая), которая меняется, будет лучше работать с некоторыми данными, но хуже с другими.
Фактор три (или больше 3, так
sort
как распараллеливается) довольно немного, что заставляет меня задуматься, нет ли здесь каких-то непредвиденных обстоятельств, таких какsort
переключение на диск (-T
вариант может показаться, что это так). Тем не менее, ваша низкая система против времени пользователя означает, что это не проблема.источник