Ani*_*tta 5 python arrays pypy numpy
为了测试 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
Run Code Online (Sandbox Code Playgroud)
对于普通的 python,执行时间约为 1.2 - 1.5 秒。但是使用 Pypy 它会超过 15 秒吗?同样在上述情况下,我只添加了 10 次数组。如果我将此值增加到 1000,我的计算机将停止响应。我发现这是因为使用 pypy 时几乎消耗了整个 RAM。难道我做错了什么?或者问题是其他的?
JIT 在这种情况下无济于事,因为在 python 代码上花费的时间很少。NumPy 是用 C 编写的,因此 JIT 无法查看该代码并使其更快。事实上,PyPy 在这种情况下会受到影响,因为用 RPython 编写的 PyPy 和用 C 编写的 NumPy 之间的阻抗匹配意味着每次从 PyPy 调用 NumPy 函数时都必须运行额外的转换代码来准备和调用 C 函数。
CFFI 是专门为此用例编写的,调用 C 所需的转换已在对象创建时处理完毕,因此程序可以更无缝地运行两者。
内存问题是一个单独的问题,应该修复,请参阅上面垃圾收集问题的答案。
pypy 不会在所有情况下在 numpy 数组中进行垃圾收集,这可能是内存不足、溢出到磁盘然后锁定的原因。
有两种解决方案。最简单的方法是简单地告诉 pypy 通过执行以下操作来删除数组:
import gc
del my_array
gc.collect()
Run Code Online (Sandbox Code Playgroud)
这将强制 pypy 进行垃圾收集。请注意,除非确实有必要,否则不应将 gc.collect() 放入紧密循环中。
第二个更手动的解决方案是使用 CFFI 自己制作数组,并使用数组接口告诉 numpy:https://docs.scipy.org/doc/numpy/reference/arrays.interface.html
这样您仍然可以从 numpy 操作结构,但您可以控制手动删除/调整数组大小。
| 归档时间: |
|
| 查看次数: |
1903 次 |
| 最近记录: |