Кажется, что 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?