J'essaie d'accélérer la réponse ici en utilisant Cython. J'essaie de compiler le code (après avoir fait le cygwinccompiler.py
hack expliqué ici ), mais obtenez un fatal error: numpy/arrayobject.h: No such file or directory...compilation terminated
Erreur. Quelqu'un peut-il me dire s'il s'agit d'un problème de code ou d'une subtilité ésotérique avec Cython?
Ci-dessous mon code. Merci d'avance:
import numpy as np
import scipy as sp
cimport numpy as np
cimport cython
cdef inline np.ndarray[np.int, ndim=1] fbincount(np.ndarray[np.int_t, ndim=1] x):
cdef int m = np.amax(x)+1
cdef int n = x.size
cdef unsigned int i
cdef np.ndarray[np.int_t, ndim=1] c = np.zeros(m, dtype=np.int)
for i in xrange(n):
c[<unsigned int>x[i]] += 1
return c
cdef packed struct Point:
np.float64_t f0, f1
@cython.boundscheck(False)
def sparsemaker(np.ndarray[np.float_t, ndim=2] X not None,
np.ndarray[np.float_t, ndim=2] Y not None,
np.ndarray[np.float_t, ndim=2] Z not None):
cdef np.ndarray[np.float64_t, ndim=1] counts, factor
cdef np.ndarray[np.int_t, ndim=1] row, col, repeats
cdef np.ndarray[Point] indices
cdef int x_, y_
_, row = np.unique(X, return_inverse=True); x_ = _.size
_, col = np.unique(Y, return_inverse=True); y_ = _.size
indices = np.rec.fromarrays([row,col])
_, repeats = np.unique(indices, return_inverse=True)
counts = 1. / fbincount(repeats)
Z.flat *= counts.take(repeats)
return sp.sparse.csr_matrix((Z.flat,(row,col)), shape=(x_, y_)).toarray()
Dans votre setup.py
, Le Extension
devrait avoir l'argument include_dirs=[numpy.get_include()]
.
De plus, il vous manque np.import_array()
dans votre code.
-
Exemple setup.py:
from distutils.core import setup, Extension
from Cython.Build import cythonize
import numpy
setup(
ext_modules=[
Extension("my_module", ["my_module.c"],
include_dirs=[numpy.get_include()]),
],
)
# Or, if you use cythonize() to make the ext_modules list,
# include_dirs can be passed to setup()
setup(
ext_modules=cythonize("my_module.pyx"),
include_dirs=[numpy.get_include()]
)
Pour un projet d'un fichier comme le vôtre, une autre alternative consiste à utiliser pyximport
. Vous n'avez pas besoin de créer un setup.py
... vous n'avez même pas besoin d'ouvrir une ligne de commande si vous utilisez IPython ... c'est très pratique. Dans votre cas, essayez d’exécuter ces commandes dans IPython ou dans un script Python normal:
import numpy
import pyximport
pyximport.install(setup_args={"script_args":["--compiler=mingw32"],
"include_dirs":numpy.get_include()},
reload_support=True)
import my_pyx_module
print my_pyx_module.some_function(...)
...
Vous devrez peut-être modifier le compilateur, bien sûr. Cela rend l'importation et le rechargement identiques pour .pyx
fichiers car ils travaillent pour .py
des dossiers.
L'erreur signifie qu'un fichier d'en-tête numpy n'a pas été trouvé lors de la compilation.
Essayez de faire export CFLAGS=-I/usr/lib/python2.7/site-packages/numpy/core/include/
, puis en compilant. Ceci est un problème avec quelques paquets différents. Un bug a été enregistré dans ArchLinux pour le même problème: https://bugs.archlinux.org/task/22326
Un moyen plus simple consiste à ajouter le chemin d'accès à votre fichier distutils.cfg
. Son nom de chemin de Windows 7 est par défaut C:\Python27\Lib\distutils\
. Vous venez d’affirmer le contenu suivant et cela devrait marcher:
[build_ext]
include_dirs= C:\Python27\Lib\site-packages\numpy\core\include
Pour vous donner un exemple à quoi le fichier de configuration pourrait ressembler, tout mon fichier se lit comme suit:
[build]
compiler = mingw32
[build_ext]
include_dirs= C:\Python27\Lib\site-packages\numpy\core\include
compiler = mingw32