2017-09-22 34 views
4

要在cython中将实数部分与复杂部分分开,我通常使用complex.realcomplex.imag作为作业。然而,这会产生html输出中带有轻微“python red”颜色的代码,我想我应该使用creal(complex)cimag(complex)代替。Cython中的complex.real和creal(complex)之间的区别

考虑波纹管的例子:

cdef double complex myfun(): 
    cdef double complex c1,c2,c3 
    c1=1.0 + 1.2j 
    c2=2.2 + 13.4j 
    c3=c2.real + c1*c2.imag 
    c3=creal(c2) + c1*c2.imag 
    c3=creal(c2) + c1*cimag(c2) 
    return c2 

的所述assigments到c3给予:

__pyx_v_c3 = __Pyx_c_sum(__pyx_t_double_complex_from_parts(__Pyx_CREAL(__pyx_v_c2), 0), __Pyx_c_prod(__pyx_v_c1, __pyx_t_double_complex_from_parts(__Pyx_CIMAG(__pyx_v_c2), 0)));

__pyx_v_c3 = __Pyx_c_sum(__pyx_t_double_complex_from_parts(creal(__pyx_v_c2), 0), __Pyx_c_prod(__pyx_v_c1, __pyx_t_double_complex_from_parts(__Pyx_CIMAG(__pyx_v_c2), 0)));

__pyx_v_c3 = __Pyx_c_sum(__pyx_t_double_complex_from_parts(creal(__pyx_v_c2), 0), __Pyx_c_prod(__pyx_v_c1, __pyx_t_double_complex_from_parts(cimag(__pyx_v_c2), 0)));

其中冷杉st line使用(python coloured)构造__Pyx_CREAL__Pyx_CIMAG

这是什么,是否会影响性能“显着”?

回答

2

当然默认的C库 (complex.h)会为你工作 。

但是,与c.realc.imag方法相比,看起来这个库不会给你任何显着的改进 。通过将一个 with nogil:块中的代码,你可以检查你的代码已经使得以 的Python API的没有呼叫:

cdef double complex c1, c2, c3 
with nogil: 
    c1 = 1.0 + 1.2j 
    c2 = 2.2 + 13.4j 
    c3 = c2.real + c1*c2.imag 

我使用的是Windows 7和Python 2.7,不具有complex.h可供 Visual Studio编译器9.0的内置C库(与Python 2.7兼容)。 正因为如此我创建一个equivalet纯C函数来检查任何可能 增益相比c.realc.imag

cdef double mycreal(double complex dc): 
    cdef double complex* dcptr = &dc 
    return (<double *>dcptr)[0] 

cdef double mycimag(double complex dc): 
    cdef double complex* dcptr = &dc 
    return (<double *>dcptr)[1] 

运行下面的两个测试功能之后:

def myfun1(double complex c1, double complex c2): 
    return c2.real + c1*c2.imag 

def myfun2(double complex c1, double complex c2): 
    return mycreal(c2) + c1*mycimag(c2) 

得到的定时:

In [3]: timeit myfun1(c1, c2) 
The slowest run took 17.50 times longer than the fastest. This could mean that a 
n intermediate result is being cached. 
10000000 loops, best of 3: 86.3 ns per loop 

In [4]: timeit myfun2(c1, c2) 
The slowest run took 17.24 times longer than the fastest. This could mean that a 
n intermediate result is being cached. 
10000000 loops, best of 3: 87.6 ns per loop 

确认对c.realc.imag已经够快了。

2

其实你不应该期望看到任何区别:__Pyx_CREAL(c)__Pyx_CIMAG(c)可以抬头here,并没有火箭科学/黑魔法参与:

#if CYTHON_CCOMPLEX 
    #ifdef __cplusplus 
    #define __Pyx_CREAL(z) ((z).real()) 
    #define __Pyx_CIMAG(z) ((z).imag()) 
    #else 
    #define __Pyx_CREAL(z) (__real__(z)) 
    #define __Pyx_CIMAG(z) (__imag__(z)) 
    #endif 
#else 
    #define __Pyx_CREAL(z) ((z).real) 
    #define __Pyx_CIMAG(z) ((z).imag) 
#endif 

它基本上说,这些都是定义和铅到一个没有开销的呼叫:

  1. std::complex<>.real()std::complex<>.imag()如果它是C++。
  2. GNU extensions__real____imag__,如果是gcc或intel编译器(intel前段时间支持)。

你不能击败它,在glibccreal使用__real__。而剩下的,是微软编译器(没有定义CYTHON_CCOMPLEX),为使用该an own/special cython-class

#if CYTHON_CCOMPLEX 
    .... 
#else 
    static CYTHON_INLINE {{type}} {{type_name}}_from_parts({{real_type}} x, {{real_type}} y) { 
     {{type}} z; 
     z.real = x; 
     z.imag = y; 
     return z; 
    } 
#endif 

通常情况下,人们不应该写他/她自己的复数执行,但没有这么多,你可以做错误的,如果只考虑到实部和虚部。我不会担保其他功能,但不会期望它比通常的Windows实现速度慢得多(但如果您有一些,希望看到结果)。

作为结论: gcc/intel编译器没有什么区别,我也不会为其他人的差异而烦恼太久。