UNIX sort
コマンドは、次のように非常に大きなファイルをソートできます。
sort large_file
並べ替えアルゴリズムはどのように実装されていますか?
それはなぜメモリの過度の消費を引き起こさないのですか?
UNIX sort
コマンドは、次のように非常に大きなファイルをソートできます。
sort large_file
並べ替えアルゴリズムはどのように実装されていますか?
それはなぜメモリの過度の消費を引き起こさないのですか?
回答:
UNIX Sortコマンドのアルゴリズムの詳細では、Unix Sortは外部R-Wayマージソートアルゴリズムを使用していると述べています。リンクはより詳細になりますが、本質的には入力を(メモリに収まる)小さな部分に分割し、最後に各部分をマージします。
警告:このスクリプトはチャンクごとに1つのシェルを開始します。非常に大きなファイルの場合、これは数百になる場合があります。
これは私がこの目的のために書いたスクリプトです。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
私はプログラムに精通していませんが、外部ソートによって行われていると思います(問題の大部分は一時ファイルに保持され、問題の比較的小さな部分は一度にメモリに保持されます)。Donald KnuthのThe Art of Computer Programming、Vol。3ソートと検索、セクション5.4。
#!/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
ソートのオプションを注意深く見てパフォーマンスを向上させ、マシンと問題への影響を理解してください。Ubuntuの主要なパラメーターは
質問者は「メモリ使用量が多いのはなぜですか?」その答えは歴史から来ています。古いUNIXマシンは小さく、デフォルトのメモリサイズは小さく設定されています。これをワークロードに合わせてできるだけ大きく調整して、ソートのパフォーマンスを大幅に向上させます。作業ディレクトリを、ソートするファイルのサイズの少なくとも1.25 *を保持するのに十分なスペースがある最速のデバイスの場所に設定します。
メモリは問題ではないはずです-ソートはすでにそれを処理しています。マルチコア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*