Python pypy:高效求数组/向量绝对值差的和
我正在尝试减少我的脚本计算时间,这个脚本是用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能发现并进行优化。而前面提到的两种方法只需要遍历一次,所以会更快。