为了测试Pypy JIT明显更快的说法,我写了一个简单的代码,重复添加两个大小为1200x1200的数组。我的代码如下
import numpy as np
import random
a=np.zeros((1200, 1200), dtype=np.float32)
b=np.zeros((1200, 1200), dtype=np.float32)
import timeit
#Start timer
start=timeit.default_timer()
#Initialize the arrays
for j in range(1200):
for k in range(1200):
a[j][k]=random.random()
b[j][k]=random.random()
#Repeatedly add the arrays
for j in range(10):
a=np.add(a,b)
#Stop timer and display the results
stop=timeit.default_timer()
print stop-start
使用普通的python执行时间约为1.2 - 1.5秒。然而对于Pypy它超过15秒? 同样在上面的例子中,我只添加了10次数组。如果我将此值增加到1000,我的计算机将停止响应。我发现这是因为在使用pypy时几乎消耗了整个RAM。难道我做错了什么?或者是其他问题?
答案 0 :(得分:1)
numpy.ndarray objects not garbage collected
Reducing numpy memory footprint in long-running application
有两种解决方案。最简单的方法是通过执行以下操作告诉pypy删除数组:
import gc
del my_array
gc.collect()
这将迫使pypy进行垃圾收集。请注意,gc.collect()不应该被置于紧密的循环中,除非它确实非常必要。
第二个更手动的解决方案是使用CFFI自己创建数组,并使用数组接口告诉他们:https://docs.scipy.org/doc/numpy/reference/arrays.interface.html
这样你仍然可以从numpy操作struct,但你可以手动删除/调整数组大小。
答案 1 :(得分:0)
在这种情况下,JIT无法提供帮助,因为在python代码中花费的时间非常少。 NumPy是用C语言编写的,因此JIT无法查看该代码并使其更快。事实上,PyPy在这种情况下受到影响,因为用RPython编写的PyPy和用C编写的NumPy之间的阻抗匹配意味着每次从PyPy调用NumPy函数时,必须运行额外的转换代码来准备和调用C函数。
CFFI专门针对此用例编写,调用C所需的转换已在对象创建时处理,因此程序可以更加无缝地运行。
内存问题是一个单独的问题,应该修复,请参阅上面的垃圾收集问题的答案。