我们如何使用unix排序更快地排序?

lam*_*988 25 unix sorting

我们正在对包含37个字段的5GB文件进行排序,并使用5个键对其进行排序.大文件由1000个文件组成,每个文件5MB.

190分钟后仍然没有完成.

我想知道是否还有其他方法可以加快排序速度.我们选择unix排序因为我们不希望它耗尽所有内存,所以任何基于内存的方法都不行.

独立排序每个文件的优点是什么,然后使用-m选项合并排序呢?

Mal*_*olm 41

使用缓冲区在内存中缓存-S.例如,要使用(最多)50%的内存作为排序缓冲区,请执行以下操作:

sort -S 50% file
Run Code Online (Sandbox Code Playgroud)

请注意,现代Unix sort可以并行排序.我的经验是它会自动使用尽可能多的内核.您可以直接使用它进行设置--parallel.要使用4个线程排序:

sort --parallel=4 file
Run Code Online (Sandbox Code Playgroud)

总而言之,您应该将所有内容放入一个文件中并执行以下操作:

sort -S 50% --parallel=4 file
Run Code Online (Sandbox Code Playgroud)

  • 谢谢。这很有用。`sort`“声称”受 CPU 限制到一个内核,但使用不到 10 MB 的内存来对 GB 的文本进行排序:当然这不是最好的。(排序 8.21,Linux 3.13.0-29-generic。)现在它使用 12 GB 的 RAM 和 8 个内核,我相信它会更快。;-) (2认同)

Jen*_*ens 6

  1. 分而治之.如果您首先对N个文件中的每个文件进行排序(并在多处理器上使用不同的CPU),则某种N文件可以更快.然后只需要合并文件(例如sort -m files ...; -m是POSIX,应该得到各种排序的支持;双关语意图).对每个文件进行排序会消耗更少的资源.
  2. 给sort一个快速/ tmp目录
  3. 在盒子外思考:让创建文件的过程立即对数据进行排序
  4. 蛮力:在问题上投入更多硬件(内存,CPU周期):-)
  5. 了解外部排序的概念

  • 我会质疑大部分内容.外部排序时间由I/O主导,而不是由CPU主导.一旦进入多级合并,产生的运行次数和合并次数完全占主导地位,这种情况发生在磁盘速度,而不是CPU速度.而且磁盘不是多核的. (4认同)

use*_*421 5

无论如何,Unix 排序都不是最快的排序。它使用了一种奇怪的实现,可以很容易地在大到需要多次合并传递的数据集上运行,正如您所做的那样。我会四处寻找替代品。您甚至可以考虑将文件加载到数据库中:这样您可能会获得更好的性能,并且之后您肯定会以更方便的形式获得数据。

为了完整性,主要问题是桶排序本身。对于小数据集来说它很快,虽然不如 Quicksort 快,但它产生的运行次数是替换选择的两倍。一旦进入多级合并,运行次数以及合并传递的次数将完全支配 CPU 密集型分发阶段。

多年前,我直接从 Knuth vol 中为 COBOL 实现了一个排序合并包。III、通过替换选择进行分配,并与虚拟运行平衡合并。在足够大的数据集上,它很容易胜过 Unix 排序,随着 N 的增加梯度增加,并且“足够大”并不是当时磁盘大小那么大。


Jon*_*ler 5

使用 Unix 的主要时间消费者之一sort是查找密钥;这不是您在简单排序练习中经常看到的简单比较操作。即使找到其中一个键也是一个相当缓慢的过程。

因此,加快速度的一种方法是sort通过预处理文件使您提到的 5 个键位于每行的前面,然后对数据进行排序(可能使用拆分和合并其他人建议的操作),然后删除密钥。

例如,如果您有以冒号分隔的字段,并且排序键为 1、3、7、10、12,并且它们都是常规的字母排序,那么您可以使用:

awk  -F: '{print "%s:%s:%s:%s:%s:%s\n", $1, $3, $7, $10, $12, $0; }' monster-file |
sort -t: -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 |
sed 's/^[^:]*:[^:]*:[^:]*:[^:]*:[^:]*://'
Run Code Online (Sandbox Code Playgroud)

您甚至可以不用这五个-k选项而只需运行sort -t:. 事实上,您可能可以安排完全使用不同的分隔符(可能是一个控制字符,例如 ^A)来简化代码。您可以使用以下替代字符将关键字段与主记录分开:

awk  -F: '{print "%s:%s:%s:%s:%s^A%s\n", $1, $3, $7, $10, $12, $0; }' monster-file |
sort -t$'\001' |
sed 's/^[^^A]*^A//'
Run Code Online (Sandbox Code Playgroud)

这在参数中使用bash-ism(ANSI-C 引用);和脚本中的项目是您通过键入获得的内容,但您也可以安排符号来提供字符:$'\001'sort^AawksedControl-Abash

awk  -F: '{print "%s:%s:%s:%s:%s'$'\001''%s\n", $1, $3, $7, $10, $12, $0; }' monster-file |
sort -t$'\001' |
sed "s/^[^$'\001']*$'\001'//"
Run Code Online (Sandbox Code Playgroud)

警告:未经测试的脚本。

有一篇关于重新设计 Unix 排序的引人入胜的文章('Theory and Practice in the Construction of a Working Sort Routine',JP Linderman,AT&T Bell Labs Tech Journal,1984 年 10 月)不容易获得(我没有在尽管多次尝试搜索它),这描述了如何/bin/sort改进。即使在所有改进之后,它对复杂排序的建议之一也完全符合这些原则。