Отсутствует атрибут numpy при использовании Cython - PullRequest
0 голосов
/ 28 октября 2018

У меня очень простой модуль Cython под названием empty_test.pyx:

cimport numpy as cnp


cpdef return_empty():
    return cnp.empty(0, dtype=np.int32)

Когда я пытаюсь запустить return_empty, я получаю эту ошибку:

empty_test.pyx:5:14: cimported module has no attribute 'empty'

Это мой setup.py file:

from distutils.core import setup
from Cython.Build import cythonize

import numpy as np
setup(
    ext_modules=cythonize(['empty_test.pyx'],
    ),
    include_dirs = [np.get_include()],
)

Мне известно, что я мог бы попробовать import numpy as np вместо cimport numpy as np, но я пытаюсь использовать версии кода N с кодом n.

1 Ответ

0 голосов
/ 28 октября 2018

Чтобы добиться этого, вы должны получить прямой доступ к C-API numpy, который, по крайней мере, частично упакован Cython. В вашем случае вам нужно PyArray_SimpleNew, что уже связано с numpy .

Таким образом, ваша функция становится:

%%cython
cimport numpy as cnp

cnp.import_array()  # needed to initialize numpy-API

cpdef return_empty():
    cdef cnp.npy_intp dim = 0
    return cnp.PyArray_SimpleNew(1, &dim, cnp.NPY_INT32)

А сейчас:

>>> return_empty()
array([], dtype=int32)

Очевидно, что из-за подсчета ссылок все еще есть некоторые издержки Python, но они намного меньше, чем при использовании np.empty():

>>> %timeit return_empty()   
159 ns ± 2.81 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
>>> %timeit return_empty_py
751 ns ± 8.3 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

Использование PyArray_SimpleNew также быстрее (примерно в 3 раза), чем использование array в Cython (как вы считаете в другом вопросе ):

%%cython
from cython.view cimport array as cvarray

# shape=(0,) doesn't work
cpdef create_almost_empty_carray():
    return cvarray(shape=(1,), itemsize=sizeof(int), format="i")

и, таким образом:

>>> %timeit create_almost_empty_carray()
435 ns ± 5.85 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

Список использованных функций return_empty_py:

%%cython
cimport numpy as cnp
import numpy as np

cpdef return_empty_py():
    return np.empty(0, np.int32)
...