UNIX的sort
命令可以像这样对大型文件进行排序:
sort large_file
排序算法是如何实现的?
为什么它不会导致过多的内存消耗?
UNIX的sort
命令可以像这样对大型文件进行排序:
sort large_file
排序算法是如何实现的?
为什么它不会导致过多的内存消耗?
UNIX Sort命令的算法细节显示,Unix Sort使用外部R-Way归并排序算法。这个链接提供了更多详情,但基本上它将输入分成较小的部分(适合内存),然后在最后将每个部分合并在一起。
sort
命令将工作数据存储在临时磁盘文件中(通常位于 /tmp
目录下)。
警告:此脚本每个文件块都会启动一个shell,在处理非常大的文件时,可能会有数百个shell进程。
这是我为此目的编写的脚本。在一台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
另请参见:使用shell脚本更快地对大文件进行排序
#!/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
我不熟悉这个程序,但我猜测它是通过外部排序完成的(大部分问题保存在临时文件中,每次只有相对较小的一部分问题保存在内存中)。请参阅Donald Knuth的《计算机程序设计艺术》第3卷排序和搜索第5.4节,深入讨论这个主题。
如何使用-T选项对大文件进行排序
我需要对一个大文件的第七列进行排序。
我一直在使用:
grep vdd "file name" | sort -nk 7 |
******sort: write failed: /tmp/sort1hc37c: No space left on device******
然后我使用了如下的-T选项,它起作用了:
grep vdda "file name" | sort -nk 7 -T /dev/null/ |
内存不应该是一个问题——排序已经解决了这个问题。如果您想充分利用多核 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*