Я пытаюсь ускорить свой код Numpy и решил, что я хотел бы реализовать одну конкретную функцию, где мой код провел большую часть времени в С.Расширение Numpy с функцией C
Я на самом деле новичок в C , но мне удалось написать функцию, которая нормализует каждую строку матрицы в сумме до 1. Я могу ее скомпилировать, и я проверил ее с некоторыми данными (в C), и он делает то, что я хочу. В этот момент я очень гордился собой.
Теперь я пытаюсь назвать свою славную функцию из Python, где он должен принять массив 2d-Numpy.
Различные вещи, которые я пробовал это
SWIG
SWIG +
numpy.i
ctypes
Моя функция имеет прототип
void normalize_logspace_matrix(size_t nrow, size_t ncol, double mat[nrow][ncol]);
Поэтому он принимает указатель на массив переменной длины и изменяет его на месте.
Я попробовал следующий чистый SWIG интерфейс файла:
%module c_utils
%{
extern void normalize_logspace_matrix(size_t, size_t, double mat[*][*]);
%}
extern void normalize_logspace_matrix(size_t, size_t, double** mat);
Тогда я сделал бы (на Mac OS X 64bit):
> swig -python c-utils.i
> gcc -fPIC c-utils_wrap.c -o c-utils_wrap.o \
-I/Library/Frameworks/Python.framework/Versions/6.2/include/python2.6/ \
-L/Library/Frameworks/Python.framework/Versions/6.2/lib/python2.6/ -c
c-utils_wrap.c: In function ‘_wrap_normalize_logspace_matrix’:
c-utils_wrap.c:2867: warning: passing argument 3 of ‘normalize_logspace_matrix’ from incompatible pointer type
> g++ -dynamiclib c-utils.o -o _c_utils.so
В Python я тогда получаю следующую ошибку при импорте мой модуль:
>>> import c_utils
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: dynamic module does not define init function (initc_utils)
Далее я попробовал этот подход, используя SWIG + numpy.i
:
%module c_utils
%{
#define SWIG_FILE_WITH_INIT
#include "c-utils.h"
%}
%include "numpy.i"
%init %{
import_array();
%}
%apply (int DIM1, int DIM2, DATA_TYPE* INPLACE_ARRAY2)
{(size_t nrow, size_t ncol, double* mat)};
%include "c-utils.h"
Однако, я не получаю дальше, чем это:
> swig -python c-utils.i
c-utils.i:13: Warning 453: Can't apply (int DIM1,int DIM2,DATA_TYPE *INPLACE_ARRAY2). No typemaps are defined.
SWIG, кажется, не найти typemaps, определенные в numpy.i
, но я не понимаю, почему, потому что numpy.i
является в том же каталоге, и SWIG не жалуется, что он не может его найти.
С ctypes я не очень далеко, но потерялся в документах довольно быстро, так как не мог понять, как передать ему 2d-массив, а затем вернуть результат.
Так может кто-нибудь показать мне волшебный трюк, как сделать мою функцию доступной в Python/Numpy?
Я нормализации в лог-пространстве, чтобы избежать числового переполнения. У меня очень длинные, но тонкие матрицы (т. Е. 100 000x10). Это единственный пункт в моем коде, где я должен перебирать строки, которые в соответствии с профилировщиком строк, где код проводит большую часть своего времени. Я тоже посмотрел на cython, но для меня это тоже учебный проект, поэтому я просто хотел бы узнать, как посыпать мой Python некоторым C, если мне нужно. – oceanhug 2010-12-01 04:21:39