123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490 |
- //---------------------------------------------------------------------------//
- // Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@gmail.com>
- //
- // Distributed under the Boost Software License, Version 1.0
- // See accompanying file LICENSE_1_0.txt or copy at
- // http://www.boost.org/LICENSE_1_0.txt
- //
- // See http://boostorg.github.com/compute for more information.
- //---------------------------------------------------------------------------//
- // Undefining BOOST_COMPUTE_USE_OFFLINE_CACHE macro as we want to modify cached
- // parameters for copy algorithm without any undesirable consequences (like
- // saving modified values of those parameters).
- #ifdef BOOST_COMPUTE_USE_OFFLINE_CACHE
- #undef BOOST_COMPUTE_USE_OFFLINE_CACHE
- #endif
- #define BOOST_TEST_MODULE TestScan
- #include <boost/test/unit_test.hpp>
- #include <numeric>
- #include <functional>
- #include <vector>
- #include <boost/compute/functional.hpp>
- #include <boost/compute/lambda.hpp>
- #include <boost/compute/system.hpp>
- #include <boost/compute/command_queue.hpp>
- #include <boost/compute/algorithm/copy.hpp>
- #include <boost/compute/algorithm/exclusive_scan.hpp>
- #include <boost/compute/algorithm/inclusive_scan.hpp>
- #include <boost/compute/container/vector.hpp>
- #include <boost/compute/iterator/counting_iterator.hpp>
- #include <boost/compute/iterator/transform_iterator.hpp>
- #include "check_macros.hpp"
- #include "context_setup.hpp"
- namespace bc = boost::compute;
- BOOST_AUTO_TEST_CASE(inclusive_scan_int)
- {
- using boost::compute::uint_;
- using boost::compute::int_;
- int_ data[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
- bc::vector<int_> vector(data, data + 12, queue);
- BOOST_CHECK_EQUAL(vector.size(), size_t(12));
- bc::vector<int_> result(12, context);
- BOOST_CHECK_EQUAL(result.size(), size_t(12));
- // inclusive scan
- bc::inclusive_scan(vector.begin(), vector.end(), result.begin(), queue);
- CHECK_RANGE_EQUAL(int_, 12, result, (0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66));
- // in-place inclusive scan
- CHECK_RANGE_EQUAL(int_, 12, vector, (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11));
- bc::inclusive_scan(vector.begin(), vector.end(), vector.begin(), queue);
- CHECK_RANGE_EQUAL(int_, 12, vector, (0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66));
- // scan_on_cpu
- bc::copy(data, data + 12, vector.begin(), queue);
- // make sure parallel scan_on_cpu is used, no serial_scan
- std::string cache_key =
- "__boost_scan_cpu_4";
- boost::shared_ptr<bc::detail::parameter_cache> parameters =
- bc::detail::parameter_cache::get_global_cache(device);
- // save
- uint_ map_copy_threshold =
- parameters->get(cache_key, "serial_scan_threshold", 0);
- // force parallel scan_on_cpu
- parameters->set(cache_key, "serial_scan_threshold", 0);
- // inclusive scan
- bc::inclusive_scan(vector.begin(), vector.end(), result.begin(), queue);
- CHECK_RANGE_EQUAL(int_, 12, result, (0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66));
- // in-place inclusive scan
- CHECK_RANGE_EQUAL(int_, 12, vector, (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11));
- bc::inclusive_scan(vector.begin(), vector.end(), vector.begin(), queue);
- CHECK_RANGE_EQUAL(int_, 12, vector, (0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66));
- // restore
- parameters->set(cache_key, "serial_scan_threshold", map_copy_threshold);
- }
- BOOST_AUTO_TEST_CASE(exclusive_scan_int)
- {
- using boost::compute::uint_;
- using boost::compute::int_;
- int_ data[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
- bc::vector<int_> vector(data, data + 12, queue);
- BOOST_CHECK_EQUAL(vector.size(), size_t(12));
- bc::vector<int_> result(size_t(12), int_(0), queue);
- BOOST_CHECK_EQUAL(result.size(), size_t(12));
- // exclusive scan
- bc::exclusive_scan(vector.begin(), vector.end(), result.begin(), queue);
- CHECK_RANGE_EQUAL(int_, 12, result, (0, 0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55));
- // in-place exclusive scan
- CHECK_RANGE_EQUAL(int_, 12, vector, (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11));
- bc::exclusive_scan(vector.begin(), vector.end(), vector.begin(), queue);
- CHECK_RANGE_EQUAL(int_, 12, vector, (0, 0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55));
- // scan_on_cpu
- bc::copy(data, data + 12, vector.begin(), queue);
- // make sure parallel scan_on_cpu is used, no serial_scan
- std::string cache_key =
- "__boost_scan_cpu_4";
- boost::shared_ptr<bc::detail::parameter_cache> parameters =
- bc::detail::parameter_cache::get_global_cache(device);
- // save
- uint_ map_copy_threshold =
- parameters->get(cache_key, "serial_scan_threshold", 0);
- // force parallel scan_on_cpu
- parameters->set(cache_key, "serial_scan_threshold", 0);
- // exclusive scan
- bc::exclusive_scan(vector.begin(), vector.end(), result.begin(), queue);
- CHECK_RANGE_EQUAL(int_, 12, result, (0, 0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55));
- // in-place exclusive scan
- CHECK_RANGE_EQUAL(int_, 12, vector, (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11));
- bc::exclusive_scan(vector.begin(), vector.end(), vector.begin(), queue);
- CHECK_RANGE_EQUAL(int_, 12, vector, (0, 0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55));
- // restore
- parameters->set(cache_key, "serial_scan_threshold", map_copy_threshold);
- }
- BOOST_AUTO_TEST_CASE(inclusive_scan_int2)
- {
- using boost::compute::int_;
- using boost::compute::uint_;
- using boost::compute::int2_;
- int_ data[] = { 1, 2,
- 3, 4,
- 5, 6,
- 7, 8,
- 9, 0 };
- boost::compute::vector<int2_> input(reinterpret_cast<int2_*>(data),
- reinterpret_cast<int2_*>(data) + 5,
- queue);
- BOOST_CHECK_EQUAL(input.size(), size_t(5));
- boost::compute::vector<int2_> output(5, context);
- boost::compute::inclusive_scan(input.begin(), input.end(), output.begin(),
- queue);
- CHECK_RANGE_EQUAL(
- int2_, 5, output,
- (int2_(1, 2), int2_(4, 6), int2_(9, 12), int2_(16, 20), int2_(25, 20))
- );
- // scan_on_cpu
- // make sure parallel scan_on_cpu is used, no serial_scan
- std::string cache_key =
- "__boost_scan_cpu_8";
- boost::shared_ptr<bc::detail::parameter_cache> parameters =
- bc::detail::parameter_cache::get_global_cache(device);
- // save
- uint_ map_copy_threshold =
- parameters->get(cache_key, "serial_scan_threshold", 0);
- // force parallel scan_on_cpu
- parameters->set(cache_key, "serial_scan_threshold", 0);
- boost::compute::inclusive_scan(input.begin(), input.end(), output.begin(),
- queue);
- CHECK_RANGE_EQUAL(
- int2_, 5, output,
- (int2_(1, 2), int2_(4, 6), int2_(9, 12), int2_(16, 20), int2_(25, 20))
- );
- // restore
- parameters->set(cache_key, "serial_scan_threshold", map_copy_threshold);
- }
- BOOST_AUTO_TEST_CASE(inclusive_scan_counting_iterator)
- {
- using boost::compute::int_;
- using boost::compute::uint_;
- bc::vector<int_> result(10, context);
- bc::inclusive_scan(bc::make_counting_iterator(1),
- bc::make_counting_iterator(11),
- result.begin(), queue);
- CHECK_RANGE_EQUAL(int_, 10, result, (1, 3, 6, 10, 15, 21, 28, 36, 45, 55));
- // scan_on_cpu
- // make sure parallel scan_on_cpu is used, no serial_scan
- std::string cache_key =
- "__boost_scan_cpu_4";
- boost::shared_ptr<bc::detail::parameter_cache> parameters =
- bc::detail::parameter_cache::get_global_cache(device);
- // save
- uint_ map_copy_threshold =
- parameters->get(cache_key, "serial_scan_threshold", 0);
- // force parallel scan_on_cpu
- parameters->set(cache_key, "serial_scan_threshold", 0);
- bc::inclusive_scan(bc::make_counting_iterator(1),
- bc::make_counting_iterator(11),
- result.begin(), queue);
- CHECK_RANGE_EQUAL(int_, 10, result, (1, 3, 6, 10, 15, 21, 28, 36, 45, 55));
- // restore
- parameters->set(cache_key, "serial_scan_threshold", map_copy_threshold);
- }
- BOOST_AUTO_TEST_CASE(exclusive_scan_counting_iterator)
- {
- using boost::compute::int_;
- using boost::compute::uint_;
- bc::vector<int_> result(10, context);
- bc::exclusive_scan(bc::make_counting_iterator(1),
- bc::make_counting_iterator(11),
- result.begin(), queue);
- CHECK_RANGE_EQUAL(int_, 10, result, (0, 1, 3, 6, 10, 15, 21, 28, 36, 45));
- // scan_on_cpu
- // make sure parallel scan_on_cpu is used, no serial_scan
- std::string cache_key =
- "__boost_scan_cpu_4";
- boost::shared_ptr<bc::detail::parameter_cache> parameters =
- bc::detail::parameter_cache::get_global_cache(device);
- // save
- uint_ map_copy_threshold =
- parameters->get(cache_key, "serial_scan_threshold", 0);
- // force parallel scan_on_cpu
- parameters->set(cache_key, "serial_scan_threshold", 0);
- bc::exclusive_scan(bc::make_counting_iterator(1),
- bc::make_counting_iterator(11),
- result.begin(), queue);
- CHECK_RANGE_EQUAL(int_, 10, result, (0, 1, 3, 6, 10, 15, 21, 28, 36, 45));
- // restore
- parameters->set(cache_key, "serial_scan_threshold", map_copy_threshold);
- }
- BOOST_AUTO_TEST_CASE(inclusive_scan_transform_iterator)
- {
- float data[] = { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f };
- bc::vector<float> input(data, data + 5, queue);
- bc::vector<float> output(5, context);
- // normal inclusive scan of the input
- bc::inclusive_scan(input.begin(), input.end(), output.begin(), queue);
- queue.finish();
- BOOST_CHECK_CLOSE(float(output[0]), 1.0f, 1e-4f);
- BOOST_CHECK_CLOSE(float(output[1]), 3.0f, 1e-4f);
- BOOST_CHECK_CLOSE(float(output[2]), 6.0f, 1e-4f);
- BOOST_CHECK_CLOSE(float(output[3]), 10.0f, 1e-4f);
- BOOST_CHECK_CLOSE(float(output[4]), 15.0f, 1e-4f);
- // inclusive scan of squares of the input
- using ::boost::compute::_1;
- bc::inclusive_scan(bc::make_transform_iterator(input.begin(), pown(_1, 2)),
- bc::make_transform_iterator(input.end(), pown(_1, 2)),
- output.begin(), queue);
- queue.finish();
- BOOST_CHECK_CLOSE(float(output[0]), 1.0f, 1e-4f);
- BOOST_CHECK_CLOSE(float(output[1]), 5.0f, 1e-4f);
- BOOST_CHECK_CLOSE(float(output[2]), 14.0f, 1e-4f);
- BOOST_CHECK_CLOSE(float(output[3]), 30.0f, 1e-4f);
- BOOST_CHECK_CLOSE(float(output[4]), 55.0f, 1e-4f);
- }
- BOOST_AUTO_TEST_CASE(inclusive_scan_doctest)
- {
- //! [inclusive_scan_int]
- // setup input
- int data[] = { 1, 2, 3, 4 };
- boost::compute::vector<int> input(data, data + 4, queue);
- // setup output
- boost::compute::vector<int> output(4, context);
- // scan values
- boost::compute::inclusive_scan(
- input.begin(), input.end(), output.begin(), queue
- );
- // output = [ 1, 3, 6, 10 ]
- //! [inclusive_scan_int]
- CHECK_RANGE_EQUAL(int, 4, output, (1, 3, 6, 10));
- }
- BOOST_AUTO_TEST_CASE(exclusive_scan_doctest)
- {
- //! [exclusive_scan_int]
- // setup input
- int data[] = { 1, 2, 3, 4 };
- boost::compute::vector<int> input(data, data + 4, queue);
- // setup output
- boost::compute::vector<int> output(4, context);
- // scan values
- boost::compute::exclusive_scan(
- input.begin(), input.end(), output.begin(), queue
- );
- // output = [ 0, 1, 3, 6 ]
- //! [exclusive_scan_int]
- CHECK_RANGE_EQUAL(int, 4, output, (0, 1, 3, 6));
- }
- BOOST_AUTO_TEST_CASE(inclusive_scan_int_multiplies)
- {
- //! [inclusive_scan_int_multiplies]
- // setup input
- int data[] = { 1, 2, 1, 2, 3 };
- boost::compute::vector<int> input(data, data + 5, queue);
- // setup output
- boost::compute::vector<int> output(5, context);
- // inclusive scan with multiplication
- boost::compute::inclusive_scan(
- input.begin(), input.end(), output.begin(),
- boost::compute::multiplies<int>(), queue
- );
- // output = [1, 2, 2, 4, 12]
- //! [inclusive_scan_int_multiplies]
- BOOST_CHECK_EQUAL(input.size(), size_t(5));
- BOOST_CHECK_EQUAL(output.size(), size_t(5));
- CHECK_RANGE_EQUAL(int, 5, output, (1, 2, 2, 4, 12));
- // in-place inclusive scan
- CHECK_RANGE_EQUAL(int, 5, input, (1, 2, 1, 2, 3));
- boost::compute::inclusive_scan(input.begin(), input.end(), input.begin(),
- boost::compute::multiplies<int>(), queue);
- CHECK_RANGE_EQUAL(int, 5, input, (1, 2, 2, 4, 12));
- }
- BOOST_AUTO_TEST_CASE(exclusive_scan_int_multiplies)
- {
- //! [exclusive_scan_int_multiplies]
- // setup input
- int data[] = { 1, 2, 1, 2, 3 };
- boost::compute::vector<int> input(data, data + 5, queue);
- // setup output
- boost::compute::vector<int> output(5, context);
- // exclusive_scan with multiplication
- // initial value equals 10
- boost::compute::exclusive_scan(
- input.begin(), input.end(), output.begin(),
- int(10), boost::compute::multiplies<int>(), queue
- );
- // output = [10, 10, 20, 20, 40]
- //! [exclusive_scan_int_multiplies]
- BOOST_CHECK_EQUAL(input.size(), size_t(5));
- BOOST_CHECK_EQUAL(output.size(), size_t(5));
- CHECK_RANGE_EQUAL(int, 5, output, (10, 10, 20, 20, 40));
- // in-place exclusive scan
- CHECK_RANGE_EQUAL(int, 5, input, (1, 2, 1, 2, 3));
- bc::exclusive_scan(input.begin(), input.end(), input.begin(),
- int(10), bc::multiplies<int>(), queue);
- CHECK_RANGE_EQUAL(int, 5, input, (10, 10, 20, 20, 40));
- }
- BOOST_AUTO_TEST_CASE(inclusive_scan_int_multiplies_long_vector)
- {
- size_t size = 1000;
- bc::vector<int> device_vector(size, int(2), queue);
- BOOST_CHECK_EQUAL(device_vector.size(), size);
- bc::inclusive_scan(device_vector.begin(), device_vector.end(),
- device_vector.begin(), bc::multiplies<int>(), queue);
- std::vector<int> host_vector(size, 2);
- BOOST_CHECK_EQUAL(host_vector.size(), size);
- bc::copy(device_vector.begin(), device_vector.end(),
- host_vector.begin(), queue);
- std::vector<int> test(size, 2);
- BOOST_CHECK_EQUAL(test.size(), size);
- std::partial_sum(test.begin(), test.end(),
- test.begin(), std::multiplies<int>());
- BOOST_CHECK_EQUAL_COLLECTIONS(host_vector.begin(), host_vector.end(),
- test.begin(), test.end());
- }
- BOOST_AUTO_TEST_CASE(exclusive_scan_int_multiplies_long_vector)
- {
- size_t size = 1000;
- bc::vector<int> device_vector(size, int(2), queue);
- BOOST_CHECK_EQUAL(device_vector.size(), size);
- bc::exclusive_scan(device_vector.begin(), device_vector.end(),
- device_vector.begin(), int(10), bc::multiplies<int>(),
- queue);
- std::vector<int> host_vector(size, 2);
- BOOST_CHECK_EQUAL(host_vector.size(), size);
- bc::copy(device_vector.begin(), device_vector.end(),
- host_vector.begin(), queue);
- std::vector<int> test(size, 2);
- BOOST_CHECK_EQUAL(test.size(), size);
- test[0] = 10;
- std::partial_sum(test.begin(), test.end(),
- test.begin(), std::multiplies<int>());
- BOOST_CHECK_EQUAL_COLLECTIONS(host_vector.begin(), host_vector.end(),
- test.begin(), test.end());
- }
- BOOST_AUTO_TEST_CASE(inclusive_scan_int_custom_function)
- {
- BOOST_COMPUTE_FUNCTION(int, multi, (int x, int y),
- {
- return x * y * 2;
- });
- int data[] = { 1, 2, 1, 2, 3 };
- bc::vector<int> vector(data, data + 5, queue);
- BOOST_CHECK_EQUAL(vector.size(), size_t(5));
- bc::vector<int> result(5, context);
- BOOST_CHECK_EQUAL(result.size(), size_t(5));
- // inclusive scan
- bc::inclusive_scan(vector.begin(), vector.end(), result.begin(),
- multi, queue);
- CHECK_RANGE_EQUAL(int, 5, result, (1, 4, 8, 32, 192));
- // in-place inclusive scan
- CHECK_RANGE_EQUAL(int, 5, vector, (1, 2, 1, 2, 3));
- bc::inclusive_scan(vector.begin(), vector.end(), vector.begin(),
- multi, queue);
- CHECK_RANGE_EQUAL(int, 5, vector, (1, 4, 8, 32, 192));
- }
- BOOST_AUTO_TEST_CASE(exclusive_scan_int_custom_function)
- {
- BOOST_COMPUTE_FUNCTION(int, multi, (int x, int y),
- {
- return x * y * 2;
- });
- int data[] = { 1, 2, 1, 2, 3 };
- bc::vector<int> vector(data, data + 5, queue);
- BOOST_CHECK_EQUAL(vector.size(), size_t(5));
- bc::vector<int> result(5, context);
- BOOST_CHECK_EQUAL(result.size(), size_t(5));
- // exclusive_scan
- bc::exclusive_scan(vector.begin(), vector.end(), result.begin(),
- int(1), multi, queue);
- CHECK_RANGE_EQUAL(int, 5, result, (1, 2, 8, 16, 64));
- // in-place exclusive scan
- CHECK_RANGE_EQUAL(int, 5, vector, (1, 2, 1, 2, 3));
- bc::exclusive_scan(vector.begin(), vector.end(), vector.begin(),
- int(1), multi, queue);
- CHECK_RANGE_EQUAL(int, 5, vector, (1, 2, 8, 16, 64));
- }
- BOOST_AUTO_TEST_SUITE_END()
|