Python 将cython cdef扩展阵列设置为零

Python 将cython cdef扩展阵列设置为零,python,cython,Python,Cython,是否有cython ic方法将cdef数组设置为零。我有一个具有以下签名的函数: cdef cget_values(double[:] cpc_x, double[:] cpc_y): 函数的调用如下所示: cdef double cpc_x [16] cdef double cpc_y [16] cget_values(cpc_x, cpc_y) 现在我要做的第一件事是将这些数组中的所有内容都设置为零。目前,我正在使用for循环进行此操作,如下所示: for i in range(16):

是否有cython ic方法将
cdef
数组设置为零。我有一个具有以下签名的函数:

cdef cget_values(double[:] cpc_x, double[:] cpc_y):
函数的调用如下所示:

cdef double cpc_x [16]
cdef double cpc_y [16]
cget_values(cpc_x, cpc_y)
现在我要做的第一件事是将这些数组中的所有内容都设置为零。目前,我正在使用for循环进行此操作,如下所示:

for i in range(16):
    cpc_x[i] = 0.0
    cpc_y[i] = 0.0

我想知道这是否是一种没有太多开销的合理方法。我经常调用这个函数,想知道cython中是否有更优雅/更快的方法来实现这一点

我假设,您已经在使用
@cython.boundscheck(False)
,因此在提高it性能方面没有什么可以做的

出于可读性原因,我将使用:

cpc_x[:]=0.0
cpc_y[:]=0.0
cython会将此转换为-循环的
。另一个额外的优点是:即使没有使用
@cython.boundscheck(False)
,生成的C代码仍然没有边界检查(
\uuuuupyx\uRaiseBufferIndexer
)。以下是
a[:]=0.0的结果代码:

  {
      double __pyx_temp_scalar = 0.0;
      {
          Py_ssize_t __pyx_temp_extent_0 = __pyx_v_a.shape[0];
          Py_ssize_t __pyx_temp_stride_0 = __pyx_v_a.strides[0];
          char *__pyx_temp_pointer_0;
          Py_ssize_t __pyx_temp_idx_0;
          __pyx_temp_pointer_0 = __pyx_v_a.data;
          for (__pyx_temp_idx_0 = 0; __pyx_temp_idx_0 < __pyx_temp_extent_0; __pyx_temp_idx_0++) {
            *((double *) __pyx_temp_pointer_0) = __pyx_temp_scalar;
            __pyx_temp_pointer_0 += __pyx_temp_stride_0;
          }
      }
  }
正如人们所看到的,
strips[0]
不再在连续版本中使用-
strips[0]=1
在编译过程中进行评估,得到的C代码可以更好地优化(例如,请参见)


人们可能会想变得聪明,使用低级的
memset
-函数:

from libc.string cimport memset
memset(&cpc_x[0], 0, 16*sizeof(double))

但是,对于更大的阵列,与使用连续内存视图(即
double[::1]
,请参见示例)相比,没有什么不同。较小尺寸的可能会减少开销,但我从来没有认真检查过。

如果您关闭wraparound和boundschecking,这大约是您能够以最快的速度完成的。也就是说,通常分配数组并不是最慢的部分。而不是使用指针数组(这要么需要在堆栈上分配数据,冒堆栈溢出的风险,要么使用malloc/tree并处理手动内存管理。最好只使用np.zero,让numpy来管理内存。谢谢!我最终使用了扁平表示法。Cython太棒了。我不敢相信我等了这么久才使用它。我制作了我的应用程序20x faste不费吹灰之力!
from libc.string cimport memset
memset(&cpc_x[0], 0, 16*sizeof(double))