JayBeams  0.1
Another project to have fun coding.
clfft_plan_ut.cpp
Go to the documentation of this file.
1 #include <jb/clfft/init.hpp>
2 #include <jb/clfft/plan.hpp>
6 
7 #include <boost/test/unit_test.hpp>
8 #include <complex>
9 #include <vector>
10 
11 /**
12  * @test Verify that we can create and destroy default initialized plans.
13  */
14 BOOST_AUTO_TEST_CASE(clfft_plan_default) {
16  {
17  using invector = boost::compute::vector<std::complex<float>>;
18  using outvector = boost::compute::vector<std::complex<float>>;
19  using tested_type = jb::clfft::plan<invector, outvector>;
20  tested_type x;
21  tested_type y;
22  }
23 }
24 
25 /**
26  * @test Verify that we use move copy constructor and assignment on plans.
27  */
28 BOOST_AUTO_TEST_CASE(clfft_plan_move) {
29  boost::compute::device device = jb::opencl::device_selector();
30  boost::compute::context context(device);
31  boost::compute::command_queue queue(context, device);
33 
34  std::size_t size = 128;
35  using invector = boost::compute::vector<std::complex<float>>;
36  using outvector = boost::compute::vector<std::complex<float>>;
37 
38  std::vector<std::complex<float>> src(size);
40 
41  invector in(size, context);
42  outvector out(size, context);
43 
44  boost::compute::copy(src.begin(), src.end(), in.begin(), queue);
45 
46  {
47  auto fft = jb::clfft::create_forward_plan_1d(out, in, context, queue);
48 
49  auto p(std::move(fft));
50 
51  BOOST_CHECK_NO_THROW(p.enqueue(out, in, queue).wait());
52  BOOST_CHECK_THROW(fft.enqueue(out, in, queue), std::exception);
53  }
54  {
55  auto fft = jb::clfft::create_forward_plan_1d(out, in, context, queue);
56 
58  p = std::move(fft);
59  BOOST_CHECK_NO_THROW(p.enqueue(out, in, queue).wait());
60  BOOST_CHECK_THROW(fft.enqueue(out, in, queue), std::exception);
61  }
62  {
64 
65  p = jb::clfft::create_forward_plan_1d(out, in, context, queue);
66  BOOST_CHECK_NO_THROW(p.enqueue(out, in, queue).wait());
67  }
68 }
69 
70 /**
71  * @test Verify that we can create clfft_plan objects and they work as expected.
72  */
73 BOOST_AUTO_TEST_CASE(clfft_plan_basic) {
74  std::size_t const size = 1 << 8;
75  // The max precision loss for an FFT is O(sqrt(N)). With N == 1<<8
76  // the sqrt is 1<<4, but we have 2 FFT operations and the error
77  // factors compound (we need to multiply them), so 1<<8 epsilons is
78  // a good guess to the maximum error:
79  int const tol = 1 << 8;
80 
81  boost::compute::device device = jb::opencl::device_selector();
82  boost::compute::context context(device);
83  boost::compute::command_queue queue(context, device);
85 
86  using invector = boost::compute::vector<std::complex<float>>;
87  using outvector = boost::compute::vector<std::complex<float>>;
88 
89  std::vector<std::complex<float>> src(size);
91 
92  invector in(size, context);
93  outvector tmp(size, context);
94  invector out(size, context);
95 
96  auto fft = jb::clfft::create_forward_plan_1d(tmp, in, context, queue);
97  auto ifft = jb::clfft::create_inverse_plan_1d(out, tmp, context, queue);
98 
99  boost::compute::copy(src.begin(), src.end(), in.begin(), queue);
100 
101  fft.enqueue(tmp, in, queue).wait();
102  ifft.enqueue(out, tmp, queue).wait();
103 
104  std::vector<std::complex<float>> dst(size);
105  boost::compute::copy(out.begin(), out.end(), dst.begin(), queue);
106 
107  bool res = jb::testing::check_collection_close_enough(dst, src, tol);
108  BOOST_CHECK_MESSAGE(res, "collections are not within tolerance=" << tol);
109 }
110 
111 /**
112  * @test Verify that the plan detects errors and reports them.
113  */
114 BOOST_AUTO_TEST_CASE(clfft_plan_error) {
115  using invector = boost::compute::vector<std::complex<float>>;
116  using outvector = boost::compute::vector<std::complex<float>>;
117 
118  std::size_t const size = 1 << 8;
119  boost::compute::device device = jb::opencl::device_selector();
120  boost::compute::context context(device);
121  boost::compute::command_queue queue(context, device);
123 
124  invector in(size, context);
125  outvector tmp(size - 1, context);
126 
127  BOOST_CHECK_THROW(
128  jb::clfft::create_forward_plan_1d(tmp, in, context, queue),
129  std::invalid_argument);
130 
131  outvector out(size, context);
132  BOOST_CHECK_THROW(
133  jb::clfft::create_forward_plan_1d(out, in, context, queue, 0),
134  std::invalid_argument);
135  BOOST_CHECK_THROW(
136  jb::clfft::create_forward_plan_1d(out, in, context, queue, 3),
137  std::invalid_argument);
138 }
plan< invector, outvector > create_forward_plan_1d(outvector const &out, invector const &in, boost::compute::context &ct, boost::compute::command_queue &q, int batch_size=1)
Create a forward DFT plan.
Definition: plan.hpp:255
plan< invector, outvector > create_inverse_plan_1d(outvector const &out, invector const &in, boost::compute::context &ct, boost::compute::command_queue &q, int batch_size=1)
Create an inverse DFT plan.
Definition: plan.hpp:284
Wrap clfftPlanHandle objects in a class that can automatically destroy them.
Definition: init.hpp:13
boost::compute::event enqueue(out_timeseries_type &out, in_timeseries_type const &in, boost::compute::command_queue &queue, boost::compute::wait_list const &wait=boost::compute::wait_list())
Enqueue the transform to be executed.
Definition: plan.hpp:107
boost::compute::device device_selector(config const &cfg)
Select an OpenCL device matching the current configuration.
Wrap clfftPlanHandle objects.
Definition: plan.hpp:35
void create_square_timeseries(int nsamples, timeseries &ts)
Create a simple timeseries where the values look like a square.
void init(config const &cfg)
Initialize the logging functions using the configuration provided.
Definition: log.cpp:190
bool check_collection_close_enough(collection_t const &a, collection_t const &b, int tol=1, int max_differences_printed=JB_TESTING_MAX_DIFFERENCES_PRINTED)
Given two collections of numbers of the same value type, find the differences that are out of a given...
BOOST_AUTO_TEST_CASE(clfft_plan_default)