RAM에 맞는 대용량 파일의 "정렬" 속도를 높이기 위해 "병렬"을 사용하는 방법은 무엇입니까?

RAM에 맞는 대용량 파일의 "정렬" 속도를 높이기 위해 "병렬"을 사용하는 방법은 무엇입니까?

GNU/Linux 시스템의 RAM에 맞는 100M 라인 파일이 있습니다.

이것은 다소 느립니다.

sort bigfile > bigfile.sorted

내 컴퓨터에서 48개 코어를 모두 사용하지는 않습니다.

해당 파일을 빨리 정렬하려면 어떻게 해야 합니까?

답변1

48개의 코어, 500GB의 여유 RAM이 있고 파일이 1억 라인이고 메모리에 적합하다고 가정해 보겠습니다.

일반 정렬을 사용하면 다소 느립니다.

$ 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

정렬에 더 많은 작업 메모리를 제공할 수도 있습니다(이는 정렬에 이미 충분한 메모리가 있는 경우에는 도움이 되지 않습니다).

$ 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개의 블록(코어당 하나의 블록)으로 자르고 해당 블록을 병렬로 정렬합니다. 그런 다음 우리는 그것들을 한 쌍으로 병합합니다. 그런 다음 우리는 그것들을 한 쌍으로 병합합니다. 그런 다음 우리는 그것들을 한 쌍으로 병합합니다. 그런 다음 우리는 그것들을 한 쌍으로 병합합니다. 그런 다음 우리는 그것들을 한 쌍으로 병합합니다. 그리고 입력이 하나만 있을 때까지 계속됩니다. 가능하다면 이 모든 작업은 병렬로 수행됩니다.

4G 라인이 포함된 100GB 파일의 경우 타이밍은 다음과 같습니다.

$ 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배 빨라집니다.

더 쉽게 사용할 수 있도록 작은 도구로 만들었습니다. parsort이제 GNU Parallel의 일부가 되었습니다.

sort옵션과 stdin에서의 읽기도 지원합니다 ( parsort -k2rn < bigfile).

관련 정보