Cython:将单个元素分配给多维内存视图切片

Posted

技术标签:

【中文标题】Cython:将单个元素分配给多维内存视图切片【英文标题】:Cython: Assigning single element to multidimensional memory view slice 【发布时间】:2019-09-21 09:35:06 【问题描述】:

每当我将单个值分配给多维内存视图的切片时,Cython 似乎使用了错误的跨步,除非切片沿第一个维度。下面我给出一个完整的例子:

# bug.py
import numpy as np

def bug():
    #cdef int[:, ::1] a
    a = 2*np.ones((2, 2), dtype=np.intc)
    a[:, :1] = 1
    print(np.asarray(a))

如果我们在 Python 中运行它(例如python3 -c 'import bug; bug.bug()'),我们会得到

[[1 2]
 [1 2]]

按预期打印出来。我现在用 Cython 编译它,将文件重命名为 bug.pyx,将以下内容保存在同一目录中的 Makefile 中,

# Makefile
python = python3
python_config = $(python)-config
CC = gcc
CFLAGS  = $(shell $(python_config) --cflags) -fPIC
CFLAGS += $(shell $(python_config) --includes)
python_libdir = $(shell $(python) -c "import sysconfig; \
    print(sysconfig.get_config_var('LIBDIR'));")
LDLIBS  = -L$(python_libdir) -Wl,-rpath=$(python_libdir)
LDLIBS += $(shell $(python_config) --libs)
LDFLAGS = $(shell $(python_config) --ldflags) -shared

bug.so: bug.c; $(CC) $(CFLAGS) $(LDFLAGS) $(LDLIBS) -o bug.so bug.c
bug.c: bug.pyx; $(python) -m cython -3 $<

然后运行make。再次运行python3 -c 'import bug; bug.bug()',它现在会获取已编译的bug.so,它会再次打印出来

[[1 2]
 [1 2]]

如果我们现在取消注释cdef 声明,再次运行makepython3 -c 'import bug; bug.bug()',我们得到

[[1 1]
 [2 2]]

这是错误的。我不相信 int[:, ::1] 声明是错误的,因为 Cython 会抱怨。如果我只用int[:, :] 替换它,它就可以工作。另外,如果我分配给aa[:1, :] = 1 的第一个维度,它会起作用。

这是一个已知问题,还是我以某种方式误解了 Cython 内存视图的这种看似基本的用法?

【问题讨论】:

你确定输入数组是连续的吗? 如果我们print(a.flags)(在纯Python中,没有编译),我们看到a确实是C-contiguous,所以int[:, ::1] a是正确的。但是,print(a[:, :1].flags) 不是!我想这是问题的根源。 这确实是 Cython 中的一个错误。现在是fixed。 @jmd_dk 你能把它写成答案而不是评论吗? 【参考方案1】:

我提交了bug report,此后问题一直是fixed。

【讨论】:

以上是关于Cython:将单个元素分配给多维内存视图切片的主要内容,如果未能解决你的问题,请参考以下文章

GO语言切片Slice数组Array的比较;利用多维切片接受EXCEL内容的输出

我可以将可变切片引用重新分配给自身的子切片吗?

如何将numpy.ndarray分配给cython中nogil循环下的临时变量?

Go 切片内存分配

Cython + PyInstaller 创建 EXE 文件

Python 切片分配内存使用情况