提交 129c21c6 authored 作者: slefrancois's avatar slefrancois

revise fft doc

上级 0a889321
.. _libdoc_gpuarray_fft:
===================================================
==============================================
:mod:`gpuarray.fft` -- Fast Fourier Transforms
===================================================
==============================================
Performs Fast Fourier Transforms (FFT) on the GPU.
FFT gradients are implemented as the opposite Fourier transform of the output gradients.
.. warning ::
The real and imaginary parts of the Fourier domain arrays are stored as a pair of float32
array, emulating complex64. Since theano does not support complex
number operations, care must be taken to manually implement operators such as complex
multiplication.
.. automodule:: theano.gpuarray.fft
:members:
:members: curfft, cuirfft
For example, the code below performs the real input FFT of a box function, which is a sinc function.
The absolute value is plotted, since the phase oscillates due to the box function being
shifted to the middle of the array. The Theano flag ``device=cuda{0,1...}`` must be used.
.. testcode::
import numpy as np
import theano
import theano.tensor as T
from theano.gpuarray import fft
x = T.matrix('x', dtype='float32')
rfft = fft.curfft(x, norm='ortho')
f_rfft = theano.function([x], rfft)
N = 1024
box = np.zeros((1,N), dtype='float32')
box[:, N/2-10: N/2+10] = 1
out = f_rfft(box)
c_out = np.asarray(out[0, :, 0] + 1j*out[0, :, 1])
abs_out = abs(c_out)
.. image:: plot_fft.png
\ No newline at end of file
......@@ -281,18 +281,15 @@ cuirfft_op = CuIRFFTOp()
def curfft(inp, norm=None):
"""
Performs the fast Fourier transform of a real-valued output on the GPU
through the gpuarray backend.
Performs the fast Fourier transform of a real-valued input on the GPU.
The input must be a real-valued float32 variable of dimensions (m, ..., n).
It performs FFTs of size (..., n) on m batches.
The output is a GpuArray of dimensions (m, ..., n//2+1, 2). The second to
last dimension of the output contains the n//2+1 non-trivial elements of
the real-valued FFTs. The real and imaginary parts are stored as two
float32 arrays, emulating complex64. Since theano does not support complex
number operations, care must be taken to manually implement operators such
as multiplication.
the real-valued FFTs. The real and imaginary parts are stored as a pair of
float32 arrays.
Parameters
----------
......@@ -318,14 +315,12 @@ def curfft(inp, norm=None):
def cuirfft(inp, norm=None, is_odd=False):
"""
Performs the real-valued output inverse Fourier Transform using the
gpuarray backend.
Performs the inverse fast Fourier Transform with real-valued output on the GPU.
The input is a variable of dimensions (m, ..., n//2+1, 2) with
type float32 representing the non-trivial elements of m
real-valued Fourier transforms of initial size (..., n). The real and
imaginary parts are stored as two float32 arrays, emulating complex64
given that Theano does not support complex numbers.
imaginary parts are stored as a pair of float32 arrays.
The output is a real-valued float32 variable of dimensions (m, ..., n)
giving the m inverse FFTs.
......@@ -344,6 +339,7 @@ def cuirfft(inp, norm=None, is_odd=False):
is_odd : {True, False}
Set to True to get a real inverse transform output with an odd last dimension
of length (N-1)*2 + 1 for an input last dimension of length N.
"""
if is_odd not in (True, False):
......
......@@ -9,12 +9,9 @@ from theano.tests import unittest_tools as utt
import theano.gpuarray.fft
import numpy.fft
from .config import mode_with_gpu
# Skip tests if pygpu is not available.
from nose.plugins.skip import SkipTest
from theano.gpuarray.fft import pygpu_available, scikits_cuda_available
from theano.gpuarray.fft import pycuda_available
from theano.gpuarray.fft import pygpu_available, scikits_cuda_available, pycuda_available
if not pygpu_available: # noqa
raise SkipTest('Optional package pygpu not available')
if not scikits_cuda_available: # noqa
......@@ -22,8 +19,6 @@ if not scikits_cuda_available: # noqa
if not pycuda_available: # noqa
raise SkipTest('Optional package pycuda not available')
import theano.gpuarray.cuda_fft
# Transform sizes
N = 64
......@@ -35,7 +30,7 @@ class TestFFT(unittest.TestCase):
x = T.matrix('x', dtype='float32')
rfft = theano.gpuarray.fft.curfft(x)
f_rfft = theano.function([x], rfft, mode=mode_with_gpu)
f_rfft = theano.function([x], rfft)
res_rfft = f_rfft(inputs_val)
res_rfft_comp = (np.asarray(res_rfft[:, :, 0]) +
1j * np.asarray(res_rfft[:, :, 1]))
......@@ -46,7 +41,7 @@ class TestFFT(unittest.TestCase):
m = rfft.type()
irfft = theano.gpuarray.fft.cuirfft(m)
f_irfft = theano.function([m], irfft, mode=mode_with_gpu)
f_irfft = theano.function([m], irfft)
res_irfft = f_irfft(res_rfft)
utt.assert_allclose(inputs_val, np.asarray(res_irfft))
......@@ -70,7 +65,7 @@ class TestFFT(unittest.TestCase):
inputs = theano.shared(inputs_val)
rfft = theano.gpuarray.fft.curfft(inputs)
f_rfft = theano.function([], rfft, mode=mode_with_gpu)
f_rfft = theano.function([], rfft)
res_rfft = f_rfft()
res_rfft_comp = (np.asarray(res_rfft[:, :, :, 0]) +
1j * np.asarray(res_rfft[:, :, :, 1]))
......@@ -84,12 +79,12 @@ class TestFFT(unittest.TestCase):
inputs = theano.shared(inputs_val)
fft = theano.gpuarray.fft.curfft(inputs)
f_fft = theano.function([], fft, mode=mode_with_gpu)
f_fft = theano.function([], fft)
res_fft = f_fft()
m = fft.type()
ifft = theano.gpuarray.fft.cuirfft(m)
f_ifft = theano.function([m], ifft, mode=mode_with_gpu)
f_ifft = theano.function([m], ifft)
res_ifft = f_ifft(res_fft)
utt.assert_allclose(inputs_val, np.asarray(res_ifft))
......@@ -109,7 +104,7 @@ class TestFFT(unittest.TestCase):
# Unitary normalization
rfft = theano.gpuarray.fft.curfft(inputs, norm='ortho')
f_rfft = theano.function([], rfft, mode=mode_with_gpu)
f_rfft = theano.function([], rfft)
res_rfft = f_rfft()
res_rfft_comp = (np.asarray(res_rfft[:, :, :, 0]) +
1j * np.asarray(res_rfft[:, :, :, 1]))
......@@ -121,7 +116,7 @@ class TestFFT(unittest.TestCase):
# No normalization
rfft = theano.gpuarray.fft.curfft(inputs, norm='no_norm')
f_rfft = theano.function([], rfft, mode=mode_with_gpu)
f_rfft = theano.function([], rfft)
res_rfft = f_rfft()
res_rfft_comp = (np.asarray(res_rfft[:, :, :, 0]) +
1j * np.asarray(res_rfft[:, :, :, 1]))
......@@ -136,7 +131,7 @@ class TestFFT(unittest.TestCase):
# Unitary normalization inverse FFT
irfft = theano.gpuarray.fft.cuirfft(inputs, norm='ortho')
f_irfft = theano.function([], irfft, mode=mode_with_gpu)
f_irfft = theano.function([], irfft)
res_irfft = f_irfft()
irfft_ref_ortho = numpy.fft.irfftn(
......@@ -147,7 +142,7 @@ class TestFFT(unittest.TestCase):
# No normalization inverse FFT
irfft = theano.gpuarray.fft.cuirfft(inputs, norm='no_norm')
f_irfft = theano.function([], irfft, mode=mode_with_gpu)
f_irfft = theano.function([], irfft)
res_irfft = f_irfft()
utt.assert_allclose(irfft_ref_ortho * np.sqrt(N * N),
......@@ -185,7 +180,7 @@ class TestFFT(unittest.TestCase):
inputs = theano.shared(inputs_val)
rfft = theano.gpuarray.fft.curfft(inputs)
f_rfft = theano.function([], rfft, mode=mode_with_gpu)
f_rfft = theano.function([], rfft)
res_rfft = f_rfft()
res_rfft_comp = (np.asarray(res_rfft[:, :, :, 0]) +
......@@ -197,7 +192,7 @@ class TestFFT(unittest.TestCase):
m = rfft.type()
ifft = theano.gpuarray.fft.cuirfft(m, is_odd=True)
f_ifft = theano.function([m], ifft, mode=mode_with_gpu)
f_ifft = theano.function([m], ifft)
res_ifft = f_ifft(res_rfft)
utt.assert_allclose(inputs_val, np.asarray(res_ifft))
......@@ -206,7 +201,7 @@ class TestFFT(unittest.TestCase):
inputs = theano.shared(inputs_val)
irfft = theano.gpuarray.fft.cuirfft(inputs, norm='ortho', is_odd=True)
f_irfft = theano.function([], irfft, mode=mode_with_gpu)
f_irfft = theano.function([], irfft)
res_irfft = f_irfft()
inputs_ref = inputs_val[:, :, :, 0] + 1j * inputs_val[:, :, :, 1]
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论