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 #define BOOST_TEST_MODULE TestCopy
12 #include <boost/test/unit_test.hpp>
21 #include <boost/compute/svm.hpp>
22 #include <boost/compute/system.hpp>
23 #include <boost/compute/functional.hpp>
24 #include <boost/compute/command_queue.hpp>
25 #include <boost/compute/algorithm/copy.hpp>
26 #include <boost/compute/algorithm/copy_n.hpp>
27 #include <boost/compute/algorithm/fill.hpp>
28 #include <boost/compute/algorithm/iota.hpp>
29 #include <boost/compute/async/future.hpp>
30 #include <boost/compute/container/vector.hpp>
31 #include <boost/compute/detail/device_ptr.hpp>
32 #include <boost/compute/iterator/detail/swizzle_iterator.hpp>
35 #include "check_macros.hpp"
36 #include "context_setup.hpp"
38 namespace bc
= boost::compute
;
39 namespace compute
= boost::compute
;
41 BOOST_AUTO_TEST_CASE(copy_on_device
)
43 float data
[] = { 6.1f
, 10.2f
, 19.3f
, 25.4f
};
44 bc::vector
<float> a(4, context
);
45 bc::copy(data
, data
+ 4, a
.begin(), queue
);
46 CHECK_RANGE_EQUAL(float, 4, a
, (6.1f
, 10.2f
, 19.3f
, 25.4f
));
48 bc::vector
<float> b(4, context
);
49 bc::fill(b
.begin(), b
.end(), 0, queue
);
50 CHECK_RANGE_EQUAL(float, 4, b
, (0.0f
, 0.0f
, 0.0f
, 0.0f
));
52 bc::copy(a
.begin(), a
.end(), b
.begin(), queue
);
53 CHECK_RANGE_EQUAL(float, 4, b
, (6.1f
, 10.2f
, 19.3f
, 25.4f
));
55 bc::vector
<float> c(context
);
56 bc::copy(c
.begin(), c
.end(), b
.begin(), queue
);
57 CHECK_RANGE_EQUAL(float, 4, b
, (6.1f
, 10.2f
, 19.3f
, 25.4f
));
60 BOOST_AUTO_TEST_CASE(copy_on_device_device_ptr
)
62 float data
[] = { 6.1f
, 10.2f
, 19.3f
, 25.4f
};
63 bc::vector
<float> a(4, context
);
64 bc::copy(data
, data
+ 4, a
.begin(), queue
);
65 CHECK_RANGE_EQUAL(float, 4, a
, (6.1f
, 10.2f
, 19.3f
, 25.4f
));
67 bc::vector
<float> b(4, context
);
68 bc::detail::device_ptr
<float> b_ptr(b
.get_buffer(), size_t(0));
70 // buffer_iterator -> device_ptr
71 bc::copy(a
.begin(), a
.end(), b_ptr
, queue
);
72 CHECK_RANGE_EQUAL(float, 4, b
, (6.1f
, 10.2f
, 19.3f
, 25.4f
));
74 bc::vector
<float> c(4, context
);
75 bc::fill(c
.begin(), c
.end(), 0.0f
, queue
);
76 bc::detail::device_ptr
<float> c_ptr(c
.get_buffer(), size_t(2));
78 // device_ptr -> device_ptr
79 bc::copy(b_ptr
, b_ptr
+ 2, c_ptr
, queue
);
80 CHECK_RANGE_EQUAL(float, 4, c
, (0.0f
, 0.0f
, 6.1f
, 10.2f
));
82 // device_ptr -> buffer_iterator
83 bc::copy(c_ptr
, c_ptr
+ 2, a
.begin() + 2, queue
);
84 CHECK_RANGE_EQUAL(float, 4, a
, (6.1f
, 10.2f
, 6.1f
, 10.2f
));
87 BOOST_AUTO_TEST_CASE(copy_on_host
)
89 int data
[] = { 2, 4, 6, 8 };
90 std::vector
<int> vector(4);
91 compute::copy(data
, data
+ 4, vector
.begin(), queue
);
92 CHECK_RANGE_EQUAL(int, 4, vector
, (2, 4, 6, 8));
95 BOOST_AUTO_TEST_CASE(copy
)
97 int data
[] = { 1, 2, 5, 6 };
98 bc::vector
<int> vector(4, context
);
99 bc::copy(data
, data
+ 4, vector
.begin(), queue
);
100 CHECK_RANGE_EQUAL(int, 4, vector
, (1, 2, 5, 6));
102 std::vector
<int> host_vector(4);
103 bc::copy(vector
.begin(), vector
.end(), host_vector
.begin(), queue
);
104 BOOST_CHECK_EQUAL(host_vector
[0], 1);
105 BOOST_CHECK_EQUAL(host_vector
[1], 2);
106 BOOST_CHECK_EQUAL(host_vector
[2], 5);
107 BOOST_CHECK_EQUAL(host_vector
[3], 6);
110 BOOST_AUTO_TEST_CASE(empty_copy
)
112 int data
[] = { 1, 2, 5, 6 };
113 bc::vector
<int> a(4, context
);
114 bc::vector
<int> b(context
);
117 bc::copy(data
, data
+ 4, a
.begin(), queue
);
118 CHECK_RANGE_EQUAL(int, 4, a
, (1, 2, 5, 6));
120 bc::copy(b
.begin(), b
.end(), a
.begin(), queue
);
121 CHECK_RANGE_EQUAL(int, 4, a
, (1, 2, 5, 6));
123 bc::copy(c
.begin(), c
.end(), a
.begin(), queue
);
124 CHECK_RANGE_EQUAL(int, 4, a
, (1, 2, 5, 6));
126 bc::future
<bc::vector
<int>::iterator
> future
=
127 bc::copy_async(c
.begin(), c
.end(), a
.begin(), queue
);
130 CHECK_RANGE_EQUAL(int, 4, a
, (1, 2, 5, 6));
133 // Test copying from a std::list to a bc::vector. This differs from
134 // the test copying from std::vector because std::list has non-contigous
135 // storage for its data values.
136 BOOST_AUTO_TEST_CASE(copy_from_host_list
)
138 int data
[] = { -4, 12, 9, 0 };
139 std::list
<int> host_list(data
, data
+ 4);
141 bc::vector
<int> vector(4, context
);
142 bc::copy(host_list
.begin(), host_list
.end(), vector
.begin(), queue
);
143 CHECK_RANGE_EQUAL(int, 4, vector
, (-4, 12, 9, 0));
146 BOOST_AUTO_TEST_CASE(copy_n_int
)
148 int data
[] = { 1, 2, 3, 4, 5 };
149 bc::vector
<int> a(data
, data
+ 5, queue
);
151 bc::vector
<int> b(5, context
);
152 bc::fill(b
.begin(), b
.end(), 0, queue
);
153 bc::copy_n(a
.begin(), 3, b
.begin(), queue
);
154 CHECK_RANGE_EQUAL(int, 5, b
, (1, 2, 3, 0, 0));
156 bc::copy_n(b
.begin(), 4, a
.begin(), queue
);
157 CHECK_RANGE_EQUAL(int, 5, a
, (1, 2, 3, 0, 5));
160 BOOST_AUTO_TEST_CASE(copy_swizzle_iterator
)
165 int data
[] = { 1, 2, 3, 4,
170 bc::vector
<int4_
> input(reinterpret_cast<int4_
*>(data
),
171 reinterpret_cast<int4_
*>(data
) + 4,
173 BOOST_CHECK_EQUAL(input
.size(), size_t(4));
174 CHECK_RANGE_EQUAL(int4_
, 4, input
,
181 bc::vector
<int4_
> output4(4, context
);
183 bc::detail::make_swizzle_iterator
<4>(input
.begin(), "wzyx"),
184 bc::detail::make_swizzle_iterator
<4>(input
.end(), "wzyx"),
188 CHECK_RANGE_EQUAL(int4_
, 4, output4
,
195 bc::vector
<int2_
> output2(4, context
);
197 bc::detail::make_swizzle_iterator
<2>(input
.begin(), "xz"),
198 bc::detail::make_swizzle_iterator
<2>(input
.end(), "xz"),
202 CHECK_RANGE_EQUAL(int2_
, 4, output2
,
209 bc::vector
<int> output1(4, context
);
211 bc::detail::make_swizzle_iterator
<1>(input
.begin(), "y"),
212 bc::detail::make_swizzle_iterator
<1>(input
.end(), "y"),
216 CHECK_RANGE_EQUAL(int, 4, output1
, (2, 6, 1, 5));
219 BOOST_AUTO_TEST_CASE(copy_int_async
)
222 int host_data
[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
223 typedef int* host_iterator
;
226 bc::vector
<int> device_data(8, context
);
227 typedef bc::vector
<int>::iterator device_iterator
;
229 // copy data to device
230 bc::future
<device_iterator
> host_to_device_future
=
231 bc::copy_async(host_data
, host_data
+ 8, device_data
.begin(), queue
);
233 // wait for copy to complete
234 host_to_device_future
.wait();
237 CHECK_RANGE_EQUAL(int, 8, device_data
, (1, 2, 3, 4, 5, 6, 7, 8));
238 BOOST_VERIFY(host_to_device_future
.get() == device_data
.end());
240 // fill host data with zeros
241 std::fill(host_data
, host_data
+ 8, int(0));
243 // copy data back to host
244 bc::future
<host_iterator
> device_to_host_future
=
245 bc::copy_async(device_data
.begin(), device_data
.end(), host_data
, queue
);
247 // wait for copy to complete
248 device_to_host_future
.wait();
251 BOOST_CHECK_EQUAL(host_data
[0], int(1));
252 BOOST_CHECK_EQUAL(host_data
[1], int(2));
253 BOOST_CHECK_EQUAL(host_data
[2], int(3));
254 BOOST_CHECK_EQUAL(host_data
[3], int(4));
255 BOOST_CHECK_EQUAL(host_data
[4], int(5));
256 BOOST_CHECK_EQUAL(host_data
[5], int(6));
257 BOOST_CHECK_EQUAL(host_data
[6], int(7));
258 BOOST_CHECK_EQUAL(host_data
[7], int(8));
259 BOOST_VERIFY(device_to_host_future
.get() == host_data
+ 8);
262 BOOST_AUTO_TEST_CASE(copy_to_back_inserter
)
264 compute::vector
<int> device_vector(5, context
);
265 compute::iota(device_vector
.begin(), device_vector
.end(), 10, queue
);
267 std::vector
<int> host_vector
;
269 device_vector
.begin(),
271 std::back_inserter(host_vector
),
275 BOOST_CHECK_EQUAL(host_vector
.size(), size_t(5));
276 BOOST_CHECK_EQUAL(host_vector
[0], 10);
277 BOOST_CHECK_EQUAL(host_vector
[1], 11);
278 BOOST_CHECK_EQUAL(host_vector
[2], 12);
279 BOOST_CHECK_EQUAL(host_vector
[3], 13);
280 BOOST_CHECK_EQUAL(host_vector
[4], 14);
283 BOOST_AUTO_TEST_CASE(copy_to_stringstream
)
285 std::stringstream stream
;
287 int data
[] = { 2, 3, 4, 5, 6, 7, 8, 9 };
288 compute::vector
<int> vector(data
, data
+ 8, queue
);
293 std::ostream_iterator
<int>(stream
, " "),
296 BOOST_CHECK_EQUAL(stream
.str(), std::string("2 3 4 5 6 7 8 9 "));
299 BOOST_AUTO_TEST_CASE(check_copy_type
)
301 // copy from host to device and ensure clEnqueueWriteBuffer() is used
302 int data
[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
303 compute::vector
<int> a(8, context
);
304 compute::future
<void> future
=
305 compute::copy_async(data
, data
+ 8, a
.begin(), queue
);
307 future
.get_event().get_command_type() == CL_COMMAND_WRITE_BUFFER
310 CHECK_RANGE_EQUAL(int, 8, a
, (1, 2, 3, 4, 5, 6, 7, 8));
312 // copy on the device and ensure clEnqueueCopyBuffer() is used
313 compute::vector
<int> b(8, context
);
314 future
= compute::copy_async(a
.begin(), a
.end(), b
.begin(), queue
);
316 future
.get_event().get_command_type() == CL_COMMAND_COPY_BUFFER
319 CHECK_RANGE_EQUAL(int, 8, b
, (1, 2, 3, 4, 5, 6, 7, 8));
321 // copy between vectors of different types on the device and ensure
322 // that the copy kernel is used
323 compute::vector
<short> c(8, context
);
324 future
= compute::copy_async(a
.begin(), a
.end(), c
.begin(), queue
);
326 future
.get_event().get_command_type() == CL_COMMAND_NDRANGE_KERNEL
329 CHECK_RANGE_EQUAL(short, 8, c
, (1, 2, 3, 4, 5, 6, 7, 8));
331 // copy from device to host and ensure clEnqueueReadBuffer() is used
332 future
= compute::copy_async(b
.begin(), b
.end(), data
, queue
);
334 future
.get_event().get_command_type() == CL_COMMAND_READ_BUFFER
337 CHECK_HOST_RANGE_EQUAL(int, 8, data
, (1, 2, 3, 4, 5, 6, 7, 8));
340 #ifdef BOOST_COMPUTE_CL_VERSION_2_0
341 BOOST_AUTO_TEST_CASE(copy_svm_ptr
)
343 REQUIRES_OPENCL_VERSION(2, 0);
345 using boost::compute::int_
;
347 if(bug_in_svmmemcpy(device
)){
348 std::cerr
<< "skipping copy_svm_ptr test case" << std::endl
;
352 int_ data
[] = { 1, 3, 2, 4 };
354 compute::svm_ptr
<int_
> ptr
= compute::svm_alloc
<int_
>(context
, 4);
355 compute::copy(data
, data
+ 4, ptr
, queue
);
357 int_ output
[] = { 0, 0, 0, 0 };
358 compute::copy(ptr
, ptr
+ 4, output
, queue
);
359 CHECK_HOST_RANGE_EQUAL(int_
, 4, output
, (1, 3, 2, 4));
361 compute::svm_free(context
, ptr
);
364 BOOST_AUTO_TEST_CASE(copy_async_svm_ptr
)
366 REQUIRES_OPENCL_VERSION(2, 0);
368 using boost::compute::int_
;
370 if(bug_in_svmmemcpy(device
)){
371 std::cerr
<< "skipping copy_svm_ptr test case" << std::endl
;
375 int_ data
[] = { 1, 3, 2, 4 };
377 compute::svm_ptr
<int_
> ptr
= compute::svm_alloc
<int_
>(context
, 4);
378 boost::compute::future
<void> future
=
379 compute::copy_async(data
, data
+ 4, ptr
, queue
);
382 int_ output
[] = { 0, 0, 0, 0 };
384 compute::copy_async(ptr
, ptr
+ 4, output
, queue
);
386 CHECK_HOST_RANGE_EQUAL(int_
, 4, output
, (1, 3, 2, 4));
388 compute::svm_free(context
, ptr
);
390 #endif // BOOST_COMPUTE_CL_VERSION_2_0
392 BOOST_AUTO_TEST_CASE(copy_to_vector_bool
)
394 using compute::uchar_
;
396 compute::vector
<uchar_
> vec(2, context
);
399 bool data
[] = {true, false};
400 compute::copy(data
, data
+ 2, vec
.begin(), queue
);
401 BOOST_CHECK(static_cast<bool>(vec
[0]) == true);
402 BOOST_CHECK(static_cast<bool>(vec
[1]) == false);
405 std::vector
<bool> host_vec(vec
.size());
406 compute::copy(vec
.begin(), vec
.end(), host_vec
.begin(), queue
);
407 BOOST_CHECK(host_vec
[0] == true);
408 BOOST_CHECK(host_vec
[1] == false);
411 BOOST_AUTO_TEST_SUITE_END()