GNU/LinuxシステムでRAM=に適合する100 Mの行ファイルがあります。
これはかなり遅いです:
sort bigfile > bigfile.sorted
私のマシンでは48コアすべてを使用していません。
どうすればそのファイルをすばやくソートできますか?
48コア、500 GBの空き容量があるRAMで、ファイルが100 M行でメモリに収まると仮定します。
通常のソートを使用すると、かなり遅くなります:
$ time sort bigfile > bigfile.sort
real 4m48.664s
user 21m15.259s
sys 0m42.184s
あなたのロケールを無視することで少し速くすることができます:
$ export LC_ALL=C
$ time sort bigfile > bigfile.sort
real 1m51.957s
user 6m2.053s
sys 0m42.524s
より多くのコアを使用するようにsortに指示することで、より速くすることができます。
$ export LC_ALL=C
$ time sort --parallel=48 bigfile > bigfile.sort
real 1m39.977s
user 15m32.202s
sys 1m1.336s
また、sortにより多くの作業メモリを与えることもできます(sortにすでに十分なメモリがある場合、これは役に立ちません):
$ export LC_ALL=C
$ time sort --buffer-size=80% --parallel=48 bigfile > bigfile.sort
real 1m39.779s
user 14m31.033s
sys 1m0.304s
しかし、実際には、多くのシングルスレッドを実行するのが本当に好きなようです。あなたはそれをもっと並列化するように強制することができます:
$ merge() {
if [ $1 -le 1 ] ; then
parallel -Xj1 -n2 --dr 'sort -m <({=uq=}) | mbuffer -m 30M;'
else
parallel -Xj1 -n2 --dr 'sort -m <({=uq=}) | mbuffer -m 30M;' |
merge $(( $1/2 ));
fi
}
# Generate commands that will read blocks of bigfile and sort those
# This only builds the command - it does not run anything
$ parallel --pipepart -a bigfile --block -1 --dr -vv sort |
# Merge these commands 2 by 2 until only one is left
# This only builds the command - it does not run anything
merge $(parallel --number-of-threads) |
# Execute the command
# This runs the command built in the previous step
bash > bigfile.sort
real 0m30.906s
user 0m21.963s
sys 0m28.870s
ファイルをその場で48ブロック(コアごとに1ブロック)にチョップし、それらのブロックを並列に並べ替えます。次に、それらのペアのマージソートを実行します。次に、それらのペアのマージソートを実行します。次に、それらのペアのマージソートを実行します。次に、それらのペアのマージソートを実行します。次に、それらのペアのマージソートを実行します。以下同様に、入力が1つになるまで続けます。これはすべて、可能な場合は並行して行われます。
4 Gラインの100 GBファイルの場合、タイミングは次のとおりです。
$ LC_ALL=C time sort --parallel=48 -S 80% --compress-program pzstd bigfile >/dev/null
real 77m22.255s
$ LC_ALL=C time parsort bigfile >/dev/null
649.49user 727.04system 18:10.37elapsed 126%CPU (0avgtext+0avgdata 32896maxresident)k
したがって、並列化を使用すると、約4倍の速度になります。
使いやすくするために、小さなツールにしています https://gitlab.com/ole.tange/tangetools/-/tree/master/parsort
sort
オプションとstdinからの読み取りもサポートしています(parsort -k2rn < bigfile
)。