Cython: назначение одного элемента многомерному срезу памяти

Кажется, что 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, снова запустим make и python3 -c 'import bug; bug.bug()', мы получим

[[1 1]
 [2 2]]

что неправильно. Я не считаю, что декларация int[:, ::1] неверна, поскольку Cython будет жаловаться. Если я заменю его только на int[:, :], он сработает. Кроме того, если я назначу первому измерению a, a[:1, :] = 1, это сработает.

Это известная проблема, или я как-то неправильно понимаю это, казалось бы, базовое использование представлений памяти Cython?


person jmd_dk    schedule 02.05.2019    source источник
comment
Вы уверены, что входной массив непрерывен?   -  person mikewatt    schedule 07.05.2019
comment
Если мы print(a.flags) (в чистом Python, без компиляции), мы увидим, что a действительно является C-непрерывным, поэтому int[:, ::1] a правильно. Однако print(a[:, :1].flags) нет! Я предполагаю, что это источник проблемы.   -  person jmd_dk    schedule 07.05.2019
comment
Это действительно была ошибка в Cython. Сейчас это исправлено.   -  person jmd_dk    schedule 01.06.2019
comment
@jmd_dk Не могли бы вы написать это как ответ вместо комментария?   -  person Roland Weber    schedule 02.06.2019


Ответы (1)


Я отправил отчет об ошибке, и с тех пор проблема была исправлено.

person jmd_dk    schedule 02.06.2019