1 //---------------------------------------------------------------------------//
2 // Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@gmail.com>
4 // Distributed under the Boost Software License, Version 1.0
5 // See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt
8 // See http://boostorg.github.com/compute for more information.
9 //---------------------------------------------------------------------------//
11 // Undefining BOOST_COMPUTE_USE_OFFLINE_CACHE macro as we want to modify cached
12 // parameters for copy algorithm without any undesirable consequences (like
13 // saving modified values of those parameters).
14 #ifdef BOOST_COMPUTE_USE_OFFLINE_CACHE
15 #undef BOOST_COMPUTE_USE_OFFLINE_CACHE
18 #define BOOST_TEST_MODULE TestExtrema
19 #include <boost/test/unit_test.hpp>
21 #include <boost/compute/system.hpp>
22 #include <boost/compute/command_queue.hpp>
23 #include <boost/compute/algorithm/copy.hpp>
24 #include <boost/compute/algorithm/iota.hpp>
25 #include <boost/compute/algorithm/fill.hpp>
26 #include <boost/compute/algorithm/max_element.hpp>
27 #include <boost/compute/algorithm/min_element.hpp>
28 #include <boost/compute/algorithm/minmax_element.hpp>
29 #include <boost/compute/container/vector.hpp>
30 #include <boost/compute/iterator/transform_iterator.hpp>
31 #include <boost/compute/detail/parameter_cache.hpp>
34 #include "context_setup.hpp"
36 namespace bc
= boost::compute
;
37 namespace compute
= boost::compute
;
39 BOOST_AUTO_TEST_CASE(empyt_min
)
41 using boost::compute::int_
;
43 boost::compute::vector
<int_
> vector(size_t(16), int_(0), queue
);
44 boost::compute::vector
<int_
>::iterator min_iter
=
45 boost::compute::min_element(vector
.begin(), vector
.begin(), queue
);
46 BOOST_CHECK(min_iter
== vector
.begin());
49 boost::compute::min_element(vector
.begin(), vector
.begin() + 1, queue
);
50 BOOST_CHECK(min_iter
== vector
.begin());
53 BOOST_AUTO_TEST_CASE(int_min_max
)
55 using boost::compute::int_
;
56 using boost::compute::uint_
;
58 boost::compute::vector
<int_
> vector(size_t(4096), int_(0), queue
);
59 boost::compute::iota(vector
.begin(), (vector
.begin() + 512), 1, queue
);
60 boost::compute::fill((vector
.end() - 512), vector
.end(), 513, queue
);
62 boost::compute::vector
<int_
>::iterator min_iter
=
63 boost::compute::min_element(vector
.begin(), vector
.end(), queue
);
64 BOOST_CHECK(min_iter
== vector
.begin() + 512);
65 BOOST_CHECK_EQUAL((vector
.begin() + 512).read(queue
), 0);
66 BOOST_CHECK_EQUAL(min_iter
.read(queue
), 0);
68 boost::compute::vector
<int_
>::iterator max_iter
=
69 boost::compute::max_element(vector
.begin(), vector
.end(), queue
);
70 BOOST_CHECK(max_iter
== vector
.end() - 512);
71 BOOST_CHECK_EQUAL((vector
.end() - 512).read(queue
), 513);
72 BOOST_CHECK_EQUAL(max_iter
.read(queue
), 513);
75 boost::compute::less
<int_
> lessint
;
77 // test minmax_element
79 boost::compute::vector
<int_
>::iterator
,
80 boost::compute::vector
<int_
>::iterator
82 boost::compute::minmax_element(vector
.begin(), vector
.end(), queue
);
83 BOOST_CHECK_EQUAL((minmax_iter
.first
).read(queue
), 0);
84 BOOST_CHECK_EQUAL((minmax_iter
.second
).read(queue
), 513);
87 boost::compute::minmax_element(vector
.begin(), vector
.end(), lessint
, queue
);
88 BOOST_CHECK_EQUAL((minmax_iter
.first
).read(queue
), 0);
89 BOOST_CHECK_EQUAL((minmax_iter
.second
).read(queue
), 513);
91 // find_extrama_on_cpu
93 // make sure find_extrama_on_cpu is used, no serial_find_extrema
94 std::string cache_key
=
95 "__boost_find_extrema_cpu_4";
96 boost::shared_ptr
<bc::detail::parameter_cache
> parameters
=
97 bc::detail::parameter_cache::get_global_cache(device
);
100 uint_ map_copy_threshold
=
101 parameters
->get(cache_key
, "serial_find_extrema_threshold", 0);
102 // force find_extrama_on_cpu
103 parameters
->set(cache_key
, "serial_find_extrema_threshold", 16);
105 min_iter
= boost::compute::detail::find_extrema_on_cpu(
106 vector
.begin(), vector
.end(), lessint
, true /* find minimum */, queue
108 BOOST_CHECK(min_iter
== vector
.begin() + 512);
109 BOOST_CHECK_EQUAL((vector
.begin() + 512).read(queue
), 0);
110 BOOST_CHECK_EQUAL(min_iter
.read(queue
), 0);
112 max_iter
= boost::compute::detail::find_extrema_on_cpu(
113 vector
.begin(), vector
.end(), lessint
, false /* find minimum */, queue
115 BOOST_CHECK(max_iter
== vector
.end() - 512);
116 BOOST_CHECK_EQUAL((vector
.end() - 512).read(queue
), 513);
117 BOOST_CHECK_EQUAL(max_iter
.read(queue
), 513);
120 parameters
->set(cache_key
, "serial_find_extrema_threshold", map_copy_threshold
);
122 if(is_apple_cpu_device(device
)) {
124 << "skipping all further tests due to Apple platform"
125 << " behavior when local memory is used on a CPU device"
130 // find_extrama_with_reduce
131 min_iter
= boost::compute::detail::find_extrema_with_reduce(
132 vector
.begin(), vector
.end(), lessint
, true /* find minimum */, queue
134 BOOST_CHECK(min_iter
== vector
.begin() + 512);
135 BOOST_CHECK_EQUAL((vector
.begin() + 512).read(queue
), 0);
136 BOOST_CHECK_EQUAL(min_iter
.read(queue
), 0);
138 max_iter
= boost::compute::detail::find_extrema_with_reduce(
139 vector
.begin(), vector
.end(), lessint
, false /* find minimum */, queue
141 BOOST_CHECK(max_iter
== vector
.end() - 512);
142 BOOST_CHECK_EQUAL((vector
.end() - 512).read(queue
), 513);
143 BOOST_CHECK_EQUAL(max_iter
.read(queue
), 513);
145 // find_extram_with_atomics
146 min_iter
= boost::compute::detail::find_extrema_with_atomics(
147 vector
.begin(), vector
.end(), lessint
, true /* find minimum */, queue
149 BOOST_CHECK(min_iter
== vector
.begin() + 512);
150 BOOST_CHECK_EQUAL((vector
.begin() + 512).read(queue
), 0);
151 BOOST_CHECK_EQUAL(min_iter
.read(queue
), 0);
153 max_iter
= boost::compute::detail::find_extrema_with_atomics(
154 vector
.begin(), vector
.end(), lessint
, false /* find minimum */, queue
156 BOOST_CHECK(max_iter
== vector
.end() - 512);
157 BOOST_CHECK_EQUAL((vector
.end() - 512).read(queue
), 513);
158 BOOST_CHECK_EQUAL(max_iter
.read(queue
), 513);
161 BOOST_AUTO_TEST_CASE(int2_min_max_custom_comparision_function
)
163 using boost::compute::int2_
;
164 using boost::compute::uint_
;
166 boost::compute::vector
<int2_
> vector(context
);
167 vector
.push_back(int2_(1, 10), queue
);
168 vector
.push_back(int2_(2, -100), queue
);
169 vector
.push_back(int2_(3, 30), queue
);
170 vector
.push_back(int2_(4, 20), queue
);
171 vector
.push_back(int2_(5, 5), queue
);
172 vector
.push_back(int2_(6, -80), queue
);
173 vector
.push_back(int2_(7, 21), queue
);
174 vector
.push_back(int2_(8, -5), queue
);
176 BOOST_COMPUTE_FUNCTION(bool, compare_second
, (const int2_ a
, const int2_ b
),
181 boost::compute::vector
<int2_
>::iterator min_iter
=
182 boost::compute::min_element(
183 vector
.begin(), vector
.end(), compare_second
, queue
185 BOOST_CHECK(min_iter
== vector
.begin() + 1);
186 BOOST_CHECK_EQUAL(*min_iter
, int2_(2, -100));
188 boost::compute::vector
<int2_
>::iterator max_iter
=
189 boost::compute::max_element(
190 vector
.begin(), vector
.end(), compare_second
, queue
192 BOOST_CHECK(max_iter
== vector
.begin() + 2);
193 BOOST_CHECK_EQUAL(*max_iter
, int2_(3, 30));
195 // find_extrama_on_cpu
197 // make sure find_extrama_on_cpu is used, no serial_find_extrema
198 std::string cache_key
=
199 "__boost_find_extrema_cpu_8";
200 boost::shared_ptr
<bc::detail::parameter_cache
> parameters
=
201 bc::detail::parameter_cache::get_global_cache(device
);
204 uint_ map_copy_threshold
=
205 parameters
->get(cache_key
, "serial_find_extrema_threshold", 0);
206 // force find_extrama_on_cpu
207 parameters
->set(cache_key
, "serial_find_extrema_threshold", 16);
209 min_iter
= boost::compute::detail::find_extrema_on_cpu(
210 vector
.begin(), vector
.end(), compare_second
, true /* find minimum */, queue
212 BOOST_CHECK(min_iter
== vector
.begin() + 1);
213 BOOST_CHECK_EQUAL(*min_iter
, int2_(2, -100));
215 max_iter
= boost::compute::detail::find_extrema_on_cpu(
216 vector
.begin(), vector
.end(), compare_second
, false /* find minimum */, queue
218 BOOST_CHECK(max_iter
== vector
.begin() + 2);
219 BOOST_CHECK_EQUAL(*max_iter
, int2_(3, 30));
222 parameters
->set(cache_key
, "serial_find_extrema_threshold", map_copy_threshold
);
224 if(is_apple_cpu_device(device
)) {
226 << "skipping all further tests due to Apple platform"
227 << " behavior when local memory is used on a CPU device"
232 // find_extrama_with_reduce
233 min_iter
= boost::compute::detail::find_extrema_with_reduce(
234 vector
.begin(), vector
.end(), compare_second
, true /* find minimum */, queue
236 BOOST_CHECK(min_iter
== vector
.begin() + 1);
237 BOOST_CHECK_EQUAL(*min_iter
, int2_(2, -100));
239 max_iter
= boost::compute::detail::find_extrema_with_reduce(
240 vector
.begin(), vector
.end(), compare_second
, false /* find minimum */, queue
242 BOOST_CHECK(max_iter
== vector
.begin() + 2);
243 BOOST_CHECK_EQUAL(*max_iter
, int2_(3, 30));
245 // find_extram_with_atomics
246 min_iter
= boost::compute::detail::find_extrema_with_atomics(
247 vector
.begin(), vector
.end(), compare_second
, true /* find minimum */, queue
249 BOOST_CHECK(min_iter
== vector
.begin() + 1);
250 BOOST_CHECK_EQUAL(*min_iter
, int2_(2, -100));
252 max_iter
= boost::compute::detail::find_extrema_with_atomics(
253 vector
.begin(), vector
.end(), compare_second
, false /* find minimum */, queue
255 BOOST_CHECK(max_iter
== vector
.begin() + 2);
256 BOOST_CHECK_EQUAL(*max_iter
, int2_(3, 30));
259 BOOST_AUTO_TEST_CASE(iota_min_max
)
261 boost::compute::vector
<int> vector(5000, context
);
263 // fill with 0 -> 4999
264 boost::compute::iota(vector
.begin(), vector
.end(), 0, queue
);
266 boost::compute::vector
<int>::iterator min_iter
=
267 boost::compute::min_element(vector
.begin(), vector
.end(), queue
);
268 BOOST_CHECK(min_iter
== vector
.begin());
269 BOOST_CHECK_EQUAL(*min_iter
, 0);
271 boost::compute::vector
<int>::iterator max_iter
=
272 boost::compute::max_element(vector
.begin(), vector
.end(), queue
);
273 BOOST_CHECK(max_iter
== vector
.end() - 1);
274 BOOST_CHECK_EQUAL(*max_iter
, 4999);
277 boost::compute::min_element(
278 vector
.begin() + 1000,
282 BOOST_CHECK(min_iter
== vector
.begin() + 1000);
283 BOOST_CHECK_EQUAL(*min_iter
, 1000);
286 boost::compute::max_element(
287 vector
.begin() + 1000,
291 BOOST_CHECK(max_iter
== vector
.begin() + 3999);
292 BOOST_CHECK_EQUAL(*max_iter
, 3999);
294 // fill with -2500 -> 2499
295 boost::compute::iota(vector
.begin(), vector
.end(), -2500, queue
);
297 boost::compute::min_element(vector
.begin(), vector
.end(), queue
);
298 BOOST_CHECK(min_iter
== vector
.begin());
299 BOOST_CHECK_EQUAL(*min_iter
, -2500);
302 boost::compute::max_element(vector
.begin(), vector
.end(), queue
);
303 BOOST_CHECK(max_iter
== vector
.end() - 1);
304 BOOST_CHECK_EQUAL(*max_iter
, 2499);
307 // uses max_element() and length() to find the longest 2d vector
308 BOOST_AUTO_TEST_CASE(max_vector_length
)
310 float data
[] = { -1.5f
, 3.2f
,
315 boost::compute::vector
<boost::compute::float2_
> vector(
316 reinterpret_cast<boost::compute::float2_
*>(data
),
317 reinterpret_cast<boost::compute::float2_
*>(data
) + 5,
321 // find length of the longest vector
322 typedef boost::compute::transform_iterator
<
323 boost::compute::vector
<boost::compute::float2_
>::iterator
,
324 boost::compute::length
<boost::compute::float2_
>
325 > length_transform_iter
;
327 length_transform_iter max_iter
=
328 boost::compute::max_element(
329 boost::compute::make_transform_iterator(
331 boost::compute::length
<boost::compute::float2_
>()
333 boost::compute::make_transform_iterator(
335 boost::compute::length
<boost::compute::float2_
>()
340 max_iter
== boost::compute::make_transform_iterator(
342 boost::compute::length
<boost::compute::float2_
>()
345 BOOST_CHECK(max_iter
.base() == vector
.begin() + 1);
346 BOOST_CHECK_EQUAL(*max_iter
, float(10.0));
348 // find length of the shortest vector
349 length_transform_iter min_iter
=
350 boost::compute::min_element(
351 boost::compute::make_transform_iterator(
353 boost::compute::length
<boost::compute::float2_
>()
355 boost::compute::make_transform_iterator(
357 boost::compute::length
<boost::compute::float2_
>()
362 min_iter
== boost::compute::make_transform_iterator(
364 boost::compute::length
<boost::compute::float2_
>()
367 BOOST_CHECK(min_iter
.base() == vector
.begin() + 3);
368 BOOST_CHECK_EQUAL(*min_iter
, float(0.5));
371 // uses max_element() and popcount() to find the value with the most 1 bits
372 BOOST_AUTO_TEST_CASE(max_bits_set
)
374 using boost::compute::uint_
;
376 uint_ data
[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
377 boost::compute::vector
<uint_
> vector(data
, data
+ 10, queue
);
379 boost::compute::vector
<uint_
>::iterator iter
=
380 boost::compute::max_element(
381 boost::compute::make_transform_iterator(
383 boost::compute::popcount
<uint_
>()
385 boost::compute::make_transform_iterator(
387 boost::compute::popcount
<uint_
>()
392 BOOST_CHECK(iter
== vector
.begin() + 7);
393 BOOST_CHECK_EQUAL(uint_(*iter
), uint_(7));
396 BOOST_AUTO_TEST_SUITE_END()