2009-05-30 5 views
79

UNIX sort 명령은 다음과 같이 매우 큰 파일을 정렬 할 수 있습니다.UNIX sort 명령으로 매우 큰 파일을 어떻게 정렬 할 수 있습니까?

sort large_file 

정렬 알고리즘은 어떻게 구현됩니까?

메모리를 과도하게 소비하지 않는 이유는 무엇입니까?

+0

명령을 다시 편집했습니다. UUoC. ;) – ayaz

+0

이것은 흥미 롭습니다. 나는 그것이 어떻게 작동하는지 정말로 모른다. 그러나 나는 추측을 가지고있다. 아마도 각 키의 첫 번째 문자를 이진 트리에 넣을 것이며, 충돌이 발생하면 키의 다음 문자도 사용하므로 필요 이상의 키를 절약하지는 못합니다.그런 다음 각 키를 사용하여 파일에 오프셋을 저장할 수 있으므로 각 줄을 순서대로 찾아서 인쇄 할 수 있습니다. – Zifre

+0

사실, @ayaz는 디스크에 파일이 아니라 파이프에 파일을 정렬하는 것이 더 흥미 롭습니다. 왜냐하면 입력 데이터를 여러 번 통과시킬 수 없다는 것을 분명히 알기 때문입니다. – tvanfosson

답변

93

Algorithmic details of UNIX Sort command은 Unix Sort가 외부 R-Way 병합 정렬 알고리즘을 사용한다고 말합니다. 링크는 더 자세한 내용으로 들어가지만 본질적으로 입력을 더 작은 부분 (메모리에 맞춰 짐)으로 나누고 마지막 부분에서 각 부분을 병합합니다.

33

sort 명령은 작업 데이터를 임시 디스크 파일 (보통 /tmp)에 저장합니다.

+16

임시 디렉토리 지정을 위해'-T' 사용 –

11

나는이 프로그램에 익숙하지 않지만 외부 정렬을 통해 이루어 졌다고 생각한다. (문제의 대부분은 임시 파일에 저장되는 반면, 문제의 비교적 작은 부분은 한 번에 메모리에 저장된다.) Donald Knuth의 The Art of Computer Programming, Vol. 3 Sorting and Searching, Section 5.4에서 주제에 대한 자세한 설명을 볼 수 있습니다.

13

경고 :이 스크립트는 청크 당 하나의 셸을 시작하며, 실제로는 대용량 파일의 경우 수백 개가 될 수 있습니다.


다음은이 목적으로 작성한 스크립트입니다. 4 프로세서 시스템에서는 정렬 성능이 100 % 향상되었습니다!

#! /bin/ksh 

MAX_LINES_PER_CHUNK=1000000 
ORIGINAL_FILE=$1 
SORTED_FILE=$2 
CHUNK_FILE_PREFIX=$ORIGINAL_FILE.split. 
SORTED_CHUNK_FILES=$CHUNK_FILE_PREFIX*.sorted 

usage() 
{ 
    echo Parallel sort 
    echo usage: psort file1 file2 
    echo Sorts text file file1 and stores the output in file2 
    echo Note: file1 will be split in chunks up to $MAX_LINES_PER_CHUNK lines 
    echo and each chunk will be sorted in parallel 
} 

