2016-05-26 2 views
0

Я пытаюсь сортировать файл, который слишком велик, чтобы вписаться в память. Человек для сортировки gnu по опции -m: merge already sorted files; do not sort. Я изо всех сил пытаюсь понять последствия этого, чтобы убедиться, что сортировка выполняет то, что я хочу. Этот пост (Sorting in pandas for large datasets) предлагает комбинацию gnu split и gnu sort для выполнения такой задачи, например, сначала разбивая файл на более мелкие фрагменты, которые будут вписываться в память, сортируя каждую из них по отдельности, а затем рекомбинируя. Мои эксперименты пока показывают, что эта процедура действительно работает. Тем не менее, меня беспокоит описание варианта слияния в руководстве, в котором говорится, что он не сортируется. Для моих целей необходимо, чтобы большой файл был полностью отсортирован, а не просто конкатенация меньших фрагментов, которые были отсортированы локально. Хотя я проверил процедуру на небольших примерах и, похоже, это работает, в руководстве мне не хватает уверенности в применении его к моей реальной ситуации, поскольку я обеспокоен тем, что неожиданное поведение может возникнуть в ситуациях, когда уже невозможно проверить, не является ли gnu сортировка функционировала так, как я предполагал.gnu-sort - что означает ручное значение, когда он говорит, что опция merge делает «not 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 

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

В качестве альтернативы, если следовать процедуре, пропагандируемых здесь (Sorting in pandas for large datasets), который сначала сортировать кусочки, а затем объединить, я, кажется, чтобы получить правильный результат:

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 будет надежно выполнять то, что она утверждает при использовании опции слияния? Является ли текст руководства каким-то образом намеком на определенные ситуации, в которых эта процедура не сможет достичь желаемого результата?

ответ

1

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

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

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

0

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

Итак, для сортировки очень большого файла то, что вы делаете, действительно работает: разделите его на несколько файлов меньшего размера, отсортируйте их локально. На этом этапе, если вы просто добавите каждый файл в другой, у вас будет что-то вроде 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 
Смежные вопросы