stingray icon indicating copy to clipboard operation
stingray copied to clipboard

replace numpyfft with scipyfft for better performance

Open Sauravroy34 opened this issue 10 months ago • 9 comments

it seems that scipy.fft is faster than numpy fft sources

1 ) https://stackoverflow.com/questions/6363154/what-is-the-difference-between-numpy-fft-and-scipy-fftpack 2 ) https://medium.com/@corentin.soubeiran/whos-the-most-efficient-fft-techniques-in-python-boosting-performance-and-understanding-d19b6641d6d8

Sauravroy34 avatar Feb 26 '25 05:02 Sauravroy34

1_qKnX4-MhBzj5LL3thLXW6g

Sauravroy34 avatar Feb 26 '25 05:02 Sauravroy34

compared to other avialble options numpy fft and scipy fft seem to have higher accuracy as well

Sauravroy34 avatar Feb 26 '25 05:02 Sauravroy34

@Sauravroy34 interesting, thanks. Do you have measurements for the 1D transform we use as well?

matteobachetti avatar Feb 26 '25 07:02 matteobachetti

sure , i could not find data for 1 d in internet so i decided of making one

import numpy as np
import scipy.fft
import timeit
import matplotlib.pyplot as plt

# Different sizes of input signals
sizes = [2**i for i in range(5, 21)]  
import pyfftw
def benchmark_fft(lib, size):
    x = np.random.random(size)
    if lib == 'numpy':
        return timeit.timeit(lambda: pyfftw.interfaces.numpy_fft.fft(x), number=10) / 10
    elif lib == 'scipy':
        return timeit.timeit(lambda: pyfftw.interfaces.scipy_fft.fft(x), number=10) / 10

numpy_times = [benchmark_fft('numpy', size) for size in sizes]
scipy_times = [benchmark_fft('scipy', size) for size in sizes]


plt.figure(figsize=(10, 6))
plt.plot(sizes, numpy_times, label='pyfftw NumPy FFT', marker='o')
plt.plot(sizes, scipy_times, label='pyfftw SciPy FFT', marker='s')
plt.xlabel('Input Size')
plt.ylabel('Time (seconds)')
plt.xscale('log')
plt.yscale('log')
plt.legend()
plt.title('Comparison of FFT Computation Time: NumPy vs SciPy')
plt.grid(True, which='both', linestyle='--', linewidth=0.5)
plt.show()

using pyfftw interfaces

output

Sauravroy34 avatar Feb 26 '25 08:02 Sauravroy34

import numpy as np
import scipy.fft
import timeit
import matplotlib.pyplot as plt

# Different sizes of input signals
sizes = [2**i for i in range(5, 21)]  

def benchmark_fft(lib, size):
    x = np.random.random(size)
    if lib == 'numpy':
        return timeit.timeit(lambda: np.fft.fft(x), number=10) / 10
    elif lib == 'scipy':
        return timeit.timeit(lambda: scipy.fft.fft(x), number=10) / 10

numpy_times = [benchmark_fft('numpy', size) for size in sizes]
scipy_times = [benchmark_fft('scipy', size) for size in sizes]


plt.figure(figsize=(10, 6))
plt.plot(sizes, numpy_times, label='NumPy FFT', marker='o')
plt.plot(sizes, scipy_times, label='SciPy FFT', marker='s')
plt.xlabel('Input Size')
plt.ylabel('Time (seconds)')
plt.xscale('log')
plt.yscale('log')
plt.legend()
plt.title('Comparison of FFT Computation Time: NumPy vs SciPy')
plt.grid(True, which='both', linestyle='--', linewidth=0.5)
plt.show()

normal scipy fft and numpy fft

raw2

Sauravroy34 avatar Feb 26 '25 08:02 Sauravroy34

@Sauravroy34 would you mind re-running the benchmark inverting the order of the calls to numpy and scipy?

Just as a sanity check

matteobachetti avatar Feb 26 '25 08:02 matteobachetti

@Sauravroy34 would you mind re-running the benchmark inverting the order of the calls to numpy and scipy?

Just as a sanity check

inverting the calls seems to have reverse effect on plots it might be due to some caching effect i will try to create a uniform benchmark for both of them and post update here

Sauravroy34 avatar Feb 26 '25 08:02 Sauravroy34

@matteobachetti in this comment the benchmark was conducted https://github.com/StingraySoftware/stingray/issues/369#issuecomment-603697909 Screenshot from 2025-02-26 20-15-13 Screenshot from 2025-02-26 20-15-29

Sauravroy34 avatar Feb 26 '25 09:02 Sauravroy34

i have conducted few test myself here is the notebook https://github.com/Sauravroy34/Benchmark_test_for_scipy_and_numpy

new

Sauravroy34 avatar Feb 26 '25 09:02 Sauravroy34