0
$\begingroup$

I have been doing a study which part of it includes a comparison of computation time vs window type and length (among some other things in the computation time, however I speak in terms of relative computation time).

I found that among three windows I tested: Hann, Hamming and Blackman; the Blackman window had the slowest computation time (albeit only by ~20ms) with the Hann window outperforming the rest. This was tested over 100 runs for each.

enter image description here

My question is, why is this the case? Is there something specific about the windowing function (as well as FFT length of course) that causes this increase in computation time? Are there any sources for justification that explores this in more depth?

For reference, my input signal samples are 2s long with sampling rate of 2MHz, so a total length of 4,000,000 samples. The code I am using is as follows:

from datetime import datetime
from scipy import signal

for window in ['hann', 'hamming', 'blackman']: #'hamming', 'hann',
    for nperseg in [1024, 2048, 4096, 8192, 16384]: # 1024, 2048, 4096, 8192
        win = signal.windows.get_window(window, nperseg)
        et = 0
        for i in range(0, 100):
            start_time = datetime.now() # time.monotonic()
            f, t, Zxx = signal.stft(x, fs=fs, window=win, nperseg=nperseg)
            end_time = datetime.now() # time.monotonic()
            et += (end_time - start_time).total_seconds() * 1000 # convert to ms
        print(f'Time Taken (window={window},nperseg={nperseg}): {et / 100}ms')
$\endgroup$
7
  • $\begingroup$ As long as you precompute the window, there should be no difference. $\endgroup$
    – Hilmar
    May 18, 2022 at 14:28
  • $\begingroup$ Could you elaborate on precomputing the window? What I am doing is given a stream of input samples at 2MHz sampling rate, I am computing the STFT for individual 2s samples and measuring the time taken to do the computation (after reading of course) and then averaging over 100 runs. $\endgroup$
    – rshah
    May 18, 2022 at 14:33
  • 1
    $\begingroup$ @rshah Before computing the STFT, assign the window to a variable and use that variable to scale your data - don't call the functions that create the window (e.g., hamming) over and over again. $\endgroup$
    – Ash
    May 18, 2022 at 14:39
  • $\begingroup$ @Ash Thank you. However, pre-computing the window still results in these differences in computation time between window functions regardless of the FFT length. $\endgroup$
    – rshah
    May 18, 2022 at 14:59
  • $\begingroup$ @rshah, What is the standard deviation of your measurements? $\endgroup$
    – Ash
    May 18, 2022 at 15:23

2 Answers 2

1
$\begingroup$

I think this is just measurement noise. You would not expect the window to make any difference (if it's precomputed). However the window length should make a small but consistent difference and that's not visible in the data either: executioin time should slightly with window length but it doesn't consistently.

Elapsed real time is always noisy since it highly depends on what else is going on on the system, that interrupts are happening and how long it takes to serve them, who the processes and threads are time sliced etc.

$\endgroup$
2
  • $\begingroup$ Thanks for elaborating! I would have thought that in some cases longer window lengths would not necessarily result in small differences, but I may be wrong. In either case, perhaps this is now an issue of how I measure the time (i.e. using datetime.now()) so perhaps there is another preferred method. $\endgroup$
    – rshah
    May 18, 2022 at 16:24
  • 1
    $\begingroup$ Longer windows require a more expensive FFTs but the number of frames goes down, so it mostly compensates other than the non-linear increase of the FFT execution time with length. $\endgroup$
    – Hilmar
    May 18, 2022 at 16:28
1
$\begingroup$

Some prefer to use the minimum rather than the average compute time. The idea being that the core phenomenon is the «noiseless» compute time, and that noise only ever adds to that time, never subtracts.

I know few reasons why multiplying by a vector of 2048 Hann values should be faster or slower than multiplying by a vector of 2048 Hamming values.

One possibility: If your window had been non power-of-two (eg 2049) and one of the window functions was exactly 0.0f for the final sample, and the compiler recognized this, then perhaps it could dispatch a clean set of 128/256/512-bit simd instructions, load clean 32/64-byte cache lines etc. While in the other case you would get a tail loop costing a few cycles and generally more «mess»?

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.