gpt4 book ai didi

python - 将 cython cdef 扩展数组设置为零

转载 作者:太空宇宙 更新时间:2023-11-04 04:43:39 25 4
gpt4 key购买 nike

是否有一种 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),因此您无法在性能方面提高它。

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

cpc_x[:]=0.0
cpc_y[:]=0.0

cython 会将其转换为 for 循环。另一个额外的优势:即使未使用 @cython.boundscheck(False),生成的 C 代码仍然没有边界检查(__Pyx_RaiseBufferIndexError)。以下是 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;
}
}
}

可以提高性能的是将内存 View 声明为连续的(即 double[::1] 而不是 double[:]。生成的 C a[:]=0.0 的代码将是:

  {
double __pyx_temp_scalar = 0.0;
{
Py_ssize_t __pyx_temp_extent = __pyx_v_a.shape[0];
Py_ssize_t __pyx_temp_idx;
double *__pyx_temp_pointer = (double *) __pyx_v_a.data;
for (__pyx_temp_idx = 0; __pyx_temp_idx < __pyx_temp_extent; __pyx_temp_idx++) {
*((double *) __pyx_temp_pointer) = __pyx_temp_scalar;
__pyx_temp_pointer += 1;
}
}
}

如您所见,连续版本中不再使用 strides[0] - strides[0]=1 在编译期间求值,生成的 C -代码可以得到更好的优化(例如参见 here )。


人们可能会想变聪明并使用低级 memset 函数:

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

然而,对于更大的数组,与使用连续内存 View (即 double[::1],参见 here 示例)相比没有区别。较小尺寸的开销可能更少,但我从来没有关心到检查。

关于python - 将 cython cdef 扩展数组设置为零,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50091523/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com