2016-06-10 2 views
0

Я пытаюсь сделать сложную экспоненту в Cython.Использование сложных функций C++ в Cython

я смог сколотить следующий код для моего pyx:

from libc.math cimport sin, cos, acos, exp, sqrt, fabs, M_PI, floor, ceil 

cdef extern from "complex.h": 
    double complex cexp(double complex z) 

import numpy as np 
cimport numpy as np 
import cython 
from cython.parallel cimport prange, parallel 

def try_cexp(): 
    cdef: 
     double complex rr1 
     double complex rr2 
    rr1 = 1j 
    rr2 = 2j 

    print(rr1*rr2) 

    #print(cexp(rr1)) 

Обратите внимание, что print(cexp(rr1)) комментируется. Когда линия активна, я получаю следующее сообщение об ошибке при запуске setup.py:

error: command 'C:\\WinPYthon\\Winpython-64bit-3.4.3.6\\python-3.4.3.amd64\\scripts\\gcc.exe' failed with exit status 1 

Обратите внимание, что, когда cexp закомментирована, все работает как ожидается ... Я могу запустить setup.py, и когда я проверить функцию он печатает произведение двух комплексных чисел.

Это мой setup.py файл. Обратите внимание, что он включает в себя код для запуска openmp в Cython с помощью г ++:

from distutils.core import setup 
from Cython.Build import cythonize 
from distutils.extension import Extension 
from Cython.Distutils import build_ext 
import numpy as np 
import os 
os.environ["CC"] = "g++-4.7" 
os.environ["CXX"] = "g++-4.7" 

# These were added based on some examples I had seen of cexp in Cython. No effect. 
#import pyximport 
#pyximport.install(reload_support=True) 

ext_modules = [ 
    Extension('complex_test', 
       ['complex_test.pyx'], 
       language="c++", 
       extra_compile_args=['-fopenmp'], 
       extra_link_args=['-fopenmp', '-lm']) # Note that '-lm' was 
       # added due to an example where someone mentioned g++ required 
       # this. Same results with and without it. 
    ] 

setup(
    name='complex_test', 
    cmdclass={'build_ext': build_ext}, 
    ext_modules=ext_modules, 
    include_dirs=[np.get_include()] 
    ) 

В конечном счете моя цель состоит в том, чтобы ускорить calcualtion, который выглядит как k*exp(z), где k и z являются сложными. В настоящее время я использую числовые выражения, однако у меня большие издержки памяти, и я считаю, что можно оптимизировать дальше, чем может.

Благодарим за помощь.

+0

Вы нашли их быстрее, чем 'cmath'? –

+0

Ну, я изначально пытался сделать свою сложную экспоненту, используя закон Эйлера с синусами и косинусами, но это было не так эффективно, как я надеялся –

+0

Ну ладно, но вы еще пробовали 'cmath'? –

ответ

1

Вы используете cexp вместо exp как есть в C++. Измените ваш cdef extern на:

cdef extern from "<complex.h>" namespace "std": 
    double complex exp(double complex z) 
    float complex exp(float complex z) # overload 

и ваш звонок печати на:

print(exp(rr1)) 

и он должен работать как шарм.


Я знаю компиляции сообщения длинны, но там вы можете найти ошибку, которая указывает на виновника:

complex_test.cpp: In function ‘PyObject* __pyx_pf_12complex_test_try_cexp(PyObject*)’: 
complex_test.cpp:1270:31: error: cannot convert ‘__pyx_t_double_complex {aka std::complex<double>}’ to ‘__complex__ double’ for argument ‘1’ to ‘__complex__ double cexp(__complex__ double)’ 
    __pyx_t_3 = cexp(__pyx_v_rr1); 

это грязно, но вы можете видеть причину. * Вы задаете C++ определенный тип (__pyx_t_double_complex в Cython Jargon) функции C, которая ожидает другого типа (__complex__ double).

+0

Большое вам спасибо! Я не думаю, что когда-нибудь это выдумал. В Интернете нет примеров, которые я видел с этим ответом ... и я бы никогда не подумал об этом. Я чувствую себя очень глупым. Хотя в моей защите кривая обучения Cython крутая. : D Вопрос, хотя @Jim ... что, если я хочу определить функции как для поплавков, так и для парных? Не было бы столкновения? Или будет работать на любом из них? И о, черт возьми, спасибо. –

+0

@KeithL Я уверен, что вы можете перегружать функции без проблем, пытаясь дать ожидаемые результаты. –

+0

Вы правы @ Jim.И мне удалось успешно создать параллельную функцию Cython, но, к сожалению, она все еще не так быстро, как память Numexpr. :(Еще раз спасибо за вашу помощь! Я думаю, что я собираюсь сделать это в Visual Studio как dll и посмотреть, если THAT будет быстрее. –

Смежные вопросы