Cython 中 complex.real 和 creal(complex) 的区别
Difference between complex.real and creal(complex) in Cython
为了在 cython 中将真实部分与复杂部分分开,我通常使用 complex.real
和 complex.imag
来完成这项工作。然而,这确实会在 html
- 输出中生成颜色为 "python red" 的代码,我想我应该使用 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
的分配给出:
__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)));
其中第一行使用(python 彩色)构造 __Pyx_CREAL
和 __Pyx_CIMAG
.
这是为什么,它会影响性能吗"significantly"?
肯定是默认的C库
(complex.h) 会起作用
给你。
但是,这个库似乎不会给你任何显着的改进
与 c.real
c.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,它们在
Visual Studio 编译器 9.0 的内置 C 库(与 Python 2.7 兼容)。
因此,我创建了一个 equivalet 纯 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]
在运行之后有以下两个测试函数:
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.real
和 c.imag
已经够快了。
实际上你不应该期望看到任何区别:__Pyx_CREAL(c)
和 __Pyx_CIMAG(c)
可以查找 here,并且不涉及火箭 science/black 魔法:
#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::complex<>.real()
和 std::complex<>.imag()
如果是 c++。
- GNU extensions
__real__
和__imag__
,如果是gcc或者intel编译器(intel前段时间加入了支持)。
你打不过它,例如在 glibc, creal
uses __real__
. What is left, is Microsoft compiler (CYTHON_CCOMPLEX
is not defined), for that 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
通常情况下,不应该his/her自己编写复数实现,但是如果只考虑访问实部和虚部,那么您不会犯太多错误。我不会保证其他功能,但不希望它比通常的 windows 实现慢很多(但如果你有的话,我想看看结果)。
作为结论: gcc/intel 编译器没有区别,我不会为其他编译器的区别担心太久。
为了在 cython 中将真实部分与复杂部分分开,我通常使用 complex.real
和 complex.imag
来完成这项工作。然而,这确实会在 html
- 输出中生成颜色为 "python red" 的代码,我想我应该使用 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
的分配给出:
__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)));
其中第一行使用(python 彩色)构造 __Pyx_CREAL
和 __Pyx_CIMAG
.
这是为什么,它会影响性能吗"significantly"?
肯定是默认的C库 (complex.h) 会起作用 给你。
但是,这个库似乎不会给你任何显着的改进
与 c.real
c.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,它们在
Visual Studio 编译器 9.0 的内置 C 库(与 Python 2.7 兼容)。
因此,我创建了一个 equivalet 纯 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]
在运行之后有以下两个测试函数:
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.real
和 c.imag
已经够快了。
实际上你不应该期望看到任何区别:__Pyx_CREAL(c)
和 __Pyx_CIMAG(c)
可以查找 here,并且不涉及火箭 science/black 魔法:
#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::complex<>.real()
和std::complex<>.imag()
如果是 c++。- GNU extensions
__real__
和__imag__
,如果是gcc或者intel编译器(intel前段时间加入了支持)。
你打不过它,例如在 glibc, creal
uses __real__
. What is left, is Microsoft compiler (CYTHON_CCOMPLEX
is not defined), for that 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
通常情况下,不应该his/her自己编写复数实现,但是如果只考虑访问实部和虚部,那么您不会犯太多错误。我不会保证其他功能,但不希望它比通常的 windows 实现慢很多(但如果你有的话,我想看看结果)。
作为结论: gcc/intel 编译器没有区别,我不会为其他编译器的区别担心太久。