我假设您已经在使用@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;
}
}
}
可以提高性能的方法是将内存视图声明为连续的(即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 https://stackoverflow.com/q/49058949/5769463).
人们可能会想要变得聪明并使用低级的memset
-功能:
from libc.string cimport memset
memset(&cpc_x[0], 0, 16*sizeof(double))
然而,对于更大的数组,与连续内存视图的使用相比没有区别(即double[::1]
, see here https://stackoverflow.com/a/48276340/5769463例如)。对于较小的尺寸,开销可能会更少,但我从来没有足够关心去检查。