ViennaCL - The Vienna Computing Library: viennacl/linalg/opencl/fft_operations.hpp Source File

ViennaCL - The Vienna Computing Library 1.7.1 Free open-source GPU-accelerated linear algebra and solver library. |

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
fft_operations.hpp
Go to the documentation of this file.
1 #ifndef VIENNACL_LINALG_OPENCL_FFT_OPERATIONS_HPP_
2 #define VIENNACL_LINALG_OPENCL_FFT_OPERATIONS_HPP_
3
4 /* =========================================================================
5 Copyright (c) 2010-2016, Institute for Microelectronics,
6 Institute for Analysis and Scientific Computing,
7 TU Wien.
8 Portions of this software are copyright by UChicago Argonne, LLC.
9
10 -----------------
11 ViennaCL - The Vienna Computing Library
12 -----------------
13
14 Project Head: Karl Rupp rupp@iue.tuwien.ac.at
15
16 (A list of authors and contributors can be found in the manual)
17
18 License: MIT (X11), see file LICENSE in the base directory
19 ============================================================================= */
20
25 #include "viennacl/forwards.h"
26 #include "viennacl/ocl/device.hpp"
27 #include "viennacl/ocl/kernel.hpp"
28 #include "viennacl/traits/handle.hpp"
29 #include "viennacl/traits/stride.hpp"
30 #include "viennacl/linalg/host_based/fft_operations.hpp"
31 #include "viennacl/linalg/opencl/kernels/fft.hpp"
32 #include "viennacl/linalg/opencl/kernels/matrix.hpp"
33
34 #include <viennacl/vector.hpp>
35 #include <viennacl/matrix.hpp>
36
37 #include <cmath>
38 #include <stdexcept>
39
40 namespace viennacl
41 {
42 namespace linalg
43 {
44 namespace detail
45 {
46 namespace fft
47 {
48
49 const vcl_size_t MAX_LOCAL_POINTS_NUM = 512;
50
54 inline vcl_size_t num_bits(vcl_size_t size)
55 {
56 vcl_size_t bits_datasize = 0;
57 vcl_size_t ds = 1;
58
59 while (ds < size)
60 {
61 ds = ds << 1;
62 bits_datasize++;
63 }
64
65 return bits_datasize;
66 }
67
71 inline vcl_size_t next_power_2(vcl_size_t n)
72 {
73 n = n - 1;
74
75 vcl_size_t power = 1;
76
77 while (power < sizeof(vcl_size_t) * 8)
78 {
79 n = n | (n >> power);
80 power *= 2;
81 }
82
83 return n + 1;
84 }
85
86 } //namespce fft
87 } //namespace detail
88
89 namespace opencl
90 {
91
98 template<typename NumericT>
99 void direct(viennacl::ocl::handle<cl_mem> const & in,
100 viennacl::ocl::handle<cl_mem> const & out,
101 vcl_size_t size, vcl_size_t stride, vcl_size_t batch_num, NumericT sign = NumericT(-1),
102 viennacl::linalg::host_based::detail::fft::FFT_DATA_ORDER::DATA_ORDER data_order = viennacl::linalg::host_based::detail::fft::FFT_DATA_ORDER::ROW_MAJOR)
103 {
104 viennacl::ocl::context & ctx = const_cast<viennacl::ocl::context &>(in.context());
105 viennacl::linalg::opencl::kernels::fft<NumericT>::init(ctx);
106
107 std::string program_string = viennacl::linalg::opencl::kernels::matrix_legacy<NumericT, row_major>::program_name();
108 if (data_order == viennacl::linalg::host_based::detail::fft::FFT_DATA_ORDER::COL_MAJOR)
109 {
110 viennacl::linalg::opencl::kernels::matrix_legacy<NumericT, column_major>::init(ctx);
111 program_string =
112 viennacl::linalg::opencl::kernels::matrix_legacy<NumericT, column_major>::program_name();
113 } else
114 viennacl::linalg::opencl::kernels::matrix_legacy<NumericT, row_major>::init(ctx);
115
116 viennacl::ocl::kernel & k = ctx.get_kernel(program_string, "fft_direct");
117 viennacl::ocl::enqueue(k(in, out,
118 static_cast<cl_uint>(size),
119 static_cast<cl_uint>(stride),
120 static_cast<cl_uint>(batch_num),
121 sign)
122 );
123 }
124
125 /*
126 * This function performs reorder of input data. Indexes are sorted in bit-reversal order.
127 * Such reordering should be done before in-place FFT.
128 */
129 template<typename NumericT>
130 void reorder(viennacl::ocl::handle<cl_mem> const & in,
131 vcl_size_t size, vcl_size_t stride,
132 vcl_size_t bits_datasize, vcl_size_t batch_num,
133 viennacl::linalg::host_based::detail::fft::FFT_DATA_ORDER::DATA_ORDER data_order = viennacl::linalg::host_based::detail::fft::FFT_DATA_ORDER::ROW_MAJOR)
134 {
135 viennacl::ocl::context & ctx = const_cast<viennacl::ocl::context &>(in.context());
136 viennacl::linalg::opencl::kernels::fft<NumericT>::init(ctx);
137
138 std::string program_string = viennacl::linalg::opencl::kernels::matrix_legacy<NumericT, row_major>::program_name();
139 if (data_order == viennacl::linalg::host_based::detail::fft::FFT_DATA_ORDER::COL_MAJOR)
140 {
141 viennacl::linalg::opencl::kernels::matrix_legacy<NumericT, column_major>::init(ctx);
142 program_string = viennacl::linalg::opencl::kernels::matrix_legacy<NumericT, column_major>::program_name();
143 } else
144 viennacl::linalg::opencl::kernels::matrix_legacy<NumericT, row_major>::init(ctx);
145
146 viennacl::ocl::kernel& k = ctx.get_kernel(program_string, "fft_reorder");
147 viennacl::ocl::enqueue(k(in,
148 static_cast<cl_uint>(bits_datasize), static_cast<cl_uint>(size),
149 static_cast<cl_uint>(stride), static_cast<cl_uint>(batch_num))
150 );
151 }
152
160 template<typename NumericT>
161 void radix2(viennacl::ocl::handle<cl_mem> const & in,
162 vcl_size_t size, vcl_size_t stride,
163 vcl_size_t batch_num, NumericT sign = NumericT(-1),
164 viennacl::linalg::host_based::detail::fft::FFT_DATA_ORDER::DATA_ORDER data_order = viennacl::linalg::host_based::detail::fft::FFT_DATA_ORDER::ROW_MAJOR)
165 {
166 viennacl::ocl::context & ctx = const_cast<viennacl::ocl::context &>(in.context());
167 viennacl::linalg::opencl::kernels::fft<NumericT>::init(ctx);
168
169 assert(batch_num != 0 && bool("batch_num must be larger than 0"));
170
171 std::string program_string = viennacl::linalg::opencl::kernels::matrix_legacy<NumericT, row_major>::program_name();
172 if (data_order == viennacl::linalg::host_based::detail::fft::FFT_DATA_ORDER::COL_MAJOR)
173 {
174 viennacl::linalg::opencl::kernels::matrix_legacy<NumericT, column_major>::init(ctx);
175 program_string = viennacl::linalg::opencl::kernels::matrix_legacy<NumericT, column_major>::program_name();
176 } else
177 viennacl::linalg::opencl::kernels::matrix_legacy<NumericT, row_major>::init(ctx);
178
179 vcl_size_t bits_datasize = viennacl::linalg::detail::fft::num_bits(size);
180 if (size <= viennacl::linalg::detail::fft::MAX_LOCAL_POINTS_NUM)
181 {
182 viennacl::ocl::kernel & k = ctx.get_kernel(program_string, "fft_radix2_local");
183 viennacl::ocl::enqueue(k(in,
184 viennacl::ocl::local_mem((size * 4) * sizeof(NumericT)),
185 static_cast<cl_uint>(bits_datasize), static_cast<cl_uint>(size),
186 static_cast<cl_uint>(stride), static_cast<cl_uint>(batch_num), sign));
187
188 }
189 else
190 {
191 viennacl::linalg::opencl::reorder<NumericT>(in, size, stride, bits_datasize, batch_num);
192
193 for (vcl_size_t step = 0; step < bits_datasize; step++)
194 {
195 viennacl::ocl::kernel & k = ctx.get_kernel(program_string, "fft_radix2");
196 viennacl::ocl::enqueue(k(in,
197 static_cast<cl_uint>(step), static_cast<cl_uint>(bits_datasize),
198 static_cast<cl_uint>(size), static_cast<cl_uint>(stride),
199 static_cast<cl_uint>(batch_num), sign));
200 }
201 }
202 }
203
211 template<typename NumericT, unsigned int AlignmentV>
212 void bluestein(viennacl::vector<NumericT, AlignmentV>& in,
213 viennacl::vector<NumericT, AlignmentV>& out, vcl_size_t /*batch_num*/)
214 {
215 viennacl::ocl::context & ctx = const_cast<viennacl::ocl::context &>(viennacl::traits::opencl_handle(in).context());
216 viennacl::linalg::opencl::kernels::fft<NumericT>::init(ctx);
217
218 vcl_size_t size = in.size() >> 1;
219 vcl_size_t ext_size = viennacl::linalg::detail::fft::next_power_2(2 * size - 1);
220
221 viennacl::vector<NumericT, AlignmentV> A(ext_size << 1);
222 viennacl::vector<NumericT, AlignmentV> B(ext_size << 1);
223 viennacl::vector<NumericT, AlignmentV> Z(ext_size << 1);
224
225 {
226 viennacl::ocl::kernel & k = ctx.get_kernel(viennacl::linalg::opencl::kernels::fft<NumericT>::program_name(), "zero2");
227 viennacl::ocl::enqueue(k(A, B, static_cast<cl_uint>(ext_size)));
228 }
229 {
230 viennacl::ocl::kernel & k = ctx.get_kernel(viennacl::linalg::opencl::kernels::fft<NumericT>::program_name(), "bluestein_pre");
231 viennacl::ocl::enqueue(k(in, A, B, static_cast<cl_uint>(size), static_cast<cl_uint>(ext_size)));
232 }
233
234 viennacl::linalg::convolve_i(A, B, Z);
235
236 {
237 viennacl::ocl::kernel& k = ctx.get_kernel(viennacl::linalg::opencl::kernels::fft<NumericT>::program_name(), "bluestein_post");
238 viennacl::ocl::enqueue(k(Z, out, static_cast<cl_uint>(size)));
239 }
240 }
241
245 template<typename NumericT, unsigned int AlignmentV>
246 void multiply_complex(viennacl::vector<NumericT, AlignmentV> const & input1,
247 viennacl::vector<NumericT, AlignmentV> const & input2,
248 viennacl::vector<NumericT, AlignmentV> & output)
249 {
250 viennacl::ocl::context & ctx = const_cast<viennacl::ocl::context &>(viennacl::traits::opencl_handle(input1).context());
251 viennacl::linalg::opencl::kernels::fft<NumericT>::init(ctx);
252 vcl_size_t size = input1.size() >> 1;
253 viennacl::ocl::kernel & k = ctx.get_kernel(viennacl::linalg::opencl::kernels::fft<NumericT>::program_name(), "fft_mult_vec");
254 viennacl::ocl::enqueue(k(input1, input2, output, static_cast<cl_uint>(size)));
255 }
256
260 template<typename NumericT, unsigned int AlignmentV>
261 void normalize(viennacl::vector<NumericT, AlignmentV> & input)
262 {
263 viennacl::ocl::context & ctx = const_cast<viennacl::ocl::context &>(viennacl::traits::opencl_handle(input).context());
264 viennacl::linalg::opencl::kernels::fft<NumericT>::init(ctx);
265
266 viennacl::ocl::kernel & k = ctx.get_kernel(viennacl::linalg::opencl::kernels::fft<NumericT>::program_name(), "fft_div_vec_scalar");
267
268 vcl_size_t size = input.size() >> 1;
269 NumericT norm_factor = static_cast<NumericT>(size);
270 viennacl::ocl::enqueue(k(input, static_cast<cl_uint>(size), norm_factor));
271 }
272
276 template<typename NumericT, unsigned int AlignmentV>
277 void transpose(viennacl::matrix<NumericT, viennacl::row_major, AlignmentV> & input)
278 {
279 viennacl::ocl::context & ctx = const_cast<viennacl::ocl::context &>(viennacl::traits::opencl_handle(input).context());
280 viennacl::linalg::opencl::kernels::fft<NumericT>::init(ctx);
281
282 viennacl::ocl::kernel& k = ctx.get_kernel(viennacl::linalg::opencl::kernels::fft<NumericT>::program_name(), "transpose_inplace");
283 viennacl::ocl::enqueue(k(input, static_cast<cl_uint>(input.internal_size1() >> 1),
284 static_cast<cl_uint>(input.internal_size2()) >> 1));
285 }
286
290 template<typename NumericT, unsigned int AlignmentV>
291 void transpose(viennacl::matrix<NumericT, viennacl::row_major, AlignmentV> const & input,
292 viennacl::matrix<NumericT, viennacl::row_major, AlignmentV> & output)
293 {
294 viennacl::ocl::context & ctx = const_cast<viennacl::ocl::context &>(viennacl::traits::opencl_handle(input).context());
295 viennacl::linalg::opencl::kernels::fft<NumericT>::init(ctx);
296
297 viennacl::ocl::kernel& k = ctx.get_kernel(viennacl::linalg::opencl::kernels::fft<NumericT>::program_name(), "transpose");
298 viennacl::ocl::enqueue(k(input, output, static_cast<cl_uint>(input.internal_size1() >> 1),
299 static_cast<cl_uint>(input.internal_size2() >> 1)));
300 }
301
305 template<typename NumericT>
306 void real_to_complex(viennacl::vector_base<NumericT> const & in,
307 viennacl::vector_base<NumericT> & out, vcl_size_t size)
308 {
309 viennacl::ocl::context & ctx = const_cast<viennacl::ocl::context &>(viennacl::traits::opencl_handle(in).context());
310 viennacl::linalg::opencl::kernels::fft<NumericT>::init(ctx);
311
312 viennacl::ocl::kernel & k = ctx.get_kernel(viennacl::linalg::opencl::kernels::fft<NumericT>::program_name(), "real_to_complex");
313 viennacl::ocl::enqueue(k(in, out, static_cast<cl_uint>(size)));
314 }
315
319 template<typename NumericT>
320 void complex_to_real(viennacl::vector_base<NumericT> const & in,
321 viennacl::vector_base<NumericT> & out, vcl_size_t size)
322 {
323 viennacl::ocl::context & ctx = const_cast<viennacl::ocl::context &>(viennacl::traits::opencl_handle(in).context());
324 viennacl::linalg::opencl::kernels::fft<NumericT>::init(ctx);
325
326 viennacl::ocl::kernel& k = ctx.get_kernel(viennacl::linalg::opencl::kernels::fft<NumericT>::program_name(), "complex_to_real");
327 viennacl::ocl::enqueue(k(in, out, static_cast<cl_uint>(size)));
328 }
329
333 template<typename NumericT>
334 void reverse(viennacl::vector_base<NumericT>& in)
335 {
336 viennacl::ocl::context & ctx = const_cast<viennacl::ocl::context &>(viennacl::traits::opencl_handle(in).context());
337 viennacl::linalg::opencl::kernels::fft<NumericT>::init(ctx);
338
339 vcl_size_t size = in.size();
340
341 viennacl::ocl::kernel& k = ctx.get_kernel(viennacl::linalg::opencl::kernels::fft<NumericT>::program_name(), "reverse_inplace");
342 viennacl::ocl::enqueue(k(in, static_cast<cl_uint>(size)));
343 }
344
345 } //namespace opencl
346 } //namespace linalg
347 } //namespace viennacl
348
349 #endif /* FFT_OPERATIONS_HPP_ */
350
viennacl::linalg::opencl::reorder
void reorder(viennacl::ocl::handle< cl_mem > const &in, vcl_size_t size, vcl_size_t stride, vcl_size_t bits_datasize, vcl_size_t batch_num, viennacl::linalg::host_based::detail::fft::FFT_DATA_ORDER::DATA_ORDER data_order=viennacl::linalg::host_based::detail::fft::FFT_DATA_ORDER::ROW_MAJOR)
Definition: fft_operations.hpp:130
fft.hpp
OpenCL kernel file for FFT operations.
viennacl::linalg::detail::fft::next_power_2
vcl_size_t next_power_2(vcl_size_t n)
Find next power of two.
Definition: fft_operations.hpp:71
device.hpp
Represents an OpenCL device within ViennaCL.
viennacl::linalg::host_based::detail::fft::FFT_DATA_ORDER::DATA_ORDER
DATA_ORDER
Definition: fft_operations.hpp:49
viennacl::linalg::opencl::complex_to_real
void complex_to_real(viennacl::vector_base< NumericT > const &in, viennacl::vector_base< NumericT > &out, vcl_size_t size)
Create real vector from complex vector (even elements(2*k) = real part, odd elements(2*k+1) = imagina...
Definition: fft_operations.hpp:320
viennacl::ocl::kernel
Represents an OpenCL kernel within ViennaCL.
Definition: kernel.hpp:58
matrix.hpp
Implementation of the dense matrix class.
viennacl::linalg::opencl::kernels::fft
Main kernel class for generating OpenCL kernels for the fast Fourier transform.
Definition: fft.hpp:260
viennacl::ocl::context
Manages an OpenCL context and provides the respective convenience functions for creating buffers...
Definition: context.hpp:55
viennacl::traits::stride
result_of::size_type< viennacl::vector_base< T > >::type stride(viennacl::vector_base< T > const &s)
Definition: stride.hpp:45
forwards.h
This file provides the forward declarations for the main types used within ViennaCL.
step
endcode *Final step
Definition: least-squares.cpp:145
viennacl::matrix
A dense matrix class.
Definition: forwards.h:375
stride.hpp
Determines row and column increments for matrices and matrix proxies.
viennacl::linalg::opencl::transpose
void transpose(viennacl::matrix< NumericT, viennacl::row_major, AlignmentV > &input)
Inplace_transpose matrix.
Definition: fft_operations.hpp:277
viennacl::ocl::handle::context
viennacl::ocl::context const & context() const
Definition: handle.hpp:193
NumericT
float NumericT
Definition: bisect.cpp:40
viennacl::linalg::host_based::detail::fft::FFT_DATA_ORDER::ROW_MAJOR
Definition: fft_operations.hpp:51
viennacl::traits::size
vcl_size_t size(VectorType const &vec)
Generic routine for obtaining the size of a vector (ViennaCL, uBLAS, etc.)
Definition: size.hpp:239
viennacl::ocl::local_mem
A class representing local (shared) OpenCL memory. Typically used as kernel argument.
Definition: local_mem.hpp:33
viennacl::ocl::context::get_kernel
viennacl::ocl::kernel & get_kernel(std::string const &program_name, std::string const &kernel_name)
Convenience function for retrieving the kernel of a program directly from the context.
Definition: context.hpp:605
viennacl::linalg::opencl::kernels::matrix_legacy::init
static void init(viennacl::ocl::context &ctx)
Definition: matrix.hpp:1025
viennacl::vector_base< NumericT >
viennacl::linalg::opencl::radix2
void radix2(viennacl::ocl::handle< cl_mem > const &in, vcl_size_t size, vcl_size_t stride, vcl_size_t batch_num, NumericT sign=NumericT(-1), viennacl::linalg::host_based::detail::fft::FFT_DATA_ORDER::DATA_ORDER data_order=viennacl::linalg::host_based::detail::fft::FFT_DATA_ORDER::ROW_MAJOR)
Radix-2 algorithm for computing Fourier transformation.
Definition: fft_operations.hpp:161
viennacl::linalg::opencl::reverse
void reverse(viennacl::vector_base< NumericT > &in)
Reverse vector to oposite order and save it in input vector.
Definition: fft_operations.hpp:334
viennacl::linalg::opencl::real_to_complex
void real_to_complex(viennacl::vector_base< NumericT > const &in, viennacl::vector_base< NumericT > &out, vcl_size_t size)
Create complex vector from real vector (even elements(2*k) = real part, odd elements(2*k+1) = imagina...
Definition: fft_operations.hpp:306
viennacl::vcl_size_t
std::size_t vcl_size_t
Definition: forwards.h:75
viennacl::linalg::opencl::kernels::matrix_legacy::program_name
static std::string program_name()
Definition: matrix.hpp:1020
viennacl::vector< NumericT, AlignmentV >
viennacl::linalg::convolve_i
void convolve_i(viennacl::vector< SCALARTYPE, ALIGNMENT > &input1, viennacl::vector< SCALARTYPE, ALIGNMENT > &input2, viennacl::vector< SCALARTYPE, ALIGNMENT > &output)
viennacl::linalg::host_based::detail::fft::FFT_DATA_ORDER::COL_MAJOR
Definition: fft_operations.hpp:51
viennacl::linalg::detail::fft::MAX_LOCAL_POINTS_NUM
const vcl_size_t MAX_LOCAL_POINTS_NUM
Definition: fft_operations.hpp:49
viennacl::ocl::enqueue
void enqueue(KernelType &k, viennacl::ocl::command_queue const &queue)
Enqueues a kernel in the provided queue.
Definition: enqueue.hpp:50
kernel.hpp
Representation of an OpenCL kernel in ViennaCL.
vector.hpp
The vector type with operator-overloads and proxy classes is defined here. Linear algebra operations ...
viennacl::linalg::opencl::multiply_complex
void multiply_complex(viennacl::vector< NumericT, AlignmentV > const &input1, viennacl::vector< NumericT, AlignmentV > const &input2, viennacl::vector< NumericT, AlignmentV > &output)
Mutiply two complex vectors and store result in output.
Definition: fft_operations.hpp:246
viennacl::vector_base::size
size_type size() const
Returns the length of the vector (cf. std::vector)
Definition: vector_def.hpp:118
viennacl::linalg::opencl::direct
void direct(viennacl::ocl::handle< cl_mem > const &in, viennacl::ocl::handle< cl_mem > const &out, vcl_size_t size, vcl_size_t stride, vcl_size_t batch_num, NumericT sign=NumericT(-1), viennacl::linalg::host_based::detail::fft::FFT_DATA_ORDER::DATA_ORDER data_order=viennacl::linalg::host_based::detail::fft::FFT_DATA_ORDER::ROW_MAJOR)
Direct algorithm for computing Fourier transformation.
Definition: fft_operations.hpp:99
fft_operations.hpp
Implementations of Fast Furier Transformation using a plain single-threaded or OpenMP-enabled executi...
viennacl::linalg::detail::fft::num_bits
vcl_size_t num_bits(vcl_size_t size)
Get number of bits.
Definition: fft_operations.hpp:54
viennacl::matrix_base< NumericT >::internal_size2
size_type internal_size2() const
Returns the internal number of columns. Usually required for launching OpenCL kernels only...
Definition: matrix_def.hpp:240
viennacl::matrix_base< NumericT >::internal_size1
size_type internal_size1() const
Returns the internal number of rows. Usually required for launching OpenCL kernels only...
Definition: matrix_def.hpp:238
handle.hpp
Extracts the underlying OpenCL handle from a vector, a matrix, an expression etc. ...
viennacl::linalg::opencl::kernels::fft::init
static void init(viennacl::ocl::context &ctx)
Definition: fft.hpp:267
viennacl::ocl::handle< cl_mem >
viennacl::linalg::opencl::normalize
void normalize(viennacl::vector< NumericT, AlignmentV > &input)
Normalize vector on with his own size.
Definition: fft_operations.hpp:261
viennacl::linalg::opencl::bluestein
void bluestein(viennacl::vector< NumericT, AlignmentV > &in, viennacl::vector< NumericT, AlignmentV > &out, vcl_size_t)
Bluestein's algorithm for computing Fourier transformation.
Definition: fft_operations.hpp:212
matrix.hpp
Runtime generation of OpenCL kernels for matrix operations.
fft
ScalarType fft(std::vector< ScalarType > &in, std::vector< ScalarType > &out, unsigned int, unsigned int, unsigned int batch_size)
Definition: fft_1d.cpp:719
viennacl::linalg::detail::sign
SCALARTYPE sign(SCALARTYPE val)
Definition: qr-method-common.hpp:71