`mode='c'` 在 numpy.ndarray[..., mode='c'] 中做什么?

What does `mode='c'` do in numpy.ndarray[..., mode='c'] do?

我正在修改 cython code 以绘制复值函数图。此代码包含与以下内容等效的内容:

cimport numpy as cnumpy

def do_something():
    # Buffer types only allowed as function local variables, so put
    # this inside a function.
    cdef cnumpy.ndarray[cnumpy.float_t, ndim=3, mode='c'] rgb
    pass

mode='c' kwarg 是做什么的?我不认为这是 the numpy.ndarray documentation (or anywhere else in the numpy documentation), or mentioned in the cython for numpy users documentation/tutorial, or mentioned in cython's working with numpy documentation/tutorial.

上的一个选项

我不精通 cython,但我知道 python 和 C。我从 other questions here 看到这不是一个罕见的论点,但我找不到文档或解释这是做什么的。

我猜它等同于 numpy ndarray docs 中的 order 参数。

参数 mode 映射到 Python 的 buffer protocol's flags:

  • "c"表示PyBUF_C_CONTIGUOUS
  • "fortran" 表示 PyBUF_F_CONTIGUOUS
  • "strided" 表示 PyBUF_STRIDES

还有 "full" 映射到 PyBUF_INDIRECT,因此对 numpy-arrays 没有意义。

知道内存 layout/mode 是“c”或“fortran”会导致生成性能更高的代码,但只有具有这种布局的 numpy 数组(数组的标志必须是 C_CONTIGUOUS=true 对于 mode="c"F_CONTIGUOUS=true 对于 mode="fortran") 将被接受。

另一方面,mode="strided" 会接受任何 numpy ndarray,但生成的 C-code 性能会较差。


血淋淋的细节:

要访问 numpy 数组的内容,Cython 使用 Python 的缓冲协议。每当 Cython 代码中有一个 np.ndarray 时,C-code 中就会有一个对应的 __Pyx_Buffer 变量,由 class BufferEntry 负责生成。

要从数组对象中获取缓冲区,C-function __Pyx_GetBufferAndValidate will be emitted. The mode-argument will be translated into the buffer-protocol flags used by the above function in BufferEntry.get_flags:

def get_flags(buffer_aux, buffer_type):
    flags = 'PyBUF_FORMAT'
    mode = buffer_type.mode
    if mode == 'full':
        flags += '| PyBUF_INDIRECT'
    elif mode == 'strided':
        flags += '| PyBUF_STRIDES'
    elif mode == 'c':
        flags += '| PyBUF_C_CONTIGUOUS'
    elif mode == 'fortran':
        flags += '| PyBUF_F_CONTIGUOUS'
    else:
        assert False
    if buffer_aux.writable_needed: flags += "| PyBUF_WRITABLE"
    return flags