# test if we have two arguments on the command line 
if [ $# != 2 ] 
then 
    usage 
    exit 
fi 

#Cleanup any lefover files 
rm -f $SORTED_CHUNK_FILES > /dev/null 
rm -f $CHUNK_FILE_PREFIX* > /dev/null 
rm -f $SORTED_FILE 

#Splitting $ORIGINAL_FILE into chunks ... 
split -l $MAX_LINES_PER_CHUNK $ORIGINAL_FILE $CHUNK_FILE_PREFIX 

for file in $CHUNK_FILE_PREFIX* 
do 
    sort $file > $file.sorted & 
done 
wait 

#Merging chunks to $SORTED_FILE ... 
sort -m $SORTED_CHUNK_FILES > $SORTED_FILE 

#Cleanup any lefover files 
rm -f $SORTED_CHUNK_FILES > /dev/null 
rm -f $CHUNK_FILE_PREFIX* > /dev/null 

은 참조 : "Sorting large files faster with a shell script"

+27

GNU 정렬 버전으로 sort --parallel N을 사용할 수 있습니다 8.11 – jhclark

+4

GNU coreutils 8.6 실제로 – bdeonovic

+1

이것은 나를 위해 속임수를 사용했습니다. 내가 8.4 버전을 정렬 있습니다. 파일에 직접 정렬을 사용하면 (1 억 9,000 만 줄) 어디로 가는지 알 수 없습니다. 이 프로그램은 단지 4 분 만에 –

-4

메모리는 문제가되지 않습니다 - 종류 이미 처리한다. 멀티 코어 CPU를 최적의 상태로 사용하고 싶다면 작은 스크립트 (넷에서 찾을 수있는 것과 비슷하지만 대부분의 경우보다 간단하고 깔끔한)와 같이 구현해야합니다. 조심스럽게 종류의 옵션에서

#!/bin/bash 
# Usage: psort filename <chunksize> <threads> 
# In this example a the file largefile is split into chunks of 20 MB. 
# The part are sorted in 4 simultaneous threads before getting merged. 
# 
# psort largefile.txt 20m 4  
# 
# by h.p. 
split -b $2 $1 $1.part 
suffix=sorttemp.`date +%s` 
nthreads=$3 
i=0 
for fname in `ls *$1.part*` 
do 
    let i++ 
    sort $fname > $fname.$suffix & 
    mres=$(($i % $nthreads)) 
    test "$mres" -eq 0 && wait 
done 
wait 
sort -m *.$suffix 
rm $1.part* 
+4

재미있는 스크립트이지만이 질문에 대답하는 데는 아무런 답변이 없습니다. –

+5

split -b는 바이트 단위로 분할되므로 임의의 위치에서 줄이 잘립니다. – ithkuil

11
#!/bin/bash 

usage() 
{ 
    echo Parallel sort 
    echo usage: psort file1 file2 
    echo Sorts text file file1 and stores the output in file2 
} 

# test if we have two arguments on the command line 
if [ $# != 2 ] 
then 
    usage 
    exit 
fi 

pv $1 | parallel --pipe --files sort -S512M | parallel -Xj1 sort -S1024M -m {} ';' rm {} > $2 
+0

이것은 우수합니다. 병렬 패키지가 있다는 것을 인식하지 못했습니다! 위의 사용 후 정렬 시간이 50 % 이상 향상되었습니다. 감사. – xbsd

+0

나는 이것에 의해 생성 된 파일에 diff를위한 comm을 사용하여 파일이 정렬되지 않았다는 경고를 주려고했다. – ashishb

4

봐 성능을 가속화하고 컴퓨터와 문제에 미치는 영향의 이해합니다. 우분투에 주요 매개 변수는 임시 파일의

  • 위치, 더 나은하지만 원인 가입을 통해 않도록 사용하는 모든 메모리의 -sn % (N의 %를 사용하는 메모리의 디렉토리 이름
  • 금액 -t 있습니다 디스크로 교환. 당신은 "-S 80 %"처럼 사용할 수있는 결과 2 기가 바이트 RAM을 사용할 RAM의 80 %, 또는 "-S 세대"를 사용합니다.)

질문자가 "왜 메모리 사용을 요구하지 않습니다 ? " 그 대답은 역사에서 나왔고 오래된 Unix 시스템은 작았고 기본 메모리 크기는 작게 설정되었습니다. 워크로드가 가능한 한 크게 조정하여 정렬 성능을 크게 향상시킵니다. 작업 디렉토리를 정렬하는 파일의 크기를 최소한 1.25 * 보유 할 수있는 충분한 공간이있는 가장 빠른 장치의 위치로 설정하십시오.

+0

- 80GB의 RAM이있는 상자의 2.5GB 파일에서이 작업을 시도해보십시오. 전체 파일이 그보다 작더라도 실제로는 전체 비율을 사용하고 있습니다. 그게 왜? 심지어 쓸데없는 것으로 보이는 내부 정렬을 사용하지 않더라도 –

+0

아마 sort-S는 파일의 내용을 읽기 전에 정렬 프로세스를위한 메모리를 미리 할당합니다. –

관련 문제