copy_to_device.hpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. //---------------------------------------------------------------------------//
  2. // Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@gmail.com>
  3. //
  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
  7. //
  8. // See http://boostorg.github.com/compute for more information.
  9. //---------------------------------------------------------------------------//
  10. #ifndef BOOST_COMPUTE_ALGORITHM_DETAIL_COPY_TO_DEVICE_HPP
  11. #define BOOST_COMPUTE_ALGORITHM_DETAIL_COPY_TO_DEVICE_HPP
  12. #include <iterator>
  13. #include <boost/utility/addressof.hpp>
  14. #include <boost/compute/command_queue.hpp>
  15. #include <boost/compute/async/future.hpp>
  16. #include <boost/compute/iterator/buffer_iterator.hpp>
  17. #include <boost/compute/memory/svm_ptr.hpp>
  18. namespace boost {
  19. namespace compute {
  20. namespace detail {
  21. template<class HostIterator, class DeviceIterator>
  22. inline DeviceIterator copy_to_device(HostIterator first,
  23. HostIterator last,
  24. DeviceIterator result,
  25. command_queue &queue,
  26. const wait_list &events)
  27. {
  28. typedef typename
  29. std::iterator_traits<DeviceIterator>::value_type
  30. value_type;
  31. typedef typename
  32. std::iterator_traits<DeviceIterator>::difference_type
  33. difference_type;
  34. size_t count = iterator_range_size(first, last);
  35. if(count == 0){
  36. return result;
  37. }
  38. size_t offset = result.get_index();
  39. queue.enqueue_write_buffer(result.get_buffer(),
  40. offset * sizeof(value_type),
  41. count * sizeof(value_type),
  42. ::boost::addressof(*first),
  43. events);
  44. return result + static_cast<difference_type>(count);
  45. }
  46. template<class HostIterator, class DeviceIterator>
  47. inline DeviceIterator copy_to_device_map(HostIterator first,
  48. HostIterator last,
  49. DeviceIterator result,
  50. command_queue &queue,
  51. const wait_list &events)
  52. {
  53. typedef typename
  54. std::iterator_traits<DeviceIterator>::value_type
  55. value_type;
  56. typedef typename
  57. std::iterator_traits<DeviceIterator>::difference_type
  58. difference_type;
  59. size_t count = iterator_range_size(first, last);
  60. if(count == 0){
  61. return result;
  62. }
  63. size_t offset = result.get_index();
  64. // map result buffer to host
  65. value_type *pointer = static_cast<value_type*>(
  66. queue.enqueue_map_buffer(
  67. result.get_buffer(),
  68. CL_MAP_WRITE,
  69. offset * sizeof(value_type),
  70. count * sizeof(value_type),
  71. events
  72. )
  73. );
  74. // copy [first; last) to result buffer
  75. std::copy(first, last, pointer);
  76. // unmap result buffer
  77. boost::compute::event unmap_event = queue.enqueue_unmap_buffer(
  78. result.get_buffer(),
  79. static_cast<void*>(pointer)
  80. );
  81. unmap_event.wait();
  82. return result + static_cast<difference_type>(count);
  83. }
  84. template<class HostIterator, class DeviceIterator>
  85. inline future<DeviceIterator> copy_to_device_async(HostIterator first,
  86. HostIterator last,
  87. DeviceIterator result,
  88. command_queue &queue,
  89. const wait_list &events)
  90. {
  91. typedef typename
  92. std::iterator_traits<DeviceIterator>::value_type
  93. value_type;
  94. typedef typename
  95. std::iterator_traits<DeviceIterator>::difference_type
  96. difference_type;
  97. size_t count = iterator_range_size(first, last);
  98. if(count == 0){
  99. return future<DeviceIterator>();
  100. }
  101. size_t offset = result.get_index();
  102. event event_ =
  103. queue.enqueue_write_buffer_async(result.get_buffer(),
  104. offset * sizeof(value_type),
  105. count * sizeof(value_type),
  106. ::boost::addressof(*first),
  107. events);
  108. return make_future(result + static_cast<difference_type>(count), event_);
  109. }
  110. #ifdef BOOST_COMPUTE_CL_VERSION_2_0
  111. // copy_to_device() specialization for svm_ptr
  112. template<class HostIterator, class T>
  113. inline svm_ptr<T> copy_to_device(HostIterator first,
  114. HostIterator last,
  115. svm_ptr<T> result,
  116. command_queue &queue,
  117. const wait_list &events)
  118. {
  119. size_t count = iterator_range_size(first, last);
  120. if(count == 0){
  121. return result;
  122. }
  123. queue.enqueue_svm_memcpy(
  124. result.get(), ::boost::addressof(*first), count * sizeof(T), events
  125. );
  126. return result + count;
  127. }
  128. template<class HostIterator, class T>
  129. inline future<svm_ptr<T> > copy_to_device_async(HostIterator first,
  130. HostIterator last,
  131. svm_ptr<T> result,
  132. command_queue &queue,
  133. const wait_list &events)
  134. {
  135. size_t count = iterator_range_size(first, last);
  136. if(count == 0){
  137. return future<svm_ptr<T> >();
  138. }
  139. event event_ = queue.enqueue_svm_memcpy_async(
  140. result.get(), ::boost::addressof(*first), count * sizeof(T), events
  141. );
  142. return make_future(result + count, event_);
  143. }
  144. template<class HostIterator, class T>
  145. inline svm_ptr<T> copy_to_device_map(HostIterator first,
  146. HostIterator last,
  147. svm_ptr<T> result,
  148. command_queue &queue,
  149. const wait_list &events)
  150. {
  151. size_t count = iterator_range_size(first, last);
  152. if(count == 0){
  153. return result;
  154. }
  155. // map
  156. queue.enqueue_svm_map(
  157. result.get(), count * sizeof(T), CL_MAP_WRITE, events
  158. );
  159. // copy [first; last) to result buffer
  160. std::copy(first, last, static_cast<T*>(result.get()));
  161. // unmap result
  162. queue.enqueue_svm_unmap(result.get()).wait();
  163. return result + count;
  164. }
  165. #endif // BOOST_COMPUTE_CL_VERSION_2_0
  166. } // end detail namespace
  167. } // end compute namespace
  168. } // end boost namespace
  169. #endif // BOOST_COMPUTE_ALGORITHM_DETAIL_COPY_TO_DEVICE_HPP