Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ENH: uarray based backend support for scipy.fft #10383

Merged
merged 30 commits into from Jul 17, 2019
Merged
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
f86dc65
ENH: Add uarray based backend support
peterbell10 Jun 10, 2019
1450a07
ENH: Add pyfftw backend for testing
peterbell10 Jun 20, 2019
712af1c
BENCH: Add benchmark comparing different fft backends
peterbell10 Jun 20, 2019
71fcdb4
MAINT: Update uarray
peterbell10 Jul 1, 2019
4ef6be5
ENH: Properly support backends using __ua_convert__
peterbell10 Jul 1, 2019
cd437c6
ENH: Allow named backends to set functions and wrap register_backend
peterbell10 Jul 1, 2019
6156405
MAINT: Add uarray license
peterbell10 Jul 1, 2019
c1f4034
TST: Simplify fft mock_backend
peterbell10 Jul 1, 2019
4867fed
MAINT: Move uarray into scipy._lib
peterbell10 Jul 2, 2019
5a1c19e
FIX: Don't modify kwargs dict in argument_replacer
peterbell10 Jul 6, 2019
31251ba
MAINT: Update vendored uarray version
peterbell10 Jul 9, 2019
718dde4
STY: Fix PEP8 violations
peterbell10 Jul 9, 2019
b9a31b3
FIX: Update tp_name for Extension classes
peterbell10 Jul 9, 2019
770fadc
BLD: Bump macos min version to 10.9
peterbell10 Jul 10, 2019
3481659
FIX: wrapping of real transform functions
peterbell10 Jul 10, 2019
78827e3
FIX: Sphinx autosummary does not detect uarray multimethods properly
peterbell10 Jul 10, 2019
e56a752
TST: Add hfft to mock backend tests
peterbell10 Jul 11, 2019
72866e3
BENCH: Add fftn to backend benchmarks
peterbell10 Jul 11, 2019
f83a9f5
MAINT: Refactor _inherit_doc into doc_replacer and move to doccer
peterbell10 Jul 11, 2019
89a823c
DOC: Include backend functions in scipy.fft autosummary
peterbell10 Jul 11, 2019
4969bec
CI: Add fft submodule to refguide and test_circular_imports
peterbell10 Jul 11, 2019
f62158b
ENH: Wrap ua.skip_backend in scipy.fft backend control
peterbell10 Jul 11, 2019
fbb2417
DOC: Misc doc tweaks
peterbell10 Jul 11, 2019
4363483
ENH: Use installed uarray if available
peterbell10 Jul 12, 2019
53897b2
MAINT: Seperate vendorded uarray from scipy changes
peterbell10 Jul 15, 2019
c52e824
FIX: Vendored uarray versioning code
peterbell10 Jul 15, 2019
7acf8ba
MAINT: Change __ua_domain__ to numpy.scipy.fft
peterbell10 Jul 15, 2019
621d302
DOC: Fix docstring style issues and expand on usefulness of numpy.sci…
peterbell10 Jul 16, 2019
3604f47
MAINT: Move PyfftwBackend into the benchmark suite to avoid licensing…
peterbell10 Jul 16, 2019
0f47e36
DOC: Remove returns section for set_backend and skip_backend
peterbell10 Jul 16, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions LICENSES_bundled.txt
Expand Up @@ -163,3 +163,8 @@ Name: pypocketfft
Files: scipy/fft/_pocketfft/[pocketfft.h, pypocketfft.cxx]
License: 3-Clause BSD
For details, see scipy/fft/_pocketfft/LICENSE.md

