Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:29:53

0001 //---------------------------------------------------------------------------//
0002 // Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@gmail.com>
0003 //
0004 // Distributed under the Boost Software License, Version 1.0
0005 // See accompanying file LICENSE_1_0.txt or copy at
0006 // http://www.boost.org/LICENSE_1_0.txt
0007 //
0008 // See http://boostorg.github.com/compute for more information.
0009 //---------------------------------------------------------------------------//
0010 
0011 #ifndef BOOST_COMPUTE_ALGORITHM_DETAIL_COPY_TO_HOST_HPP
0012 #define BOOST_COMPUTE_ALGORITHM_DETAIL_COPY_TO_HOST_HPP
0013 
0014 #include <iterator>
0015 
0016 #include <boost/utility/addressof.hpp>
0017 
0018 #include <boost/compute/command_queue.hpp>
0019 #include <boost/compute/async/future.hpp>
0020 #include <boost/compute/iterator/buffer_iterator.hpp>
0021 #include <boost/compute/memory/svm_ptr.hpp>
0022 #include <boost/compute/detail/iterator_plus_distance.hpp>
0023 
0024 namespace boost {
0025 namespace compute {
0026 namespace detail {
0027 
0028 template<class DeviceIterator, class HostIterator>
0029 inline HostIterator copy_to_host(DeviceIterator first,
0030                                  DeviceIterator last,
0031                                  HostIterator result,
0032                                  command_queue &queue,
0033                                  const wait_list &events)
0034 {
0035     typedef typename
0036         std::iterator_traits<DeviceIterator>::value_type
0037         value_type;
0038 
0039     size_t count = iterator_range_size(first, last);
0040     if(count == 0){
0041         return result;
0042     }
0043 
0044     const buffer &buffer = first.get_buffer();
0045     size_t offset = first.get_index();
0046 
0047     queue.enqueue_read_buffer(buffer,
0048                               offset * sizeof(value_type),
0049                               count * sizeof(value_type),
0050                               ::boost::addressof(*result),
0051                               events);
0052 
0053     return iterator_plus_distance(result, count);
0054 }
0055 
0056 template<class DeviceIterator, class HostIterator>
0057 inline HostIterator copy_to_host_map(DeviceIterator first,
0058                                      DeviceIterator last,
0059                                      HostIterator result,
0060                                      command_queue &queue,
0061                                      const wait_list &events)
0062 {
0063     typedef typename
0064         std::iterator_traits<DeviceIterator>::value_type
0065         value_type;
0066     typedef typename
0067         std::iterator_traits<DeviceIterator>::difference_type
0068         difference_type;
0069 
0070     size_t count = iterator_range_size(first, last);
0071     if(count == 0){
0072         return result;
0073     }
0074 
0075     size_t offset = first.get_index();
0076 
0077     // map [first; last) buffer to host
0078     value_type *pointer = static_cast<value_type*>(
0079         queue.enqueue_map_buffer(
0080             first.get_buffer(),
0081             CL_MAP_READ,
0082             offset * sizeof(value_type),
0083             count * sizeof(value_type),
0084             events
0085         )
0086     );
0087 
0088     // copy [first; last) to result buffer
0089     std::copy(
0090         pointer,
0091         pointer + static_cast<difference_type>(count),
0092         result
0093     );
0094 
0095     // unmap [first; last)
0096     boost::compute::event unmap_event = queue.enqueue_unmap_buffer(
0097         first.get_buffer(),
0098         static_cast<void*>(pointer)
0099     );
0100     unmap_event.wait();
0101 
0102     return iterator_plus_distance(result, count);
0103 }
0104 
0105 template<class DeviceIterator, class HostIterator>
0106 inline future<HostIterator> copy_to_host_async(DeviceIterator first,
0107                                                DeviceIterator last,
0108                                                HostIterator result,
0109                                                command_queue &queue,
0110                                                const wait_list &events)
0111 {
0112     typedef typename
0113         std::iterator_traits<DeviceIterator>::value_type
0114         value_type;
0115 
0116     size_t count = iterator_range_size(first, last);
0117     if(count == 0){
0118         return future<HostIterator>();
0119     }
0120 
0121     const buffer &buffer = first.get_buffer();
0122     size_t offset = first.get_index();
0123 
0124     event event_ =
0125         queue.enqueue_read_buffer_async(buffer,
0126                                         offset * sizeof(value_type),
0127                                         count * sizeof(value_type),
0128                                         ::boost::addressof(*result),
0129                                         events);
0130 
0131     return make_future(iterator_plus_distance(result, count), event_);
0132 }
0133 
0134 #ifdef BOOST_COMPUTE_CL_VERSION_2_0
0135 // copy_to_host() specialization for svm_ptr
0136 template<class T, class HostIterator>
0137 inline HostIterator copy_to_host(svm_ptr<T> first,
0138                                  svm_ptr<T> last,
0139                                  HostIterator result,
0140                                  command_queue &queue,
0141                                  const wait_list &events)
0142 {
0143     size_t count = iterator_range_size(first, last);
0144     if(count == 0){
0145         return result;
0146     }
0147 
0148     queue.enqueue_svm_memcpy(
0149         ::boost::addressof(*result), first.get(), count * sizeof(T), events
0150     );
0151 
0152     return result + count;
0153 }
0154 
0155 template<class T, class HostIterator>
0156 inline future<HostIterator> copy_to_host_async(svm_ptr<T> first,
0157                                                svm_ptr<T> last,
0158                                                HostIterator result,
0159                                                command_queue &queue,
0160                                                const wait_list &events)
0161 {
0162     size_t count = iterator_range_size(first, last);
0163     if(count == 0){
0164         return future<HostIterator>();
0165     }
0166 
0167     event event_ = queue.enqueue_svm_memcpy_async(
0168         ::boost::addressof(*result), first.get(), count * sizeof(T), events
0169     );
0170 
0171     return make_future(iterator_plus_distance(result, count), event_);
0172 }
0173 
0174 template<class T, class HostIterator>
0175 inline HostIterator copy_to_host_map(svm_ptr<T> first,
0176                                      svm_ptr<T> last,
0177                                      HostIterator result,
0178                                      command_queue &queue,
0179                                      const wait_list &events)
0180 {
0181     size_t count = iterator_range_size(first, last);
0182     if(count == 0){
0183         return result;
0184     }
0185 
0186     // map
0187     queue.enqueue_svm_map(first.get(), count * sizeof(T), CL_MAP_READ, events);
0188 
0189     // copy [first; last) to result
0190     std::copy(
0191         static_cast<T*>(first.get()),
0192         static_cast<T*>(last.get()),
0193         result
0194     );
0195 
0196     // unmap [first; last)
0197     queue.enqueue_svm_unmap(first.get()).wait();
0198 
0199     return iterator_plus_distance(result, count);
0200 }
0201 #endif // BOOST_COMPUTE_CL_VERSION_2_0
0202 
0203 } // end detail namespace
0204 } // end compute namespace
0205 } // end boost namespace
0206 
0207 #endif // BOOST_COMPUTE_ALGORITHM_DETAIL_COPY_TO_HOST_HPP