为什么复数乘法几乎和 python 中的整数乘法一样快?

Why is complex multiplication nearly as fast as integer multiplication in python?

我的印象是复数乘法比实数乘法需要更长的时间,因为它需要 3 multiplications

但是我尝试了以下方法:

a, b = 3, 4
c, d = 5, 6
print(a*c - b*d, a*d + b*c)

e = 3+4j
f = 5+6j
print(e*f)

%timeit a*c - b*d
%timeit a*d + b*c
%timeit e*f
%timeit a*b

得到了

-9 38
(-9+38j)
110 ns ± 0.2 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
102 ns ± 0.193 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
47.2 ns ± 0.942 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
43 ns ± 1.52 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

为什么复数乘法几乎和实数乘法一样快?

我明白 Python 是一门高级语言,但这个结果仍然让我感到困惑...

我能想到的唯一解释是,我的两种计算都达到了如此低的速度,不知何故瓶颈不是计算本身,而是其他原因..


这是我原来想问的问题


我有这个版本的离散傅里叶变换,它使用复杂的操作:

from math import e, pi, cos, sin, log2

def W(n, N):
    theta = n * -1 * 2 * pi / N
    return cos(theta) + 1j*sin(theta)

def dft(signal):
    N = len(signal)
    total = []
    for k in range(N):
        s = 0
        for n in range(N):
            s += signal[n] * W(n*k, N)
        total.append(s)
    return total

我也有这个版本的 DFT,它不使用复杂的运算而是使用两个实数信号,因为信号的虚部被编码到一个实数数组中。

def Wri(n, N):
    theta = n * -1 * 2 * pi / N
    return cos(theta), sin(theta)

def dft_ri(signal_r, signal_i):
    N = len(signal_r)
    tr, ti = [], []
    for k in range(N):
        sr = 0
        si = 0
        for n in range(N):
            a = signal_r[n]
            b = signal_i[n]
            c, d = Wri(n*k, N)
            sr += a*c - b*d
            si += a*d + b*c
        tr.append(sr)
        ti.append(si)
    return tr, ti

使用以下复杂信号

x = np.linspace(0, T, 1024)
def signal2(t):
    return np.where(np.logical_and((t%T>=0), (t%T<np.pi)), t%T+t%T*1j, np.pi+np.pi*1j)

s = list(signal2(x))
sr = list(np.real(s))
si = list(np.imag(s))

这两个 W 花费的时间大致相同

%timeit W(8, 3)
%timeit Wri(8, 3)

产出

464 ns ± 0.756 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
424 ns ± 2.21 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

但是

%timeit dft(s)
%timeit dft_ri(sr, si)

产出

935 ms ± 4.63 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
1.6 s ± 3.04 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

问题

为什么没有复杂运算的DFT比有复杂运算的DFT耗时将近两倍?

您的计时几乎是 100% 的开销。无论哪种方式,实际的硬件级乘法都只是成本的一​​小部分。

尝试使用 NumPy 数组,它的每个元素开销要低得多,你会看到一个不同的故事:

In [1]: import numpy

In [2]: x = numpy.ones(10000)

In [3]: y = x.astype(complex)

In [4]: %timeit x*x
4.2 µs ± 51.5 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

In [5]: %timeit y*y
16.6 µs ± 696 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

In [6]: z = x.astype(int)

In [7]: %timeit z*z
6.54 µs ± 1 µs per loop (mean ± std. dev. of 7 runs, 100000 loops each)

每个元素的时间接近 1 纳秒,而您的时间更像是每个元素 40 到 100。


您在 FFT 实施中看到的性能差异也是由开销造成的。您的运行时间实际上很少花在做数学上。