【问题标题】:Fastest way to delete duplicates in large wordlist? [duplicate]删除大型单词表中重复项的最快方法? [复制]
【发布时间】:2015-11-27 00:25:34
【问题描述】:

类似的问题是made here,但他们没有说明为什么 sortawk 之间存在速度差异。

我首先在Unix Stackexchange 上提出了这个问题,但由于他们告诉我这对于 Stackoverflow 来说是一个很好的问题,所以我会在这里发布。

我需要对一个大的单词表进行重复数据删除。我尝试了几个命令,并做了一些研究herehere,他们解释说,删除单词列表的最快方法似乎是使用 awk,因为 awk 不会对列表进行排序。它使用哈希查找来跟踪项目并删除重复项。由于 AWK 使用哈希查找,他们认为大 O 是这样的

awk --> O(n) ?
排序 --> O(n log n) ?

但是我发现这不是真的。这是我的测试结果。我使用this python script 生成了两个随机词表。

列表 1 = 7 Mb
列表 2 = 690 Mb

测试命令

sort -u input.txt -o output.txt 

awk '!x[$0]++' input.txt > output.txt

结果 AWK:
List1
真正的 0m1.643s
用户 0m1.565s
系统 0m0.062s

列表2
真正的 2m6.918s
用户 2m4.499s
系统 0m1.345s

结果排序:
List1
真正的 0m0.724s
用户 0m0.666s
系统 0m0.048s

列表2
真正的 1m27.254s
用户 1m25.013s
系统 0m1.251s

我一遍又一遍地进行这些测试,并发现了一致的结果。也就是说,SORT 要快得多。有人可以解释为什么以及是否有更快的方法吗?

************ 更新 ***********
可能影响我的结果的事情是强>

  1. 缓存:我已经通过更改顺序排除了这种可能性 在测试中执行
  2. 大 O 符号的常数因子。我认为由于单词列表的大小,它们此时应该变得无关紧要。 (600Mb)
  3. 算法的错误实现:这仍有可能我没有检查 awk 和 sort 的源代码

【问题讨论】:

  • n 在每种情况下是什么?如果您尝试对n 的许多不同值进行此操作,您是否看到awk 的运行时间线性增加,或者sort 的增加为n lg n
  • 您的列表可能有些特别之处。对我来说,awk 按我的预期获胜。试试shuf /usr/share/dict/words > unsorted; time sort -u unsorted -o sort-sorted; time awk '!x[$0]++' unsorted > awk-sorted
  • 将您的 awk 代码添加到您的问题中。
  • 您的测试数据有 很多 个重复项(预计为 99%),sort -u 可以比最坏的情况更有效地处理这些数据。使用来自 500,000 个不同值的 1,000,000 个随机值(而不是来自 1,000,000 个不同值的 100,000,000 个随机值)进行测试,awk 的速度几乎快了 14 倍。
  • 这个问题已经被问过很多次了。这里有一些额外的策略:stackoverflow.com/q/30906191/1172700

标签: bash sorting unix awk processing-efficiency


【解决方案1】:

您的示例输入有 很多 个重复值;在 100,000,000 的样本大小中,您只有 1,000,000 个不同的值,因此您预计只有 1% 的值是唯一的。我不确切知道sort -u 是如何工作的,但可以想象它是一种合并排序,它在每次合并期间过滤唯一值。有效输入大小将远小于 100,000,000。仅使用 1,000,000 个值但从 500,000 个不同的值中选择(因此 50% 而不是 1% 应该是唯一的)重新运行您的命令会产生以下结果:

% time awk '!x[$0]++' randomwordlist.txt > /dev/null
awk ...  1.32s user 0.02s system 99% cpu 1.338 total
% time sort -u randomwordlist.txt -o /dev/null
sort ...  14.25s user 0.04s system 99% cpu 14.304 total

【讨论】:

  • 有趣的是,我已经用 10.000.000 个样本大小和 5.000.000 个不同的值复制了您的实验。但是 sort 仍然快 30% --> sort = 0m10.258s -- awk = 0m16.966s
  • 这可能与操作系统和硬件有关吗?我使用的是 Macbook pro 2015.. 2.7 GHz Intel Core i5
  • 对不起,我的意思是 5.000.000
  • 您可能会达到内存限制,从而产生与交换相关的开销。
  • 我也尝试过使用另一个具有 50% 唯一值的大型单词列表。那里的结果相同。所以这对我来说似乎是一个实施问题..
【解决方案2】:
  1. big-O 表示法仅告诉您存在 一些 N,其中 O(N) 将比 O(N*log N)。实际操作数包括常数因子和附加项,因此实际上数字是
    O(N) ~ k1 * N + c1
    O (N * log N) ~ k2 * N * log(N) + c2
    对于选定的 N
    ,哪个更快 取决于关于 kc 的值。
  2. 某些输入/算法组合会导致非常小的 kc
  3. 任何一个程序都可能不使用最佳算法。
  4. 缓存效果?如果您总是在测试 2 之前运行测试 1,则第二个测试可能会使用已缓存的数据,而第一个测试总是必须从头开始加载。正确消除/确定缓存效果是一门艺术。
  5. 其他一些我没有想到的,其他人会很快指出 :-)

【讨论】:

  • 我认为由于单词列表大小的巨大差异,k 和 c 应该变得无关紧要..(我也使用 20 Gb 的单词列表这样做)我已经排除了更改顺序的缓存效果在这个实验上执行
猜你喜欢
  • 2010-12-13
  • 1970-01-01
  • 2015-10-07
  • 2016-09-06
  • 2018-05-07
  • 1970-01-01
  • 1970-01-01
  • 2017-10-18
  • 1970-01-01
相关资源
最近更新 更多