在Linux中洗牌文件行的最快方法

在Linux中洗牌文件行的最快方法,linux,bash,unix,Linux,Bash,Unix,我想在Linux中洗牌一个包含数百万行字符串的大文件。我尝试了“sort-R”,但速度非常慢(一个16M大的文件需要50分钟)。有没有更快的实用程序可以替代它?根据您的描述,这50分钟并不是由实际的排序机制造成的。等待/dev/random生成足够的熵可能会花费时间 一种方法是使用外部随机数据源(例如)以及一个变量。施瓦茨变换将要排序的数据转换为嵌入排序键的“丰富”数据。使用键对数据进行排序,然后丢弃键 要将此应用于您的问题,请执行以下操作: 生成一个随机数的文本文件,每行1行,行数与要排序的

我想在Linux中洗牌一个包含数百万行字符串的大文件。我尝试了“sort-R”,但速度非常慢(一个16M大的文件需要50分钟)。有没有更快的实用程序可以替代它?

根据您的描述,这50分钟并不是由实际的排序机制造成的。等待
/dev/random
生成足够的熵可能会花费时间

一种方法是使用外部随机数据源(例如)以及一个变量。施瓦茨变换将要排序的数据转换为嵌入排序键的“丰富”数据。使用键对数据进行排序,然后丢弃键

要将此应用于您的问题,请执行以下操作:

  • 生成一个随机数的文本文件,每行1行,行数与要排序的文件相同。这可以在任何时候完成,在后台运行,在不同的服务器上运行,从random.org下载,等等。关键是在尝试排序时不会生成这种随机性

  • 使用
    粘贴
    创建文件的增强版本:

    paste random\u number\u file.txt string\u data.txt>tmp\u string\u data.txt

  • 对该文件进行排序:

    sort tmp\u string\u data.txt>sorted\u tmp\u string\u data.txt

  • 删除随机数据:

    cut-f2-sorted_tmp_string_data.txt>random_string_data.txt


这是基本思想。我试过了,它确实有效,但我没有1600万行文本或1600万行随机数。您可能希望将这些步骤中的一些通过管道传输,而不是全部保存到磁盘。

使用
shuf
而不是
sort-R
()

sort-R
的慢度为
shuf
只是做一个随机排列,所以它没有那个问题

(这是在一篇评论中提出的,但由于某些原因,任何人都没有将其作为答案写下来)

您可以尝试我的工具:。它能够在合理的时间内洗牌数百GB的文件

下面是有关洗牌实现的详细信息。它需要指定batchSize—写入输出时要保留在RAM中的行数。越多越好(除非您的RAM不足),因为总洗牌时间为(sourceFile中的行数)/batchSize*(完全读取sourceFile的时间)。请注意,程序洗牌整个文件,而不是每批洗牌一次

算法如下

  • 计算源文件中的行数。这只需逐行读取整个文件即可完成。(参见一些比较)这也给出了一次读取整个文件所需时间的度量。因此,我们可以估计进行一次完整的洗牌需要多少次,因为它需要Ceil(linesCount/batchSize)完整的文件读取

  • 现在我们知道了linesCount的总数,我们可以创建一个linesCount大小的索引数组,并使用(在代码中称为orderArray)将其洗牌。这将给我们一个顺序,我们希望在一个无序文件中有行。请注意,这是整个文件的全局顺序,而不是每个批、块或其他内容

  • 现在是实际代码。我们需要按照刚刚计算的顺序从sourceFile中获取所有行,但无法在内存中读取整个文件。所以我们就把任务分了

    • 我们将遍历源文件,读取所有行,并仅在内存中存储orderArray的第一个batchSize中的行。当我们得到所有这些行时,我们可以按要求的顺序将它们写入outFile,这是一个批量大小/行完成的工作
    • 接下来,我们将一次又一次地重复整个过程,获取orderArray的下一部分,并从头到尾读取每个部分的源文件。最终整个orderArray都被处理了,我们就完成了
  • 它为什么有效?

    因为我们所做的只是从头到尾读取源文件。No向前/向后搜索,这就是HDD喜欢的。根据内部HDD缓冲区、FS块、CPU cahce等将文件分块读取,所有内容都按顺序读取

    一些数字


    在我的机器(Core i5,16GB RAM,Win8.1,HDD东芝DT01ACA200 2TB,NTFS)上,我能够在大约5小时内使用350000的批大小洗牌132 GB(840000行)的文件。批量大小为2 000 000,大约需要8小时。阅读速度约为每秒118000行。

    Shuf?16MB文件有数百万行:您有非常短的行吗?顺便说一句:16MB不是很大。它将适合核心,我想排序将花费不到一秒钟的时间。@AndersLindahl:Shuf介绍的熵是什么?它是否像“sort-R”一样随机@wildplasser:哦……这是一个1600万行的文件,而不是16MB。这个文件的排序速度很快,但“sort-R”非常慢。@alpha\u cod:我猜它是
    /dev/random
    。您可以使用
    --random source
    控制熵源。我怀疑这是问题所在:使用
    sort-R
    (与使用
    shuf
    的4秒相比),我在8分钟内获得了100%的cpu使用率。如果它在等待更多的熵,那么cpu的使用将是最小的,对吗?根据这个线程上的注释
    shuf
    将所有内容加载到内存中,因此任何太大而无法加载到内存中的文件都将失败。这本身不是一个问题,但如果你试图用合法的大文件来实现这一点,这是一个问题。