Cython appears to use a wrong striding whenever I assign a single value to a slice of a multi-dimensional memory view, except when the slice is along the first dimension. I give a complete example below:
# 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))
If we run this in Python (e.g. python3 -c 'import bug; bug.bug()'
), we get
[[1 2]
[1 2]]
printed out, as expected. I now compile it with Cython by renaming the file to bug.pyx
, have the following saved in a Makefile
in the same directory,
# 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 $<
and run make
. Running python3 -c 'import bug; bug.bug()'
again it now picks up the compiled bug.so
, which again prints out
[[1 2]
[1 2]]
If we now uncomment the cdef
declaration, run make
and python3 -c 'import bug; bug.bug()'
again, we get
[[1 1]
[2 2]]
which is wrong. I do not believe the int[:, ::1]
declaration is wrong, as Cython would then complain. If I replace it with just int[:, :]
it works. Also, if I assign to the first dimension of a
, a[:1, :] = 1
, it works.
Is this a known issue, or am I somehow misunderstanding this seemingly basic usage of Cython memory views?
I submitted a bug report and the issue has since been fixed.