2

.pyx如果我在数组创建期间定义数组元素( ),我不明白为什么 Cython 需要更多 Python 调用来编译我的文件#-1-

对于元素pos1pos2PyFloat_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

4

1 回答 1

2

这应该不足为奇。你的pos1andpos2是 C 的双精度数,但是如果你将它们插入到一个列表中([pos1, pos2, 0.0]在你的代码中),它们需要是 Python 对象,因为列表存储PyObject指针,因此调用PyFloat_FromDouble. 而且您确实创建了 3 个包含 2pos1和 2的列表,pos2因此您最终将创建 4 个列表 - 外部列表和内部 3 - 并调用PyFloat_FromDouble4 次。并且它将调用np.array这些值将double再次转换为 s 的位置!

另一方面,如果您np.zeros使用“适当的” dtype 创建一个数组,它可以只插入doubles. 因为它不必将它们插入到中间 Python 对象中,所以根本不需要将它们装箱 ( PyFloat_FromDouble)。

于 2017-08-12T14:23:56.793 回答