如何使用GNU Parallel编写多核排序

时间:2015-01-15 18:59:27

标签: multithreading bash sorting parallel-processing gnu-parallel

GNU Parallel

  

GNU parallel是一个shell工具,用于使用一台或多台计算机并行执行作业

例如,如果我想编写wc的多核版本,我可以这样做:

cat XXX | parallel --block 10M --pipe wc -l | awk 'BEGIN{count=0;}{count = count+ $1;} END{print count;}'

我的问题是如何使用并行进行排序?我知道我应该做的是将并行结果传递给"合并已排序的文件"命令(就像合并排序中的最终合并一样),但我不知道如何做到这一点。

1 个答案:

答案 0 :(得分:3)

有几种方法可以做到这一点。

让我们来一个简单的文本文件:

$ curl http://www.gutenberg.org/cache/epub/2701/pg2701.txt 2>/dev/null |
   tr " " "\n" | tr "[A-Z]" "[a-z]" | 
   sed -e 's/[[:punct:]]*//g' -e '/^[[:space:]]*$/d' > moby-dick-words.txt

$ wc moby-dick-words.txt

215117 moby-dick-words.txt
$ time sort moby-dick-words.txt > moby-dick-words-sorted.txt

real    0m0.260s
user    0m0.462s
sys 0m0.004s

我们可以对文本块进行排序,一次说10000个单词,并将一些艰难的连续工作推迟到合并(sort -m)部分:

$ mkdir tmp
$ time (
  cd tmp;
  split -l 1000 ../moby-dick-words.txt;
  parallel sort {} -o {}.sorted ::: x*;
  sort -m *.sorted > ../moby-dick-words-sorted-merge.txt;
  rm x* )

real    0m0.787s
user    0m0.495s
sys 0m0.103s

$ diff moby-dick-words-sorted.txt moby-dick-words-sorted-merge.txt 

$ uniq -c moby-dick-sorted-merge.txt | tail      
  1 zeuglodon
  1 zigzag
  5 zodiac
  1 zogranda
  4 zone
  1 zone
  2 zoned
  3 zones
  2 zoology
  1 zoroaster

因此,这会将文本拆分为连续的10000行块,并行使用以对每个块进行排序,然后使用sort -m将已排序的块合并为一个完整的排序。

接下来的方法是在分裂阶段而不是合并阶段进行艰苦的工作,以便部分结果可以通过简单的猫合并在一起:

  $ rm tmp/*
  $ letters="a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9"
  $ time (
    cd tmp; 
    parallel sed -e "/^{}/w{}.txt" ../moby-dick-words.txt ::: $letters >& /dev/null;
    parallel sort {}.txt -o {}.sorted.txt ::: $letters;  
    cat *.sorted.txt > ../moby-dick-words-sorted-split.txt;
    rm *.txt )

  real  0m1.015s
  user  0m2.355s
  sys   0m0.510s
  $ diff moby-dick-words-sorted-split.txt moby-dick-words-sorted.txt
  $ uniq -c moby-dick-words-sorted-split.txt | tail
  1 zeuglodon
  1 zigzag
  5 zodiac
  1 zogranda
  4 zone
  1 zone
  2 zoned
  3 zones
  2 zoology
  1 zoroaster

这里我们(并行)将文件拆分为该行的第一个字符;单独排序这些文件;然后合并是一个简单的连接。

请注意,这仅用于娱乐/教育目的;更高版本的gnu sort内置了并行性(查看--parallel选项),这将比这更好。在this answer中可以看到合并方法的更加光滑的版本。