From d12e07c0e9f96aca2f54652f76743c5e488c8db5 Mon Sep 17 00:00:00 2001 From: Jakub Szuppe Date: Sat, 21 May 2016 16:58:15 +0200 Subject: [PATCH] Fix type-safety issues for async copying host->device --- include/boost/compute/algorithm/copy.hpp | 57 ++++++++++++++++++++++-- test/test_copy_type_mismatch.cpp | 26 +++++++++++ 2 files changed, 80 insertions(+), 3 deletions(-) diff --git a/include/boost/compute/algorithm/copy.hpp b/include/boost/compute/algorithm/copy.hpp index 52fe5de5..655485a6 100644 --- a/include/boost/compute/algorithm/copy.hpp +++ b/include/boost/compute/algorithm/copy.hpp @@ -209,9 +209,14 @@ dispatch_copy_async(InputIterator first, InputIterator last, OutputIterator result, command_queue &queue, - typename boost::enable_if_c< - !is_device_iterator::value && - is_device_iterator::value + typename boost::enable_if< + mpl::and_< + mpl::not_< + is_device_iterator + >, + is_device_iterator, + is_same_value_type + > >::type* = 0) { BOOST_STATIC_ASSERT_MSG( @@ -222,6 +227,52 @@ dispatch_copy_async(InputIterator first, return copy_to_device_async(first, last, result, queue); } +// host -> device (async) +// Type mismatch between InputIterator and OutputIterator value_types +template +inline future +dispatch_copy_async(InputIterator first, + InputIterator last, + OutputIterator result, + command_queue &queue, + typename boost::enable_if< + mpl::and_< + mpl::not_< + is_device_iterator + >, + is_device_iterator, + mpl::not_< + is_same_value_type + > + > + >::type* = 0) +{ + BOOST_STATIC_ASSERT_MSG( + is_contiguous_iterator::value, + "copy_async() is only supported for contiguous host iterators" + ); + + typedef typename std::iterator_traits::value_type input_type; + + const context &context = queue.get_context(); + size_t input_size = iterator_range_size(first, last); + + // map [first; last) to device and run copy kernel + // on device for copying & casting + ::boost::compute::mapped_view mapped_host( + // make sure it's a pointer to constant data + // to force read only mapping + const_cast( + ::boost::addressof(*first) + ), + input_size, + context + ); + return copy_on_device_async( + mapped_host.begin(), mapped_host.end(), result, queue + ); +} + // device -> host template inline OutputIterator diff --git a/test/test_copy_type_mismatch.cpp b/test/test_copy_type_mismatch.cpp index 885f969f..f84b0ccc 100644 --- a/test/test_copy_type_mismatch.cpp +++ b/test/test_copy_type_mismatch.cpp @@ -238,4 +238,30 @@ BOOST_AUTO_TEST_CASE(copy_host_float_to_device_int_with_transform) parameters->set(cache_key, "direct_copy_threshold", direct_copy_threshold); } +BOOST_AUTO_TEST_CASE(copy_async_host_float_to_device_int) +{ + using compute::int_; + using compute::float_; + + float_ host[] = { 6.1f, -10.2f, 19.3f, 25.4f }; + bc::vector device_vector(4, context); + + // copy host float data to int device vector + compute::future future = + bc::copy_async(host, host + 4, device_vector.begin(), queue); + future.wait(); + + CHECK_RANGE_EQUAL( + int_, + 4, + device_vector, + ( + static_cast(6.1f), + static_cast(-10.2f), + static_cast(19.3f), + static_cast(25.4f) + ) + ); +} + BOOST_AUTO_TEST_SUITE_END()