copy_to_host.hpp 6.5 KB

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