Уведомления

Группа в Telegram: @pythonsu

#1 Окт. 7, 2011 10:44:38

reseacher2011
От:
Зарегистрирован: 2011-08-08
Сообщения: 7
Репутация: +  0  -
Профиль   Отправить e-mail  

в Си функции вызвать scipy-функцию

Для ускорения Питон приложений часть расчетов вынесена в Си-функции, работающие так

void myfunct(const double *x, const double *y, const double *z ... double *out);
x,y,z, ,,, - входные массивы, out - выходной. Причина связана со сложным алгоритмом формирования массива out, нужно организовывать вложенные циклы со сложными условиями внутри и в Питон это очень медленно.

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



Офлайн

#2 Окт. 7, 2011 11:16:55

doza_and
От:
Зарегистрирован: 2010-08-15
Сообщения: 4138
Репутация: +  253  -
Профиль   Отправить e-mail  

в Си функции вызвать scipy-функцию

А как вы используете 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



Отредактировано (Окт. 7, 2011 11:19:16)

Офлайн

#3 Окт. 7, 2011 20:58:29

reseacher2011
От:
Зарегистрирован: 2011-08-08
Сообщения: 7
Репутация: +  0  -
Профиль   Отправить e-mail  

в Си функции вызвать scipy-функцию

Спасибо, пытаюсь понять по ссылке что делать :-)


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'
...



Отредактировано (Окт. 7, 2011 21:13:45)

Офлайн

#4 Окт. 7, 2011 21:35:03

doza_and
От:
Зарегистрирован: 2010-08-15
Сообщения: 4138
Репутация: +  253  -
Профиль   Отправить e-mail  

в Си функции вызвать scipy-функцию

Вы неправильно описали функцию и делаете не так как в документации

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)



Отредактировано (Окт. 7, 2011 21:39:24)

Офлайн

#5 Окт. 7, 2011 21:47:35

reseacher2011
От:
Зарегистрирован: 2011-08-08
Сообщения: 7
Репутация: +  0  -
Профиль   Отправить e-mail  

в Си функции вызвать scipy-функцию

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)
так пример сильно упрощенный, чтобы сосредоточится на сути проблемы



Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version