Найти - Пользователи
Полная версия: в Си функции вызвать scipy-функцию
Начало » Python для новичков » в Си функции вызвать scipy-функцию
1
reseacher2011
Для ускорения Питон приложений часть расчетов вынесена в Си-функции, работающие так
void myfunct(const double *x, const double *y, const double *z ... double *out);
x,y,z, ,,, - входные массивы, out - выходной. Причина связана со сложным алгоритмом формирования массива out, нужно организовывать вложенные циклы со сложными условиями внутри и в Питон это очень медленно.

Возникла необходимость при расчете элеентов out обратится к стандартной функции из scipy, переписать на Си которую достаточно сложно. Подскажите как можно решить, возникшую проблему.
doza_and
А как вы используете myfunct?

Если используете модуль ctypes, то наверное подойдет зарегистрировать callback средствами ctypes и изменить сигнатуру вызова.
например так:
void myfunct(const double *x, const double *y, const double *z ... double *out, void (*fp)(void));
см http://docs.python.org/library/ctypes.html
reseacher2011
Спасибо, пытаюсь понять по ссылке что делать :-)


doza_and
А как вы используете myfunct?
Вот эта схема позволила избавиться от Питон циклов, там где очень трудно построить матричное выражение:
void test_funct(const int n, const double* x, double* out){
int i;
double cx ;
for(i=0; i<n; ++i){
cx = *(x++);
*(out++) = 2.*cx;
}
}

def test_funct(t):
res = ndarray(t.shape,dtype='d')
n = t.shape[0]
test.test_funct(n,t.reshape(-1,1).ctypes.data,res.reshape(-1,1).ctypes.data)
return res

t=numpy.linspace(0,1,10);
R=test_funct(t)
но теперь проблема в том, что в Си функции нужно вызывать специальные функции, ну например нужно вместо 2*x вызвать scipy.special.j0(x), пока не понял можно ли это сделать

пока не очень хороший резутьтат:
void test_funct(const int n, const double* x, double* out, double(*fp)(double)){
int i;
double cx ;
for(i=0; i<n; ++i){
cx = *(x++);
*(out++) = fp(cx);
}
}

CMPFUNC = CFUNCTYPE(c_double)

def test_funct(t):
res = ndarray(t.shape,dtype='d')
n = t.shape[0]
test.test_funct(n,t.reshape(-1,1).ctypes.data,res.reshape(-1,1).ctypes.data,CMPFUNC(scipy.special.j0))
return res

./test.py
Traceback (most recent call last):
File "_ctypes/callbacks.c", line 295, in 'calling callback function'
ValueError: invalid number of arguments
Traceback (most recent call last):
File "_ctypes/callbacks.c", line 295, in 'calling callback function'
ValueError: invalid number of arguments
Traceback (most recent call last):
File "_ctypes/callbacks.c", line 295, in 'calling callback function'
ValueError: invalid number of arguments
Traceback (most recent call last):
File "_ctypes/callbacks.c", line 295, in 'calling callback function'
ValueError: invalid number of arguments
Traceback (most recent call last):
File "_ctypes/callbacks.c", line 295, in 'calling callback function'
...
doza_and
Вы неправильно описали функцию и делаете не так как в документации
CMPFUNC = CFUNCTYPE(c_double,c_double)
берет и возвращает double
def J0(v):
return scipy.special.j0(v)
test.test_funct(n,t.reshape(-1,1).ctypes.data,res.reshape(-1,1).ctypes.data,CMPFUNC(J0))
Скорее всего будет работать и как у вас, но всетаки…

Кстати в вашем случае гораздо быстрее будет просто применить j0 к массиву out (гораздо быстрее чем дергать callback)
>>> scipy.special.j0([1,4,3])
array([ 0.76519769, -0.39714981, -0.26005195])
МОжет я ошибаюсь но помоему ваш пример будет выглядеть так:
>>> y=scipy.special.j0(t)
reseacher2011
doza_and
Вы неправильно описали функцию и делаете не так как в документации
CMPFUNC = CFUNCTYPE(c_double,c_double)
берет и возвращает double
def J0(v):
return scipy.special.j0(v)
test.test_funct(n,t.reshape(-1,1).ctypes.data,res.reshape(-1,1).ctypes.data,CMPFUNC(J0))
Скорее всего будет работать и как у вас, но всетаки…



Спасибо! CMPFUNC = CFUNCTYPE(c_double,c_double) решило проблему



Кстати в вашем случае гораздо быстрее будет просто применить j0 к массиву out (гораздо быстрее чем дергать callback)
>>> scipy.special.j0([1,4,3])
array([ 0.76519769, -0.39714981, -0.26005195])
МОжет я ошибаюсь но помоему ваш пример будет выглядеть так:
>>> y=scipy.special.j0(t)
так пример сильно упрощенный, чтобы сосредоточится на сути проблемы
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB