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

8

当我将单个值分配给多维内存视图的切片时,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]]

按预期打印出来了。我现在将其重命名为bug.pyx ,使用Cython编译它,然后在同一目录下的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[:, :] 替换它,它就能工作。同时,如果我给 a 的第一维度赋值,a[:1, :] = 1,它也能工作。

这是已知问题吗?或者我对 Cython 内存视图的这种看似基本的使用方式有误解吗?


您确定输入数组是连续的吗? - berardig
如果我们在纯Python中打印print(a.flags),我们会看到a确实是C连续的,因此int[:, ::1] a是正确的。然而,print(a[:, :1].flags)不是!我猜这就是问题的根源。 - jmd_dk
2
这确实是Cython中的一个bug。现在已经被修复了。 - jmd_dk
@jmd_dk,您能否将其写成答案而不是评论? - Roland Weber
1个回答

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接