如果在创建数组期间定义了 NumPy 数组的元素,为什么 Cython 需要更多 Python 次调用?
Why does Cython needs more Python calls if elements of NumPy array are defined during array creation?
如果我在数组创建期间定义数组元素 (#-1-
),我不明白为什么 Cython 需要更多 Python 次调用来编译我的 .pyx
文件。
对于元素pos1
和pos2
,PyFloat_FromDouble
被调用了四次,每个变量调用两次,但是如果我创建一个空数组或零,然后更改元素 (#-2-
)。
import cython
import numpy as np
cimport numpy as np
from libc.math cimport sin
from libc.math cimport cos
@cython.boundcheck(False)
@cython.binding(False)
@cython.wraparound(False)
cpdef np.ndarray[np.float64_t, ndim = 2] mat (double alfa):
cdef double pos1 = cos(alfa * 0.01745)
cdef double pos2 = sin(alfa * 0.01745)
cdef np.ndarray[np.float64_t, ndim = 2] mat_ret
#-1-
mat_ret = np.array([[pos1, pos2, 0.0],
[pos1, pos2, 0.0],
[ 0.0, 0.0, 0.0]], dtype = np.float64)
#-2-
mat_ret = np.zeros((3,3), dtype = np.float64)
mat_ret[0,0] = pos1
mat_ret[0,1] = pos2
mat_ret[1,0] = pos1
mat_ret[1,1] = pos2
return mat_ret
我正在使用 Python 2.7.13、NumPy 1.13.1 和 Cython 0.25.2
这不足为奇。你的 pos1
和 pos2
是 C 双打,但如果你将它们插入列表(代码中的 [pos1, pos2, 0.0]
)它们需要是 Python 对象,因为列表存储 PyObject
指针,因此调用 PyFloat_FromDouble
。你实际上创建了 3 个包含 2 pos1
和 2 pos2
的列表,所以你最终将创建 4 个列表 - 外部列表和内部 3 - 并调用 PyFloat_FromDouble
4 次。它将调用 np.array
,这些值将再次转换为 double
s!
另一方面,如果您使用 "appropriate" dtype 创建一个 np.zeros
数组,它可以只插入 double
s。因为它不必将它们插入中间 Python 对象中,所以根本不需要将它们装箱 (PyFloat_FromDouble
)。
如果我在数组创建期间定义数组元素 (#-1-
),我不明白为什么 Cython 需要更多 Python 次调用来编译我的 .pyx
文件。
对于元素pos1
和pos2
,PyFloat_FromDouble
被调用了四次,每个变量调用两次,但是如果我创建一个空数组或零,然后更改元素 (#-2-
)。
import cython
import numpy as np
cimport numpy as np
from libc.math cimport sin
from libc.math cimport cos
@cython.boundcheck(False)
@cython.binding(False)
@cython.wraparound(False)
cpdef np.ndarray[np.float64_t, ndim = 2] mat (double alfa):
cdef double pos1 = cos(alfa * 0.01745)
cdef double pos2 = sin(alfa * 0.01745)
cdef np.ndarray[np.float64_t, ndim = 2] mat_ret
#-1-
mat_ret = np.array([[pos1, pos2, 0.0],
[pos1, pos2, 0.0],
[ 0.0, 0.0, 0.0]], dtype = np.float64)
#-2-
mat_ret = np.zeros((3,3), dtype = np.float64)
mat_ret[0,0] = pos1
mat_ret[0,1] = pos2
mat_ret[1,0] = pos1
mat_ret[1,1] = pos2
return mat_ret
我正在使用 Python 2.7.13、NumPy 1.13.1 和 Cython 0.25.2
这不足为奇。你的 pos1
和 pos2
是 C 双打,但如果你将它们插入列表(代码中的 [pos1, pos2, 0.0]
)它们需要是 Python 对象,因为列表存储 PyObject
指针,因此调用 PyFloat_FromDouble
。你实际上创建了 3 个包含 2 pos1
和 2 pos2
的列表,所以你最终将创建 4 个列表 - 外部列表和内部 3 - 并调用 PyFloat_FromDouble
4 次。它将调用 np.array
,这些值将再次转换为 double
s!
另一方面,如果您使用 "appropriate" dtype 创建一个 np.zeros
数组,它可以只插入 double
s。因为它不必将它们插入中间 Python 对象中,所以根本不需要将它们装箱 (PyFloat_FromDouble
)。