- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我在 Cython 函数中运行以下代码:
a = np.zeros((3,3,))
b = np.ones((3,3,))
for i in range(1000000):
a += b * i
return a
在此代码中,只有两个 numpy 数组分配。我预计会有 1,000,002 个。当我用自己的类替换 numpy 数组时,我看到它的 __mul__ 函数被调用 1,000,000 次,导致 1,000,000 个对象分配。
numpy 如何知道它不需要在每次迭代时分配临时对象来存储 b * i?
最佳答案
如果你看看 cython 生成的代码,我认为关键是
__pyx_t_1 = PyNumber_Multiply(__pyx_v_b, __pyx_v_i); // some error checking follows
PyNumber_Multiply
是 the standard c-api function to call the multiplication operator因此没有理由相信它的行为方式与普通乘法调用不同。但是,我们可以轻松检查中间体的类型......我取出编译后的 C 文件并插入行
if (__Pyx_PrintOne(0, ((PyObject *)Py_TYPE(__pyx_t_1))) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 11; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
(这只是通过查看 print(type(a))
生成的代码并更改变量名称而获得的。请注意,我没有更改 Python 代码,所以我不相信这会生成一个没有更改的变量'之前不存在)。然后我手动编译了该文件(Linux 上为 gcc -shared -pthread -fPIC -fwrapv -O2 -Wall -fno-strict-aliasing \ -I/usr/include/python3.4m -o filename.so filename.c
)。
这会打印
<class 'numpy.ndarray'>
这确实表明它已经生成了一个普通的 numpy 数组对象作为临时对象,正如您所期望的那样。没有什么神奇的事情发生。
<小时/>作为一个有趣的旁注,我相信 Numba 的最新版本真正能够消除临时性,把整个操作真正做到位。然而,实际上证明您给出的示例可能会发生这种情况有点超出了我的范围(您可以通过在生成的函数上调用 inspect_asm()
来看到它,并注意到有很多加/乘指令,但不是明显的函数调用)。
关于python - 没有 numpy 临时对象?这是怎么做到的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35929202/
我是一名优秀的程序员,十分优秀!