Lệnh UNIX sort
có thể sắp xếp một tệp rất lớn như thế này:
sort large_file
Thuật toán sắp xếp được thực hiện như thế nào?
Làm thế nào để nó không gây tiêu thụ quá nhiều bộ nhớ?
Lệnh UNIX sort
có thể sắp xếp một tệp rất lớn như thế này:
sort large_file
Thuật toán sắp xếp được thực hiện như thế nào?
Làm thế nào để nó không gây tiêu thụ quá nhiều bộ nhớ?
Câu trả lời:
Các chi tiết thuật toán của UNIX Sắp xếp lệnh nói Unix Sắp xếp sử dụng một ngoại R-Way merge thuật toán sắp xếp. Liên kết đi vào chi tiết hơn, nhưng về bản chất, nó chia dữ liệu đầu vào thành các phần nhỏ hơn (phù hợp với bộ nhớ) và sau đó kết hợp từng phần lại với nhau ở cuối.
Các sort
cửa hàng lệnh dữ liệu trong các tập tin đĩa tạm thời làm việc (thường là trong /tmp
).
-T
để xác định thư mục temp
CẢNH BÁO: Tập lệnh này bắt đầu một trình bao cho mỗi đoạn, đối với các tệp thực sự lớn, con số này có thể là hàng trăm.
Đây là một kịch bản tôi đã viết cho mục đích này. Trên máy 4 bộ xử lý, nó đã cải thiện 100% hiệu suất sắp xếp!
#! /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
Xem thêm: " Sắp xếp các tệp lớn nhanh hơn với tập lệnh shell "
Tôi không quen thuộc với chương trình nhưng tôi đoán nó được thực hiện bằng cách sắp xếp bên ngoài (hầu hết sự cố được lưu giữ trong các tệp tạm thời trong khi một phần tương đối nhỏ của sự cố được lưu trong bộ nhớ tại một thời điểm). Xem Nghệ thuật Lập trình Máy tính của Donald Knuth , Vol. 3 Sắp xếp và Tìm kiếm, Phần 5.4 để thảo luận sâu hơn về chủ đề này.
#!/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
Xem xét cẩn thận các tùy chọn sắp xếp để tăng tốc hiệu suất và hiểu tác động của nó đối với máy và sự cố của bạn. Các thông số chính trên Ubuntu là
Người hỏi đặt câu hỏi "Tại sao không sử dụng bộ nhớ cao?" Câu trả lời cho điều đó đến từ lịch sử, các máy unix cũ hơn nhỏ và kích thước bộ nhớ mặc định được đặt nhỏ. Điều chỉnh điều này càng lớn càng tốt để khối lượng công việc của bạn cải thiện đáng kể hiệu suất sắp xếp. Đặt thư mục làm việc vào một nơi trên thiết bị nhanh nhất của bạn có đủ dung lượng để chứa ít nhất 1,25 * kích thước của tệp đang được sắp xếp.
Bộ nhớ không phải là một vấn đề - sắp xếp đã giải quyết vấn đề đó. Nếu bạn muốn sử dụng tối ưu CPU đa lõi của mình, tôi đã triển khai phần này trong một tập lệnh nhỏ (tương tự như một số bạn có thể tìm thấy trên mạng, nhưng đơn giản hơn / sạch hơn hầu hết những cái đó;)).
#!/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*