Kokkos Core Kernels Package  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
Kokkos_ScratchSpace.hpp
1 /*
2 //@HEADER
3 // ************************************************************************
4 //
5 // Kokkos v. 2.0
6 // Copyright (2014) Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact Christian R. Trott (crtrott@sandia.gov)
39 //
40 // ************************************************************************
41 //@HEADER
42 */
43 
44 #ifndef KOKKOS_SCRATCHSPACE_HPP
45 #define KOKKOS_SCRATCHSPACE_HPP
46 
47 #include <cstdio>
48 #include <Kokkos_Core_fwd.hpp>
49 #include <Kokkos_Concepts.hpp>
50 
51 /*--------------------------------------------------------------------------*/
52 
53 namespace Kokkos {
54 
58 template< class ExecSpace >
60  static_assert (is_execution_space<ExecSpace>::value,"Instantiating ScratchMemorySpace on non-execution-space type.");
61 public:
62 
63  // Alignment of memory chunks returned by 'get'
64  // must be a power of two
65  enum { ALIGN = 8 };
66 
67 private:
68 
69  mutable char * m_iter_L0 ;
70  char * m_end_L0 ;
71  mutable char * m_iter_L1 ;
72  char * m_end_L1 ;
73 
74 
75  mutable int m_multiplier;
76  mutable int m_offset;
77  mutable int m_default_level;
78 
80  ScratchMemorySpace & operator = ( const ScratchMemorySpace & );
81 
82  enum { MASK = ALIGN - 1 }; // Alignment used by View::shmem_size
83 
84 public:
85 
88  typedef ExecSpace execution_space ;
90  typedef Kokkos::Device<execution_space,memory_space> device_type;
91 
92  typedef typename ExecSpace::array_layout array_layout ;
93  typedef typename ExecSpace::size_type size_type ;
94 
95  template< typename IntType >
96  KOKKOS_INLINE_FUNCTION static
97  IntType align( const IntType & size )
98  { return ( size + MASK ) & ~MASK ; }
99 
100  template< typename IntType >
101  KOKKOS_INLINE_FUNCTION
102  void* get_shmem (const IntType& size, int level = -1) const {
103  if(level == -1)
104  level = m_default_level;
105  if(level == 0) {
106  void* tmp = m_iter_L0 + m_offset * align (size);
107  if (m_end_L0 < (m_iter_L0 += align (size) * m_multiplier)) {
108  m_iter_L0 -= align (size) * m_multiplier; // put it back like it was
109  #ifdef KOKKOS_DEBUG
110  // mfh 23 Jun 2015: printf call consumes 25 registers
111  // in a CUDA build, so only print in debug mode. The
112  // function still returns NULL if not enough memory.
113  printf ("ScratchMemorySpace<...>::get_shmem: Failed to allocate "
114  "%ld byte(s); remaining capacity is %ld byte(s)\n", long(size),
115  long(m_end_L0-m_iter_L0));
116  #endif // KOKKOS_DEBUG
117  tmp = 0;
118  }
119  return tmp;
120  } else {
121  void* tmp = m_iter_L1 + m_offset * align (size);
122  if (m_end_L1 < (m_iter_L1 += align (size) * m_multiplier)) {
123  m_iter_L1 -= align (size) * m_multiplier; // put it back like it was
124  #ifdef KOKKOS_DEBUG
125  // mfh 23 Jun 2015: printf call consumes 25 registers
126  // in a CUDA build, so only print in debug mode. The
127  // function still returns NULL if not enough memory.
128  printf ("ScratchMemorySpace<...>::get_shmem: Failed to allocate "
129  "%ld byte(s); remaining capacity is %ld byte(s)\n", long(size),
130  long(m_end_L1-m_iter_L1));
131  #endif // KOKKOS_DEBUG
132  tmp = 0;
133  }
134  return tmp;
135 
136  }
137  }
138 
139 
140  KOKKOS_INLINE_FUNCTION
141  void* get_shmem_aligned (const ptrdiff_t size, const ptrdiff_t alignment, int level = -1) const {
142  if(level == -1)
143  level = m_default_level;
144  if(level == 0) {
145 
146  char* previous = m_iter_L0;
147  const ptrdiff_t missalign = size_t(m_iter_L0)%alignment;
148  if(missalign) m_iter_L0 += alignment-missalign;
149 
150  void* tmp = m_iter_L0 + m_offset * size;
151  if (m_end_L0 < (m_iter_L0 += size * m_multiplier)) {
152  m_iter_L0 = previous; // put it back like it was
153  #ifdef KOKKOS_DEBUG
154  // mfh 23 Jun 2015: printf call consumes 25 registers
155  // in a CUDA build, so only print in debug mode. The
156  // function still returns NULL if not enough memory.
157  printf ("ScratchMemorySpace<...>::get_shmem: Failed to allocate "
158  "%ld byte(s); remaining capacity is %ld byte(s)\n", long(size),
159  long(m_end_L0-m_iter_L0));
160  #endif // KOKKOS_DEBUG
161  tmp = 0;
162  }
163  return tmp;
164  } else {
165 
166  char* previous = m_iter_L1;
167  const ptrdiff_t missalign = size_t(m_iter_L1)%alignment;
168  if(missalign) m_iter_L1 += alignment-missalign;
169 
170  void* tmp = m_iter_L1 + m_offset * size;
171  if (m_end_L1 < (m_iter_L1 += size * m_multiplier)) {
172  m_iter_L1 = previous; // put it back like it was
173  #ifdef KOKKOS_DEBUG
174  // mfh 23 Jun 2015: printf call consumes 25 registers
175  // in a CUDA build, so only print in debug mode. The
176  // function still returns NULL if not enough memory.
177  printf ("ScratchMemorySpace<...>::get_shmem: Failed to allocate "
178  "%ld byte(s); remaining capacity is %ld byte(s)\n", long(size),
179  long(m_end_L1-m_iter_L1));
180  #endif // KOKKOS_DEBUG
181  tmp = 0;
182  }
183  return tmp;
184 
185  }
186  }
187 
188  template< typename IntType >
189  KOKKOS_INLINE_FUNCTION
190  ScratchMemorySpace( void * ptr_L0 , const IntType & size_L0 , void * ptr_L1 = NULL , const IntType & size_L1 = 0)
191  : m_iter_L0( (char *) ptr_L0 )
192  , m_end_L0( m_iter_L0 + size_L0 )
193  , m_iter_L1( (char *) ptr_L1 )
194  , m_end_L1( m_iter_L1 + size_L1 )
195  , m_multiplier( 1 )
196  , m_offset( 0 )
197  , m_default_level( 0 )
198  {}
199 
200  KOKKOS_INLINE_FUNCTION
201  const ScratchMemorySpace& set_team_thread_mode(const int& level, const int& multiplier, const int& offset) const {
202  m_default_level = level;
203  m_multiplier = multiplier;
204  m_offset = offset;
205  return *this;
206  }
207 };
208 
209 } // namespace Kokkos
210 
211 #endif /* #ifndef KOKKOS_SCRATCHSPACE_HPP */
212 
Scratch memory space associated with an execution space.
ScratchMemorySpace memory_space
Tag this class as a memory space.
Kokkos::Device< execution_space, memory_space > device_type
This execution space preferred device_type.