Name: uarray
Files: scipy/_lib/uarray/*
License: 3-Clause BSD
For details, see scipy/_lib/uarray/LICENSE
82 changes: 82 additions & 0 deletions benchmarks/benchmarks/fft_basic.py
Expand Up @@ -115,3 +115,85 @@ def setup(self, size, cmplx, module):

def time_fftn(self, size, cmplx, module):
self.fftn(self.x)


class FftBackends(Benchmark):
params = [
[100, 256, 313, 512, 1000, 1024, 2048, 2048*2, 2048*4],
['real', 'cmplx'],
['pocketfft', 'pyfftw', 'numpy', 'direct']
]
param_names = ['size', 'type', 'backend']

def setup(self, size, cmplx, backend):
import scipy.fft
if cmplx == 'cmplx':
self.x = random([size]).astype(cdouble)+random([size]).astype(cdouble)*1j
else:
self.x = random([size]).astype(double)

self.fft = scipy.fft.fft
self.ifft = scipy.fft.ifft

if backend == 'pocketfft':
scipy.fft.set_global_backend('scipy')
elif backend == 'pyfftw':
from scipy.fft._debug_backends import PyfftwBackend
import pyfftw
pyfftw.interfaces.cache.enable()
scipy.fft.set_global_backend(PyfftwBackend)
elif backend == 'numpy':
from scipy.fft._debug_backends import NumPyBackend
scipy.fft.set_global_backend(NumPyBackend)
elif backend == 'direct':
import scipy.fft._pocketfft
self.fft = scipy.fft._pocketfft.fft
self.ifft = scipy.fft._pocketfft.ifft

def time_fft(self, size, cmplx, module):
self.fft(self.x)

def time_ifft(self, size, cmplx, module):
self.ifft(self.x)


class FftnBackends(Benchmark):
params = [
["100x100", "313x100", "1000x100", "256x256", "512x512"],
['real', 'cmplx'],
['pocketfft', 'pyfftw', 'numpy', 'direct']
]
param_names = ['size', 'type', 'backend']

def setup(self, size, cmplx, backend):
import scipy.fft
size = list(map(int, size.split("x")))

if cmplx == 'cmplx':
self.x = random(size).astype(double)+random(size).astype(double)*1j
else:
self.x = random(size).astype(double)

self.fftn = scipy.fft.fftn
self.ifftn = scipy.fft.ifftn

if backend == 'pocketfft':
scipy.fft.set_global_backend('scipy')
elif backend == 'pyfftw':
from scipy.fft._debug_backends import PyfftwBackend
import pyfftw
pyfftw.interfaces.cache.enable()
scipy.fft.set_global_backend(PyfftwBackend)
elif backend == 'numpy':
from scipy.fft._debug_backends import NumPyBackend
scipy.fft.set_global_backend(NumPyBackend)
elif backend == 'direct':
import scipy.fft._pocketfft
self.fftn = scipy.fft._pocketfft.fftn
self.ifftn = scipy.fft._pocketfft.ifftn

def time_fft(self, size, cmplx, module):
self.fftn(self.x)

def time_ifft(self, size, cmplx, module):
self.ifftn(self.x)
8 changes: 8 additions & 0 deletions doc/source/conf.py
Expand Up @@ -17,6 +17,14 @@

needs_sphinx = '1.6'

# Workaround for sphinx-doc/sphinx#6573
# ua._Function should not be treated as an attribute
from sphinx.util import inspect
import scipy._lib.uarray as ua
old_isattrdesc = inspect.isattributedescriptor
inspect.isattributedescriptor = (lambda obj: old_isattrdesc(obj)
and not isinstance(obj, ua._Function))
larsoner marked this conversation as resolved.
Show resolved Hide resolved

# -----------------------------------------------------------------------------
# General configuration
# -----------------------------------------------------------------------------
Expand Down
55 changes: 55 additions & 0 deletions scipy/_build_utils/compiler_helper.py
@@ -0,0 +1,55 @@
"""
Helpers for detection of compiler features
"""
import tempfile
import os

def try_compile(compiler, code=None, flags=[], ext=None):
"""Returns True if the compiler is able to compile the given code"""
from distutils.errors import CompileError

code = code or 'int main (int argc, char **argv) { return 0; }'
ext = ext or compiler.src_extensions[0]

with tempfile.TemporaryDirectory() as temp_dir:
fname = os.path.join(temp_dir, 'main'+ext)
with open(fname, 'w') as f:
f.write(code)

try:
compiler.compile([fname], output_dir=temp_dir, extra_postargs=flags)
except CompileError:
return False
return True


def has_flag(compiler, flag, ext=None):
"""Returns True if the compiler supports the given flag"""
return try_compile(compiler, flags=[flag], ext=ext)


def get_cxx_std_flag(compiler):
"""Detects compiler flag for c++14, c++11 or None if not detected"""
gnu_flags = ['--std=c++14', '--std=c++11']
flags_by_cc = {
'msvc': ['/std:c++14', None],
'intelw': ['/Qstd=c++14', '/Qstd=c++11']
}
flags = flags_by_cc.get(compiler.compiler_type, gnu_flags)

for flag in flags:
if flag is None:
return None

if has_flag(compiler, flag):
return flag

from numpy.distutils import log
log.warn('Could not detect c++ standard flag')
return None


def try_add_flag(args, compiler, flag, ext=None):
"""Appends flag to the list of arguments if supported by the compiler"""
if try_compile(compiler, flags=args+[flag], ext=ext):
args.append(flag)
2 changes: 1 addition & 1 deletion scipy/_build_utils/tests/test_circular_imports.py
Expand Up @@ -9,6 +9,7 @@
'cluster.hierarchy',
'cluster.vq',
'constants',
'fft'
'fftpack',
'fftpack.convolve',
'integrate',
Expand Down Expand Up @@ -44,4 +45,3 @@ def test_importing_submodules():
subprocess.check_output(cmd)
except subprocess.CalledProcessError:
raise AssertionError('Importing scipy.{0} failed'.format(name))