Python pypy:高效求数组/向量绝对值差的和

0 投票
1 回答
1417 浏览
提问于 2025-04-18 08:12

我正在尝试减少我的脚本计算时间,这个脚本是用pypy运行的。它需要计算大量列表/向量/数组之间的绝对差值的成对和。输入向量的长度比较小,介于10到500之间。

到目前为止,我测试了三种不同的方法:

1) 直接的方法,输入为列表:

def std_sum(v1, v2):
distance = 0.0
for (a,b) in izip(v1, v2):
     distance += math.fabs(a-b)
 return distance

2) 使用lambda和reduce,输入为列表:

lzi = lambda v1, v2: reduce(lambda s, (a,b):s + math.fabs(a-b), izip(v1, v2), 0)
def lmd_sum(v1, v2):
    return lzi(v1, v2)

3) 使用numpy,输入为numpy数组:

def np_sum(v1, v2):
    return np.sum(np.abs(v1-v2))

在我的机器上,使用pypy和itertools.combinations_with_replacement生成的500个列表,前两种方法的运行时间非常相似(大约5秒),而numpy的方法明显更慢,大约需要12秒。

有没有更快的计算方法?这些列表是从文本文件中读取和解析的,增加一些预处理时间是可以接受的(比如创建numpy数组)。这些列表包含浮点数,并且大小是相同的,这一点是事先已知的。

我用来进行“基准测试”的脚本可以在这里找到,一些示例数据可以在这里找到。

1 个回答

3

有没有更快的方法来进行计算?这些列表是从文本文件中读取和解析的,如果预处理时间稍微长一点也没关系(比如创建numpy数组)。这些列表里包含浮点数,而且大小是相同的,事先是知道的。

PyPy在优化列表访问方面表现得很好,所以你最好还是使用列表。

有一个方法可以帮助PyPy进行优化,那就是确保你的列表里只包含一种类型的对象。也就是说,如果你从文件中读取字符串,最好不要把它们放到一个列表里,然后再在原地转换成浮点数。相反,应该在读取每个字符串的时候就直接创建浮点数的列表。还有,尽量不要预先分配一个列表,特别是用[None,]*N这种方式,这样PyPy就无法判断所有元素都是同一种类型了。

其次,尽量减少遍历列表的次数。你的np_sum函数会对两个数组进行三次遍历(减法、绝对值、求和),除非PyPy能发现并进行优化。而前面提到的两种方法只需要遍历一次,所以会更快。

撰写回答