Python Cython中complex.real和creal(complex)之间的差异
在cython中,为了将真实部分与复杂部分分开,我通常使用Python Cython中complex.real和creal(complex)之间的差异,python,cython,complex-numbers,complextype,Python,Cython,Complex Numbers,Complextype,在cython中,为了将真实部分与复杂部分分开,我通常使用complex.real和complex.imag来完成这项工作。然而,这确实会生成在html-输出中被涂成轻微“python红色”的代码,我想我应该使用creal(complex)和cimag(complex) 考虑下面的示例: cdef double complex myfun(): cdef double complex c1,c2,c3 c1=1.0 + 1.2j c2=2.2 + 13.4j c3
complex.real
和complex.imag
来完成这项工作。然而,这确实会生成在html
-输出中被涂成轻微“python红色”的代码,我想我应该使用creal(complex)
和cimag(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
向c3
的分配给出:
\uuuuPyx_v_c3=\uuPyx_c_c1(\uuuPyx_t_Udouble_Ucomplex_Ufrom_uparts(\uuPyx_v_c2),0),\uPyx_c_c_c1(\uuuPyx_v_c1,\uuuPyx_Udouble_Ucomplex_Ufrom_Uparts(\uPyx_CIMAG,0)),0)代码>
\uuuupyx\uv\uC3=\uuupyx\uC\uSum(\uuupyx\uT\uDouble\uComplex\uU from_uParts(creal(\uupyx\uV\uC2),0),\uupyx\uC\uProduct(\uupyx\uV\uC1,\uuuuuupyx\uT\uDouble\uU complex\u from_uuparts(\uuuuupyx\uCimag(\upyx\uV\uC2)),0))代码>
\uuuupyx\uv\uc3=\uuupyx\uc\u和(\uuuupyx\ut\udouble\ucomplex\uu来自各部分(creal(\uuuupyx\uv\uc2),0),\uuupyx\uc\uprod(\uuuupyx\uv\uc1,\uuuuuuupyx\udouble\u complex\u来自各部分(cimag(\upyx\uv\uc2),0))代码>
其中第一行使用(python颜色的)构造\uuupyx\ucreal
和\uupyx\ucimag
这是为什么?它是否“显著”影响性能?当然是默认的C库
()行得通
给你
然而,这个库似乎不会给您带来任何显著的改进
与c.real
c.imag
方法相比。通过将代码放入
使用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
我使用Windows7和Python2.7,这两个版本中没有可用的complex.h
Visual Studio编译器9.0的内置C库(与Python 2.7兼容)。
因此,我创建了一个等价纯C函数来检查任何可能的
与c.real
和c.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]
得到了时间安排:
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.real
和c.imag
已经足够快了。事实上,你不应该期望看到任何区别:\uuupyx\ucreal(c)
和\uuupyx\ucimag(c)
可以查找,而且不涉及火箭科学/黑魔法:
#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
它基本上是说,这些是定义并导致呼叫没有以下开销:
<>代码> STD::Fielal.Real.(/<)/<代码>和<>代码:STD:::COMPUTION IMAGE()/CUT>(如果是C++)/LI>
\uuuuu real\uuuuu
和\uuuuu imag\uuuuu
,如果是gcc或英特尔编译器(英特尔不久前添加了支持)
你无法打败它,例如,creal
使用\uuuu real\uuuu
。剩下的是Microsoft编译器(CYTHON\u CCOMPLEX
未定义),用于:
#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编译器没有区别,我不会为其他编译器的区别而烦恼太久
#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