Bolt  1.3
C++ template library with support for OpenCL
permutation_iterator.h
1 /***************************************************************************
2 * © 2012,2014 Advanced Micro Devices, Inc. All rights reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 
16 ***************************************************************************/
17 
18 // (C) Copyright Toon Knapen 2001.
19 // (C) Copyright David Abrahams 2003.
20 // (C) Copyright Roland Richter 2003.
21 // Distributed under the Boost Software License, Version 1.0. (See
22 // accompanying file LICENSE_1_0.txt or copy at
23 // http://www.boost.org/LICENSE_1_0.txt)
24 
25 #ifndef BOLT_PERMUTATION_ITERATOR_H
26 #define BOLT_PERMUTATION_ITERATOR_H
27 
28 //#include <iterator>
29 #include <type_traits>
30 #include <bolt/cl/bolt.h>
31 #include <bolt/cl/device_vector.h>
32 #include <bolt/cl/iterator/iterator_adaptor.h>
33 #include <bolt/cl/iterator/iterator_facade.h>
37 
38 
39 namespace bolt {
40 namespace cl {
42  : public fancy_iterator_tag
43  { };
44 
45 
96 template< class ElementIterator
97  , class IndexIterator>
99  : public iterator_adaptor<
100  permutation_iterator<ElementIterator, IndexIterator>
101  , IndexIterator, typename bolt::cl::iterator_traits<ElementIterator>::value_type
102  , use_default, typename bolt::cl::iterator_traits<ElementIterator>::reference
103  , std::ptrdiff_t>
104 {
105  typedef iterator_adaptor<
107  , IndexIterator, typename bolt::cl::iterator_traits<ElementIterator>::value_type
108  , use_default, typename bolt::cl::iterator_traits<ElementIterator>::reference
109  , std::ptrdiff_t> super_t;
110 
111  friend class iterator_core_access;
112 
113 public:
114  typedef std::ptrdiff_t difference_type;
115  typedef typename bolt::cl::iterator_traits<ElementIterator>::value_type value_type;
116  typedef typename bolt::cl::iterator_traits<ElementIterator>::value_type * pointer;
117  typedef typename bolt::cl::iterator_traits<IndexIterator>::value_type index_type;
118  typedef permutation_iterator_tag iterator_category;
119 
120  permutation_iterator() : m_elt_iter() {}
121 
122  explicit permutation_iterator(ElementIterator x, IndexIterator y)
123  : super_t(y), m_elt_iter(x) {}
124 
125  template<class OtherElementIterator, class OtherIndexIterator>
130  )
131  : super_t(r.base()), m_elt_iter(r.m_elt_iter)
132  {}
133 
134  index_type* getIndex_pointer ()
135  {
136  return &(*(this->base_reference()));
137  }
138 
139  value_type* getElement_pointer ()
140  {
141  return &(*(this->m_elt_iter));
142  }
143 
144  struct Payload
145  {
146  int m_Index;
147  int m_ElementPtr[ 3 ]; //Holds pointer to Element Iterator
148  int m_IndexPtr[ 3 ]; //Holds pointer to Index Iterator
149  };
150 
151  const Payload gpuPayload( ) const
152  {
153  Payload payload = { 0/*m_Index*/, { 0, 0, 0 }, { 0, 0, 0 } };
154  return payload;
155  }
156 
157  const difference_type gpuPayloadSize( ) const
158  {
159  cl_int l_Error = CL_SUCCESS;
160  //::cl::Device which_device;
161  //l_Error = m_it.getContainer().m_commQueue.getInfo(CL_QUEUE_DEVICE,&which_device );
162  //TODO - fix the device bits
163  cl_uint deviceBits = 32;// = which_device.getInfo< CL_DEVICE_ADDRESS_BITS >( );
164  // Size of index and pointer
165  difference_type payloadSize = sizeof( int ) + 2*( deviceBits >> 3 );
166 
167  // 64bit devices need to add padding for 8 byte aligned pointer
168  if( deviceBits == 64 )
169  payloadSize += 8;
170 
171  return payloadSize;
172  }
173 
174  int setKernelBuffers(int arg_num, ::cl::Kernel &kernel) const
175  {
176  /*First set the element Iterator*/
177  arg_num = m_elt_iter.setKernelBuffers(arg_num, kernel);
178  /*Next set the Argument Iterator*/
179  arg_num = this->base().setKernelBuffers(arg_num, kernel);
180  return arg_num;
181  }
182 
183 
184 private:
185  typename super_t::reference dereference() const
186  { return *(m_elt_iter + *this->base()); }
187 
188 
189 public:
190  ElementIterator m_elt_iter;
191 };
192 
193 
194 template <class ElementIterator, class IndexIterator>
195 permutation_iterator<ElementIterator, IndexIterator>
196 make_permutation_iterator( ElementIterator e, IndexIterator i )
197 {
198  return permutation_iterator<ElementIterator, IndexIterator>( e, i );
199 }
200 
201 
202  // This string represents the device side definition of the Transform Iterator template
203  static std::string devicePermutationIteratorTemplate =
204 
205  bolt::cl::deviceVectorIteratorTemplate +
206  bolt::cl::deviceConstantIterator +
207  bolt::cl::deviceCountingIterator +
208  std::string("#if !defined(BOLT_CL_PERMUTATION_ITERATOR) \n#define BOLT_CL_PERMUTATION_ITERATOR \n") +
209  STRINGIFY_CODE(
210  namespace bolt { namespace cl { \n
211  template< typename IndexIterator, typename ElementIterator > \n
212  class permutation_iterator \n
213  { \n
214  public: \n
215  typedef int iterator_category; \n
216  typedef typename ElementIterator::value_type value_type; \n
217  typedef typename ElementIterator::value_type base_type; \n
218  typedef typename IndexIterator::value_type index_type; \n
219  typedef int difference_type; \n
220  typedef int size_type; \n
221  typedef value_type* pointer; \n
222  typedef value_type& reference; \n
223 
224  permutation_iterator( value_type init ): m_StartIndex( init ), m_Ptr( 0 ) \n
225  {} \n
226 
227  void init( global value_type* element_ptr, global index_type* index_ptr )\n
228  { \n
229  m_ElementPtr = element_ptr; \n
230  m_IndexPtr = index_ptr; \n
231  } \n
232 
233  value_type operator[]( size_type threadID ) const \n
234  { \n
235  return m_ElementPtr[ m_IndexPtr[ m_StartIndex + threadID ] ]; \n
236  } \n
237 
238  value_type operator*( ) const \n
239  { \n
240  return m_ElementPtr[m_IndexPtr[ m_StartIndex + threadID ] ]; \n
241  } \n
242 
243  size_type m_StartIndex; \n
244  global value_type* m_ElementPtr; \n
245  global index_type* m_IndexPtr; \n
246  }; \n
247  } } \n
248  )
249  + std::string("#endif \n");
250 
251 } // End of namespace cl
252 } // End of namespace bolt
253 #endif