Speed Up Fast Fourier Transforms in Generated Standalone Code by Using FFTW Library Calls
This example shows how to produce calls to a specific installed FFTW library when you generate standalone code (static library, dynamically linked library, or executable program). For more information about FFTW, see www.fftw.org.
When you generate a MEX function from MATLAB® code that includes fast Fourier transform (FFT) functions, the code generator uses the library that MATLAB uses for FFT algorithms. If you generate standalone C/C++ code, by default, the code generator produces code for the FFT algorithms instead of producing FFT library calls. To increase the speed of fast Fourier transforms in generated standalone code, specify that the code generator produce calls to a specific installed FFTW library.
The code generator produces FFTW library calls when all of these conditions are true:
Your MATLAB code calls one of these functions:
fft
,fft2
,fftn
,ifft
,ifft2
, orifftn
.You generate standalone C/C++ code.
You have access to an FFTW library installation, version 3.2 or later.
You specify the FFTW library installation in an FFT library callback class that derives from
coder.fftw.StandaloneFFTW3Interface
.You set the
CustomFFTCallback
configuration parameter to the name of the callback class. In the MATLAB Coder™ app, use the Custom FFT library callback setting.
FFTW Planning Considerations
The planning method, coder.fftw.StandaloneFFTW3Interface.getPlanMethod
, must be set
according to your workflow to optimize the
performance of the FFTW library. Set the method
to one of the following values as required by your workflow:
FFTW_ESTIMATE
: This is the default setting and allows the FFTW library to deliberate less during the planning phase. This setting is advisable when you have multiple FFTs of varying size and type. This is also advisable when your workflow contains one FFT with multiple inputs of the different type and size. This can reduce the time required for the planning phase.FFTW_MEASURE
: This setting allows the FFTW library to aggressively plan for the use of the FFT algorithms in your workflow. This setting is advisable when your workflow runs one FFT on inputs of the same size and type. This might increase the planning time but can reduce the execution time for the FFT.
For more information about other planning method types, see https://www.fftw.org/fftw3_doc/Planner-Flags.html.
Consider using a previously called FFT for inputs of the same size and type. Reusing the same FFT operation on inputs of identical size and type prompts the planner to use a cached version of the FFT which has previously been called. The execution time of the FFT call also depends on the size of inputs. FFT algorithms whose inputs size is a power of two executes faster than an FFT call whose inputs sizes are non power of two. See https://www.fftw.org/fftw2_doc/fftw_3.html.
Install FFTW Library
If you do not have access to an installed FFTW library, version 3.2 or later,
then you must install one. For a Linux® platform or a Mac platform, consider using a package manager to install the FFTW
library. For a Windows® platform, in addition to .dll
files, you must have
.lib
import libraries, as described in the Windows installation notes on the FFTW website.
See the installation instructions for your platform on the FFTW website.
Write an FFT Callback Class
To specify your installation of the FFTW library, write an FFT callback class. Share the callback class with others who want to use this FFTW library for FFTW calls in standalone code.
The callback class must derive from the abstract class
coder.fftw.StandaloneFFTW3Interface
. Use this example callback
class as a template.
% copyright 2017 The MathWorks, Inc. classdef useMyFFTW < coder.fftw.StandaloneFFTW3Interface methods (Static) function th = getNumThreads coder.inline('always'); th = int32(coder.const(1)); end function updateBuildInfo(buildInfo, ctx) fftwLocation = '/usr/lib/fftw'; includePath = fullfile(fftwLocation, 'include'); buildInfo.addIncludePaths(includePath); libPath = fullfile(fftwLocation, 'lib'); %Double libName1 = 'libfftw3-3'; [~, libExt] = ctx.getStdLibInfo(); libName1 = [libName1 libExt]; addLinkObjects(buildInfo, libName1, libPath, 1000, true, true); %Single libName2 = 'libfftw3f-3'; [~, libExt] = ctx.getStdLibInfo(); libName2 = [libName2 libExt]; addLinkObjects(buildInfo, libName2, libPath, 1000, true, true); end end end
Implement the updateBuildInfo
and
getNumThreads
methods. In the
updateBuildInfo
method, set fftwLocation
to the full path for your installation of the library. Set
includePath
to the full path of the folder that contains
fftw3.h
. Set libPath
to the full path of
the folder that contains the library files. If your FFTW installation uses multiple
threads, modify the getNumThreads
method to return the number
of threads that you want to use.
Optionally, you can implement these methods:
getPlanMethod
to specify the FFTW planning method. Seecoder.fftw.StandaloneFFTW3Interface
.lock
andunlock
to synchronize multithreaded access to the FFTW planning process. See Synchronize Multithreaded Access to FFTW Planning in Generated Standalone Code.
Generate FFTW Library Calls by Specifying an FFT Library Callback Class
To generate FFTW library calls in standalone C code:
Write a MATLAB function that calls a MATLAB fast Fourier transform function. For example, write a function
myfft
that calls the MATLAB functionfft
.function y = myfft() %#codegen t = 0:1/50:10-1/50; x = sin(2*pi*15*t) + sin(2*pi*20*t); y = fft(x); end
Define a code generation configuration object for a static library, dynamically linked library, or executable program. For example, define a configuration object for a dynamically linked library.
cfg = coder.config('dll');
Specify the FFTW callback class
useMyFFTW
.cfg.CustomFFTCallback = 'useMyFFTW';
The callback class must be on the MATLAB path.
Generate code.
codegen myfft -config cfg -report
Locate FFTW Library in Execution Environment
The FFTW library must be available in your execution environment. If the FFTW library is shared, use environment variables or linker options to specify the location of the library.
On a Windows platform, modify the PATH environment variable.
On a Linux platform, modify the LD_LIBRARY_PATH environment variable or use the
rpath
linker option.On a macOS platform, modify the DYLD_LIBRARY_PATH environment variable or use the
rpath
linker option.
To specify the rpath
linker option, you can
use the build information addLinkFlags
method in the
updateBuildInfo
method of your
coder.fftw.StandaloneFFTW3Interface
class. For example, for a
GCC
compiler:
buildInfo.addLinkFlags(sprintf('-Wl,-rpath,"%s"',libPath));
Clean Up Memory Used By FFTW Library Functions
To clean up memory that the FFTW library functions use while the calling process is still running, you must incorporate the generated code into your own project and manually call the cleanup function after executing the generated code. By contrast, when the calling process terminates, FFTW library functions automatically free the memory and you do not need to call these cleanup functions.
The available cleanup functions are:
fftw_cleanup
fftwf_cleanup
fftw_cleanup_threads
fftwf_cleanup_threads
Follow these rules to decide which cleanup function to use:
If you use single-precision floating point numbers in calls to FFT functions, use the
fftwf
prefixed cleanup functions.If you use double-precision floating point numbers in calls to FFT functions, use the
fftw
prefixed cleanup functions.If your implementation of the
coder.fftw.StandaloneFFTW3Interface.getNumThreads
method returns a value that is greater than1
, use the cleanup functions that have thethreads
suffix.
See Also
coder.fftw.StandaloneFFTW3Interface