From bffc9f74fba86119ea45c46420c19f37be46a4ba Mon Sep 17 00:00:00 2001 From: Jakub Szuppe Date: Sat, 28 May 2016 22:46:35 +0200 Subject: [PATCH] Fix async copying when first == last (input is empty) --- include/boost/compute/algorithm/copy.hpp | 22 ++++-- test/test_copy_type_mismatch.cpp | 96 ++++++++++++++++++++++++ 2 files changed, 112 insertions(+), 6 deletions(-) diff --git a/include/boost/compute/algorithm/copy.hpp b/include/boost/compute/algorithm/copy.hpp index 89829bf1..ba929c6d 100644 --- a/include/boost/compute/algorithm/copy.hpp +++ b/include/boost/compute/algorithm/copy.hpp @@ -179,8 +179,8 @@ dispatch_copy(InputIterator first, ); // select copy method based on thresholds & input_size_bytes - size_t input_size = iterator_range_size(first, last); - size_t input_size_bytes = input_size * sizeof(input_type); + size_t count = iterator_range_size(first, last); + size_t input_size_bytes = count * sizeof(input_type); // [0; map_copy_threshold) -> copy_to_device_map() if(input_size_bytes < map_copy_threshold) { @@ -195,13 +195,14 @@ dispatch_copy(InputIterator first, // [direct_copy_threshold; inf) -> map [first; last) to device and // run copy kernel on device for copying & casting + // At this point we are sure that count > 1 (first != last). ::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, + count, context ); return copy_on_device(mapped_host.begin(), mapped_host.end(), result, queue); @@ -335,7 +336,11 @@ dispatch_copy_async(InputIterator first, typedef typename std::iterator_traits::value_type input_type; const context &context = queue.get_context(); - size_t input_size = iterator_range_size(first, last); + size_t count = iterator_range_size(first, last); + + if(count < size_t(1)) { + return future(); + } // map [first; last) to device and run copy kernel // on device for copying & casting @@ -345,7 +350,7 @@ dispatch_copy_async(InputIterator first, const_cast( ::boost::addressof(*first) ), - input_size, + count, context ); return copy_on_device_async( @@ -541,7 +546,8 @@ dispatch_copy(InputIterator first, // [direct_copy_threshold; inf) -> map [result; result + input_size) to // device and run copy kernel on device for copying & casting - // map host memory to device + // map host memory to device. + // At this point we are sure that count > 1 (first != last). buffer mapped_host( context, count * sizeof(output_type), @@ -623,6 +629,10 @@ dispatch_copy_async(InputIterator first, const context &context = queue.get_context(); size_t count = iterator_range_size(first, last); + if(count < size_t(1)) { + return future(); + } + // map host memory to device buffer mapped_host( context, diff --git a/test/test_copy_type_mismatch.cpp b/test/test_copy_type_mismatch.cpp index 7b622d61..8e97fcd6 100644 --- a/test/test_copy_type_mismatch.cpp +++ b/test/test_copy_type_mismatch.cpp @@ -267,6 +267,34 @@ BOOST_AUTO_TEST_CASE(copy_async_to_device_float_to_int) ); } +BOOST_AUTO_TEST_CASE(copy_async_to_device_float_to_int_empty) +{ + using compute::int_; + using compute::float_; + + float_ host[] = { 6.1f, -10.2f, 19.3f, 25.4f }; + bc::vector device_vector(size_t(4), int_(1), queue); + + // copy nothing to int device vector + compute::future::iterator > future = + bc::copy_async(host, host, device_vector.begin(), queue); + if(future.valid()) { + future.wait(); + } + + CHECK_RANGE_EQUAL( + int_, + 4, + device_vector, + ( + int_(1), + int_(1), + int_(1), + int_(1) + ) + ); +} + // Test copying from a std::list to a bc::vector. This differs from // the test copying from std::vector because std::list has non-contiguous // storage for its data values. @@ -611,6 +639,40 @@ BOOST_AUTO_TEST_CASE(copy_async_on_device_float_to_int) ); } +BOOST_AUTO_TEST_CASE(copy_async_on_device_float_to_int_empty) +{ + using compute::int_; + using compute::float_; + + float_ data[] = { 6.1f, -10.2f, 19.3f, 25.4f }; + bc::vector device_fvector(data, data + 4, queue); + bc::vector device_ivector(size_t(4), int_(1), queue); + + // copy device float vector to device int vector + compute::future future = + bc::copy_async( + device_fvector.begin(), + device_fvector.begin(), + device_ivector.begin(), + queue + ); + if(future.valid()) { + future.wait(); + } + + CHECK_RANGE_EQUAL( + int_, + 4, + device_ivector, + ( + int_(1), + int_(1), + int_(1), + int_(1) + ) + ); +} + // SVM requires OpenCL 2.0 #if defined(CL_VERSION_2_0) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED) BOOST_AUTO_TEST_CASE(copy_on_device_buffer_to_svm_float_to_int) @@ -1108,6 +1170,40 @@ BOOST_AUTO_TEST_CASE(copy_async_to_host_float_to_int) ); } +BOOST_AUTO_TEST_CASE(copy_async_to_host_float_to_int_empty) +{ + using compute::int_; + using compute::float_; + + float_ data[] = { 6.1f, -10.2f, 19.3f, 25.4f }; + bc::vector device_vector(data, data + 4, queue); + std::vector host_vector(device_vector.size(), int_(1)); + + // copy device float vector to host int vector + compute::future future = + bc::copy_async( + device_vector.begin(), + device_vector.begin(), + host_vector.begin(), + queue + ); + if(future.valid()) { + future.wait(); + } + + CHECK_HOST_RANGE_EQUAL( + int_, + 4, + host_vector.begin(), + ( + int_(1), + int_(1), + int_(1), + int_(1) + ) + ); +} + // SVM requires OpenCL 2.0 #if defined(CL_VERSION_2_0) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED) BOOST_AUTO_TEST_CASE(copy_to_host_svm_float_to_int_map)