Search code examples
pythonpython-3.xslicecythonmemoryview

Cython: Assigning single element to multidimensional memory view slice


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?


Solution

  • I submitted a bug report and the issue has since been fixed.