Skip to content

Commit

Permalink
Implement saving and loading of pyFFTW wisdom for substantial speedup
Browse files Browse the repository at this point in the history
  • Loading branch information
smallnamespace committed Nov 18, 2015
1 parent 517e3e6 commit b9ebadc
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 8 deletions.
38 changes: 30 additions & 8 deletions nsgt/fft.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@
AudioMiner project, supported by Vienna Science and Technology Fund (WWTF)
"""

import atexit
import numpy as np
import os.path
import pickle
from threading import Timer
from warnings import warn

# Try engines in order of:
Expand Down Expand Up @@ -111,29 +115,47 @@ def init(self, n, measure, outn):
original_fft = np.fft
# Enable cache to keep wisdom, etc.
pyfftw.interfaces.cache.enable()

# Load stored wisdom
PYFFTW_WISDOM_FILENAME = os.path.join(os.path.expanduser("~"), ".nsgt_pyfftw_wisdom.p")
if os.path.isfile(PYFFTW_WISDOM_FILENAME):
with open(PYFFTW_WISDOM_FILENAME, 'rb') as f:
pyfftw.import_wisdom(pickle.load(f))
print("Loaded pyFFTW wisdom from %s" % PYFFTW_WISDOM_FILENAME)

def save_wisdom():
print("Saving pyFFTW wisdom to %s" % PYFFTW_WISDOM_FILENAME)
with open(PYFFTW_WISDOM_FILENAME, 'wb') as f:
pickle.dump(pyfftw.export_wisdom(), f)

# Save wisdom on exit
atexit.register(save_wisdom)
else:
# fall back to numpy methods
warn("nsgt.fft falling back to numpy.fft")
ENGINE = "NUMPY"

if ENGINE in ["PYFFTW", "NUMPY"]:
def get_kwargs(measure):
return ({'planner_effort': 'FFTW_MEASURE' if measure else 'FFTW_ESTIMATE'}
if ENGINE=="PYFFTW" else {})
class fftp:
def __init__(self, measure=False, dtype=float):
pass
self.kwargs = get_kwargs(measure)
def __call__(self,x, outn=None, ref=False):
return np.fft.fft(x)
return np.fft.fft(x, **self.kwargs)
class ifftp:
def __init__(self, measure=False, dtype=float):
pass
self.kwargs = get_kwargs(measure)
def __call__(self,x, outn=None, n=None, ref=False):
return np.fft.ifft(x,n=n)
return np.fft.ifft(x,n=n,**self.kwargs)
class rfftp:
def __init__(self, measure=False, dtype=float):
pass
self.kwargs = get_kwargs(measure)
def __call__(self,x, outn=None, ref=False):
return np.fft.rfft(x)
return np.fft.rfft(x,**self.kwargs)
class irfftp:
def __init__(self, measure=False, dtype=float):
pass
self.kwargs = get_kwargs(measure)
def __call__(self,x,outn=None,ref=False):
return np.fft.irfft(x,n=outn)
return np.fft.irfft(x,n=outn,**self.kwargs)
4 changes: 4 additions & 0 deletions tests/cq_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
from nsgt import NSGT, OctScale
import unittest

# Make test deterministic
np.random.seed(666)


class TestNSGT(unittest.TestCase):

def test_oct(self):
Expand Down
4 changes: 4 additions & 0 deletions tests/fft_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
from nsgt.fft import rfftp, irfftp, fftp, ifftp
import unittest

# Make test deterministic
np.random.seed(666)


class TestFFT(unittest.TestCase):
def __init__(self, methodName, n=10000):
super(TestFFT, self).__init__(methodName)
Expand Down
4 changes: 4 additions & 0 deletions tests/nsgt_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
from nsgt import CQ_NSGT
import unittest

# Make test deterministic
np.random.seed(666)


class Test_CQ_NSGT(unittest.TestCase):

def test_transform(self, length=100000, fmin=50, fmax=22050, bins=12, fs=44100):
Expand Down

0 comments on commit b9ebadc

Please sign in to comment.