]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/compute/include/boost/compute/algorithm/fill.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / compute / include / boost / compute / algorithm / fill.hpp
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
11 #ifndef BOOST_COMPUTE_ALGORITHM_FILL_HPP
12 #define BOOST_COMPUTE_ALGORITHM_FILL_HPP
13
14 #include <iterator>
15
16 #include <boost/mpl/int.hpp>
17 #include <boost/mpl/vector.hpp>
18 #include <boost/mpl/contains.hpp>
19 #include <boost/utility/enable_if.hpp>
20
21 #include <boost/compute/cl.hpp>
22 #include <boost/compute/system.hpp>
23 #include <boost/compute/command_queue.hpp>
24 #include <boost/compute/algorithm/copy.hpp>
25 #include <boost/compute/async/future.hpp>
26 #include <boost/compute/iterator/constant_iterator.hpp>
27 #include <boost/compute/iterator/discard_iterator.hpp>
28 #include <boost/compute/detail/is_buffer_iterator.hpp>
29 #include <boost/compute/detail/iterator_range_size.hpp>
30
31 namespace boost {
32 namespace compute {
33 namespace detail {
34
35 namespace mpl = boost::mpl;
36
37 // fills the range [first, first + count) with value using copy()
38 template<class BufferIterator, class T>
39 inline void fill_with_copy(BufferIterator first,
40 size_t count,
41 const T &value,
42 command_queue &queue)
43 {
44 ::boost::compute::copy(
45 ::boost::compute::make_constant_iterator(value, 0),
46 ::boost::compute::make_constant_iterator(value, count),
47 first,
48 queue
49 );
50 }
51
52 // fills the range [first, first + count) with value using copy_async()
53 template<class BufferIterator, class T>
54 inline future<void> fill_async_with_copy(BufferIterator first,
55 size_t count,
56 const T &value,
57 command_queue &queue)
58 {
59 return ::boost::compute::copy_async(
60 ::boost::compute::make_constant_iterator(value, 0),
61 ::boost::compute::make_constant_iterator(value, count),
62 first,
63 queue
64 );
65 }
66
67 #if defined(CL_VERSION_1_2)
68
69 // meta-function returing true if Iterator points to a range of values
70 // that can be filled using clEnqueueFillBuffer(). to meet this criteria
71 // it must have a buffer accessible through iter.get_buffer() and the
72 // size of its value_type must by in {1, 2, 4, 8, 16, 32, 64, 128}.
73 template<class Iterator>
74 struct is_valid_fill_buffer_iterator :
75 public mpl::and_<
76 is_buffer_iterator<Iterator>,
77 mpl::contains<
78 mpl::vector<
79 mpl::int_<1>,
80 mpl::int_<2>,
81 mpl::int_<4>,
82 mpl::int_<8>,
83 mpl::int_<16>,
84 mpl::int_<32>,
85 mpl::int_<64>,
86 mpl::int_<128>
87 >,
88 mpl::int_<
89 sizeof(typename std::iterator_traits<Iterator>::value_type)
90 >
91 >
92 >::type { };
93
94 template<>
95 struct is_valid_fill_buffer_iterator<discard_iterator> : public boost::false_type {};
96
97 // specialization which uses clEnqueueFillBuffer for buffer iterators
98 template<class BufferIterator, class T>
99 inline void
100 dispatch_fill(BufferIterator first,
101 size_t count,
102 const T &value,
103 command_queue &queue,
104 typename boost::enable_if<
105 is_valid_fill_buffer_iterator<BufferIterator>
106 >::type* = 0)
107 {
108 typedef typename std::iterator_traits<BufferIterator>::value_type value_type;
109
110 if(count == 0){
111 // nothing to do
112 return;
113 }
114
115 // check if the device supports OpenCL 1.2 (required for enqueue_fill_buffer)
116 if(!queue.check_device_version(1, 2)){
117 return fill_with_copy(first, count, value, queue);
118 }
119
120 value_type pattern = static_cast<value_type>(value);
121 size_t offset = static_cast<size_t>(first.get_index());
122
123 if(count == 1){
124 // use clEnqueueWriteBuffer() directly when writing a single value
125 // to the device buffer. this is potentially more efficient and also
126 // works around a bug in the intel opencl driver.
127 queue.enqueue_write_buffer(
128 first.get_buffer(),
129 offset * sizeof(value_type),
130 sizeof(value_type),
131 &pattern
132 );
133 }
134 else {
135 queue.enqueue_fill_buffer(
136 first.get_buffer(),
137 &pattern,
138 sizeof(value_type),
139 offset * sizeof(value_type),
140 count * sizeof(value_type)
141 );
142 }
143 }
144
145 template<class BufferIterator, class T>
146 inline future<void>
147 dispatch_fill_async(BufferIterator first,
148 size_t count,
149 const T &value,
150 command_queue &queue,
151 typename boost::enable_if<
152 is_valid_fill_buffer_iterator<BufferIterator>
153 >::type* = 0)
154 {
155 typedef typename std::iterator_traits<BufferIterator>::value_type value_type;
156
157 // check if the device supports OpenCL 1.2 (required for enqueue_fill_buffer)
158 if(!queue.check_device_version(1, 2)){
159 return fill_async_with_copy(first, count, value, queue);
160 }
161
162 value_type pattern = static_cast<value_type>(value);
163 size_t offset = static_cast<size_t>(first.get_index());
164
165 event event_ =
166 queue.enqueue_fill_buffer(first.get_buffer(),
167 &pattern,
168 sizeof(value_type),
169 offset * sizeof(value_type),
170 count * sizeof(value_type));
171
172 return future<void>(event_);
173 }
174
175 #ifdef CL_VERSION_2_0
176 // specializations for svm_ptr<T>
177 template<class T>
178 inline void dispatch_fill(svm_ptr<T> first,
179 size_t count,
180 const T &value,
181 command_queue &queue)
182 {
183 if(count == 0){
184 return;
185 }
186
187 queue.enqueue_svm_fill(
188 first.get(), &value, sizeof(T), count * sizeof(T)
189 );
190 }
191
192 template<class T>
193 inline future<void> dispatch_fill_async(svm_ptr<T> first,
194 size_t count,
195 const T &value,
196 command_queue &queue)
197 {
198 if(count == 0){
199 return future<void>();
200 }
201
202 event event_ = queue.enqueue_svm_fill(
203 first.get(), &value, sizeof(T), count * sizeof(T)
204 );
205
206 return future<void>(event_);
207 }
208 #endif // CL_VERSION_2_0
209
210 // default implementations
211 template<class BufferIterator, class T>
212 inline void
213 dispatch_fill(BufferIterator first,
214 size_t count,
215 const T &value,
216 command_queue &queue,
217 typename boost::disable_if<
218 is_valid_fill_buffer_iterator<BufferIterator>
219 >::type* = 0)
220 {
221 fill_with_copy(first, count, value, queue);
222 }
223
224 template<class BufferIterator, class T>
225 inline future<void>
226 dispatch_fill_async(BufferIterator first,
227 size_t count,
228 const T &value,
229 command_queue &queue,
230 typename boost::disable_if<
231 is_valid_fill_buffer_iterator<BufferIterator>
232 >::type* = 0)
233 {
234 return fill_async_with_copy(first, count, value, queue);
235 }
236 #else
237 template<class BufferIterator, class T>
238 inline void dispatch_fill(BufferIterator first,
239 size_t count,
240 const T &value,
241 command_queue &queue)
242 {
243 fill_with_copy(first, count, value, queue);
244 }
245
246 template<class BufferIterator, class T>
247 inline future<void> dispatch_fill_async(BufferIterator first,
248 size_t count,
249 const T &value,
250 command_queue &queue)
251 {
252 return fill_async_with_copy(first, count, value, queue);
253 }
254 #endif // !defined(CL_VERSION_1_2)
255
256 } // end detail namespace
257
258 /// Fills the range [\p first, \p last) with \p value.
259 ///
260 /// \param first first element in the range to fill
261 /// \param last last element in the range to fill
262 /// \param value value to copy to each element
263 /// \param queue command queue to perform the operation
264 ///
265 /// For example, to fill a vector on the device with sevens:
266 /// \code
267 /// // vector on the device
268 /// boost::compute::vector<int> vec(10, context);
269 ///
270 /// // fill vector with sevens
271 /// boost::compute::fill(vec.begin(), vec.end(), 7, queue);
272 /// \endcode
273 ///
274 /// \see boost::compute::fill_n()
275 template<class BufferIterator, class T>
276 inline void fill(BufferIterator first,
277 BufferIterator last,
278 const T &value,
279 command_queue &queue = system::default_queue())
280 {
281 size_t count = detail::iterator_range_size(first, last);
282 if(count == 0){
283 return;
284 }
285
286 detail::dispatch_fill(first, count, value, queue);
287 }
288
289 template<class BufferIterator, class T>
290 inline future<void> fill_async(BufferIterator first,
291 BufferIterator last,
292 const T &value,
293 command_queue &queue = system::default_queue())
294 {
295 size_t count = detail::iterator_range_size(first, last);
296 if(count == 0){
297 return future<void>();
298 }
299
300 return detail::dispatch_fill_async(first, count, value, queue);
301 }
302
303 } // end compute namespace
304 } // end boost namespace
305
306 #endif // BOOST_COMPUTE_ALGORITHM_FILL_HPP