gnu-sort - что означает ручное управление, когда оно говорит, что опция слияния не сортируется

Я пытаюсь отсортировать файл, который слишком велик для размещения в памяти. Человек для сортировки gnu с опцией -m указывает: merge already sorted files; do not sort. Я изо всех сил пытаюсь понять последствия этого, чтобы убедиться, что этот вид выполняет то, что я хочу. Этот пост (Сортировка в pandas для больших наборов данных) предлагает комбинацию разделения gnu и gnu sort для выполнения такой задачи, сначала разбивая файл на более мелкие части, которые поместятся в памяти, сортируя каждую из них по отдельности, а затем рекомбинируя. Мои эксперименты показывают, что эта процедура действительно работает. Тем не менее, меня беспокоит описание опции слияния в руководстве, где говорится, что она не сортируется. Для моих целей необходимо, чтобы большой файл был полностью отсортирован, а не просто объединение более мелких частей, отсортированных локально. Хотя я проверил эту процедуру на небольших примерах, и она, кажется, работает, руководство не дает мне уверенности в применении ее к моей реальной ситуации, поскольку я обеспокоен тем, что может возникнуть неожиданное поведение в ситуациях, когда уже невозможно проверить, работает ли gnu. sort работала так, как я предполагал.

Чтобы дать MWE, рассмотрите этот файл, разделенный табуляцией, который я хотел бы отсортировать:

3   4
2   5
3   1
1   3

Я пробовал следующие операции:

SortDir="/Users/aireties/Desktop/Sort_Experiments"
## sort document as a whole (in practice, this would be infeasible due to document size)
sort --field-separator=$'\t' -k 1,1 -k 2,2 "$SortDir/To_Be_Sorted.txt" -o "$SortDir/Sorted_as_Whole.txt"  ## sort first by the first column values, then by the second

1   3
2   5
3   1
3   4

Это «правильное» решение при сортировке всего файла сразу (что невозможно в моем реальном случае использования).

Если я попытаюсь разбить файл на части, а затем сразу же использовать параметр -m, я получу неверный результат:

## Break file into pieces
MaxLines=2
mkdir "$SortDir/Pieces/"
split -l $MaxLines "$SortDir/To_Be_Sorted.txt" "$SortDir/Pieces/"
## Try merge sort on pieces without first sorting them
sort -m --field-separator=$'\t' -k 1,1 -k 2,2 "$SortDir/Pieces/"* -o "$SortDir/Sorted_in_Pieces1.txt"

3   1
1   3
3   4
2   5

Похоже, произошло то, что сортировка gnu только что рассмотрела две отдельные части и отсортировала их относительно первых значений друг в друге. Таким образом, в этом готовом изделии он поставил второй кусок первым, но не сделал никакой другой сортировки.

В качестве альтернативы, если я буду следовать процедуре, рекомендованной здесь (Сортировка в pandas для больших наборов данных ), то есть сначала отсортировать части, а затем объединить, я, кажется, получаю правильный результат:

for file in "$SortDir/Pieces/"*  ## sorts all text files in pwd
do
  sort --field-separator=$'\t' -k 1,1 -k 2,2 "$file" -o "$file"
done    

sort -m --field-separator=$'\t' -k 1,1 -k 2,2 "$SortDir/Pieces/"* -o "$SortDir/Sorted_in_Pieces2.txt"    

1   3
2   5
3   1
3   4


cmp --silent "$SortDir/Sorted_in_Pieces1.txt" "$SortDir/Sorted_as_Whole.txt" || echo "files are different"
# file are different
cmp --silent "$SortDir/Sorted_in_Pieces2.txt" "$SortDir/Sorted_as_Whole.txt" || echo "files are different"

Для меня камнем преткновения является то, что если фрагменты файлов большие, все еще необходимо выполнить довольно много вычислений, чтобы объединить их в один правильно отсортированный файл. Таким образом, мне трудно понять, как такой нетривиальный объем сортировки может быть описан как результат операции, которая утверждает, что она «не сортируется».

Может ли кто-нибудь просветить меня относительно того, почему руководство будет сформулировано так? Почему и как мы можем быть уверены, что сортировка gnu будет надежно выполнять заявленное при использовании опции слияния? Не намекает ли текст руководства на определенные ситуации, в которых эта процедура не даст желаемого результата?


person Michael Ohlrogge    schedule 26.05.2016    source источник


Ответы (3)


Сортировка Gnu (по крайней мере, версия, для которой я смотрел исходный код) будет сортировать фрагменты файла в памяти и создавать набор временных файлов (1 временный файл на фрагмент). Он также использует многопоточность на этапе сортировки памяти (параметр командной строки может установить максимальное количество используемых потоков). После создания всех временных файлов выполняется 16-кратное слияние (если вы не переопределите это) временных файлов, пока не будет создан один отсортированный файл.

Дело в том, что вам не нужно сначала разбивать файл на отдельные файлы, так как gnu sort автоматически обрабатывает большой файл, создавая при необходимости отсортированные временные файлы для объединения в один отсортированный файл.

Опция -m предназначена для особого случая, когда необходимо объединить несколько уже отсортированных файлов.

person rcgldr    schedule 26.05.2016

-m просто объединяет файлы вместе, как это делает операция merge сортировки слиянием. Это требует, чтобы два файла были отсортированы в соответствии с одним и тем же порядком.

Итак, для сортировки очень большого файла то, что вы делаете, действительно работает: разделите его на несколько файлов меньшего размера, отсортируйте их локально. На этом этапе, если вы просто добавите каждый файл к другому, вы получите что-то вроде 0 1 2 3 ... 0 1 2 3

Опция -m объединяет их правильно.

Например, с такими:

a  b
1  3
2  2
3  1

sort -m a b
# 1 2 3 3 2 1
sort -m a a
# 1 1 2 2 3 3
sort -m b b
# 3 2 1 3 2 1
sort -r -m b a
# 3 2 1 1 2 3
person T. Claverie    schedule 26.05.2016

Я подозреваю, что концептуальная проблема заключается в том, что означает «слияние». В контексте алгоритмов сортировки «слияние» имеет особое значение. См. https://en.wikipedia.org/wiki/Merge_algorithm для обсуждения. Важным моментом является то, что, хотя операция слияния принимает несколько файлов в качестве входных данных, элементы в любом отдельном входном файле должны быть в правильно отсортированном порядке, чтобы слияние выполнялось так, как предполагается — это отличается от сортировки. операция. В этом смысле «слияние не сортирует».

Существует также алгоритм сортировки под названием «сортировка слиянием», который использует в качестве одного из компонентов операции слияния.

person user2864482    schedule 05.03.2020