用于从大列表计算所有差值的算法

时间:2014-03-11 18:03:11

标签: performance algorithm large-data-volumes

我有一个问题,现在我有一个包含300万条记录的列表,我希望得到每两条记录之间的所有差值。一个简单的嵌套循环可能需要永远。有人能建议我能解决这个问题吗?

2 个答案:

答案 0 :(得分:5)

如果要计算所有绝对差异的平均值并对时间戳进行排序,则只需要一个循环:

t[i] <= t[i + 1]    -->    abs(t[i] - t[j]) = t[j] - t[i]    for    i < j

也就是说,对于每个N时间戳差异,存在带有正号的加数和带有负号的另一个加数。让我们看一个有4个时间戳的例子:

sum = (t[3] - t[2]) + (t[3] - t[1]) + (t[3] - t[0])
    + (t[2] - t[1]) + (t[2] - t[0]) 
    + (t[1] - t[0])

此处,t[3]总是被添加,t[2]被添加两次并减去一次,t[1]被添加一次并减去两次,最后最低值t[0]总是减去。

矿石,更一般:第一个时间戳,即具有最低值的时间戳,始终为负号,N - 1次。第二个具有N - 2次负号并且一次为正号,即在比较第一个时间戳时。第三次有N - 3次负号和正号两次。

所以你的循环是这样的:

sum = 0;
for i = 0 to N:
    sum = sum + (2*i - N + 1) * t[i]

其中i是从零开始的索引而N是独占上限,C风格。要获得平均值,除以(N - 1) * N / 2

如果你的数组没有排序,你必须先对它进行排序,这通常比二次时间具有更好的性能,所以你应该比使用嵌套循环更好。

可能发生的一件事是,通过总结大值,您可以达到数据类型的极限。您可以尝试通过将循环减半并从两端开始求和来解决这个问题,希望差异可以取消。或者你可以除以循环内部的差异总数,可能会引入一些讨厌的浮点舍入错误。

答案 1 :(得分:2)

您可以通过将文件拆分为8个块并同时处理它们并充分利用您支付的昂贵的Intel iCore来并行化问题....

使用split命令生成列表。

#!/bin/bash
split -l 375000 yourfile sublist      # split into lumps of 375,000 subfiles called sublist*
for f in sublist*                     # for all list* files
do
   # Start a background process to work on one list
   echo start processing file $f in background &    
done
wait                                  # till all are finished