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_DEVICE_HPP
0012 #define BOOST_COMPUTE_ALGORITHM_DETAIL_COPY_TO_DEVICE_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 
0023 namespace boost {
0024 namespace compute {
0025 namespace detail {
0026 
0027 template<class HostIterator, class DeviceIterator>
0028 inline DeviceIterator copy_to_device(HostIterator first,
0029                                      HostIterator last,
0030                                      DeviceIterator result,
0031                                      command_queue &queue,
0032                                      const wait_list &events)
0033 {
0034     typedef typename
0035         std::iterator_traits<DeviceIterator>::value_type
0036         value_type;
0037     typedef typename
0038         std::iterator_traits<DeviceIterator>::difference_type
0039         difference_type;
0040 
0041     size_t count = iterator_range_size(first, last);
0042     if(count == 0){
0043         return result;
0044     }
0045 
0046     size_t offset = result.get_index();
0047 
0048     queue.enqueue_write_buffer(result.get_buffer(),
0049                                offset * sizeof(value_type),
0050                                count * sizeof(value_type),
0051                                ::boost::addressof(*first),
0052                                events);
0053 
0054     return result + static_cast<difference_type>(count);
0055 }
0056 
0057 template<class HostIterator, class DeviceIterator>
0058 inline DeviceIterator copy_to_device_map(HostIterator first,
0059                                          HostIterator last,
0060                                          DeviceIterator result,
0061                                          command_queue &queue,
0062                                          const wait_list &events)
0063 {
0064     typedef typename
0065         std::iterator_traits<DeviceIterator>::value_type
0066         value_type;
0067     typedef typename
0068         std::iterator_traits<DeviceIterator>::difference_type
0069         difference_type;
0070 
0071     size_t count = iterator_range_size(first, last);
0072     if(count == 0){
0073         return result;
0074     }
0075 
0076     size_t offset = result.get_index();
0077 
0078     // map result buffer to host
0079     value_type *pointer = static_cast<value_type*>(
0080         queue.enqueue_map_buffer(
0081             result.get_buffer(),
0082             CL_MAP_WRITE,
0083             offset * sizeof(value_type),
0084             count * sizeof(value_type),
0085             events
0086         )
0087     );
0088 
0089     // copy [first; last) to result buffer
0090     std::copy(first, last, pointer);
0091 
0092     // unmap result buffer
0093     boost::compute::event unmap_event = queue.enqueue_unmap_buffer(
0094         result.get_buffer(),
0095         static_cast<void*>(pointer)
0096     );
0097     unmap_event.wait();
0098 
0099     return result + static_cast<difference_type>(count);
0100 }
0101 
0102 template<class HostIterator, class DeviceIterator>
0103 inline future<DeviceIterator> copy_to_device_async(HostIterator first,
0104                                                    HostIterator last,
0105                                                    DeviceIterator result,
0106                                                    command_queue &queue,
0107                                                    const wait_list &events)
0108 {
0109     typedef typename
0110         std::iterator_traits<DeviceIterator>::value_type
0111         value_type;
0112     typedef typename
0113         std::iterator_traits<DeviceIterator>::difference_type
0114         difference_type;
0115 
0116     size_t count = iterator_range_size(first, last);
0117     if(count == 0){
0118         return future<DeviceIterator>();
0119     }
0120 
0121     size_t offset = result.get_index();
0122 
0123     event event_ =
0124         queue.enqueue_write_buffer_async(result.get_buffer(),
0125                                          offset * sizeof(value_type),
0126                                          count * sizeof(value_type),
0127                                          ::boost::addressof(*first),
0128                                          events);
0129 
0130     return make_future(result + static_cast<difference_type>(count), event_);
0131 }
0132 
0133 #ifdef BOOST_COMPUTE_CL_VERSION_2_0
0134 // copy_to_device() specialization for svm_ptr
0135 template<class HostIterator, class T>
0136 inline svm_ptr<T> copy_to_device(HostIterator first,
0137                                  HostIterator last,
0138                                  svm_ptr<T> result,
0139                                  command_queue &queue,
0140                                  const wait_list &events)
0141 {
0142     size_t count = iterator_range_size(first, last);
0143     if(count == 0){
0144         return result;
0145     }
0146 
0147     queue.enqueue_svm_memcpy(
0148         result.get(), ::boost::addressof(*first), count * sizeof(T), events
0149     );
0150 
0151     return result + count;
0152 }
0153 
0154 template<class HostIterator, class T>
0155 inline future<svm_ptr<T> > copy_to_device_async(HostIterator first,
0156                                                 HostIterator last,
0157                                                 svm_ptr<T> result,
0158                                                 command_queue &queue,
0159                                                 const wait_list &events)
0160 {
0161     size_t count = iterator_range_size(first, last);
0162     if(count == 0){
0163         return future<svm_ptr<T> >();
0164     }
0165 
0166     event event_ = queue.enqueue_svm_memcpy_async(
0167         result.get(), ::boost::addressof(*first), count * sizeof(T), events
0168     );
0169 
0170     return make_future(result + count, event_);
0171 }
0172 
0173 template<class HostIterator, class T>
0174 inline svm_ptr<T> copy_to_device_map(HostIterator first,
0175                                               HostIterator last,
0176                                               svm_ptr<T> result,
0177                                               command_queue &queue,
0178                                               const wait_list &events)
0179 {
0180     size_t count = iterator_range_size(first, last);
0181     if(count == 0){
0182         return result;
0183     }
0184 
0185     // map
0186     queue.enqueue_svm_map(
0187         result.get(), count * sizeof(T), CL_MAP_WRITE, events
0188     );
0189 
0190     // copy [first; last) to result buffer
0191     std::copy(first, last, static_cast<T*>(result.get()));
0192 
0193     // unmap result
0194     queue.enqueue_svm_unmap(result.get()).wait();
0195 
0196     return result + count;
0197 }
0198 #endif // BOOST_COMPUTE_CL_VERSION_2_0
0199 
0200 } // end detail namespace
0201 } // end compute namespace
0202 } // end boost namespace
0203 
0204 #endif // BOOST_COMPUTE_ALGORITHM_DETAIL_COPY_TO_DEVICE_HPP