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