LvArray
bufferManipulation.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2021, Lawrence Livermore National Security, LLC and LvArray contributors.
3  * All rights reserved.
4  * See the LICENSE file for details.
5  * SPDX-License-Identifier: (BSD-3-Clause)
6  */
7 
13 #pragma once
14 
15 // Source includes
16 #include "LvArrayConfig.hpp"
17 #include "Macros.hpp"
18 #include "typeManipulation.hpp"
19 #include "arrayManipulation.hpp"
20 
21 // TPL includes
22 #include <camp/resource.hpp>
23 
24 // System includes
25 #include <utility>
26 
27 namespace LvArray
28 {
29 
31 using MemorySpace = camp::resources::Platform;
32 
39 inline std::ostream & operator<<( std::ostream & os, MemorySpace const space )
40 {
41  if( space == MemorySpace::undefined )
42  return os << "undefined";
43  if( space == MemorySpace::host )
44  return os << "host";
45  if( space == MemorySpace::cuda )
46  return os << "cuda";
47  if( space == MemorySpace::omp_target )
48  return os << "omp_target";
49  if( space == MemorySpace::hip )
50  return os << "hip";
51  if( space == MemorySpace::sycl )
52  return os << "sycl";
53 
54  LVARRAY_ERROR( "Unrecognized memory space " << static_cast< int >( space ) );
55  return os;
56 }
57 
62 namespace bufferManipulation
63 {
64 
70 HAS_MEMBER_FUNCTION_NO_RTYPE( move, MemorySpace::host, true );
71 
78 struct VoidBuffer
79 {
88  void moveNested( MemorySpace const space, std::ptrdiff_t const size, bool const touch ) const
89  {
91  LVARRAY_UNUSED_VARIABLE( touch );
92  LVARRAY_ERROR_IF_NE_MSG( space, MemorySpace::host, "This Buffer type can only be used on the CPU." );
93  }
94 
102  void move( MemorySpace const space, bool const touch ) const
103  {
104  LVARRAY_UNUSED_VARIABLE( touch );
105  LVARRAY_ERROR_IF_NE_MSG( space, MemorySpace::host, "This Buffer type can only be used on the CPU." );
106  }
107 
113  { return MemorySpace::host; }
114 
121  void registerTouch( MemorySpace const space ) const
122  { LVARRAY_ERROR_IF_NE_MSG( space, MemorySpace::host, "This Buffer type can only be used on the CPU." ); }
123 
129  template< typename=VoidBuffer >
131  void setName( std::string const & name )
132  { LVARRAY_UNUSED_VARIABLE( name ); }
133 };
134 
142 template< typename BUFFER >
144 void check( BUFFER const & buf, std::ptrdiff_t const size )
145 {
146 #ifdef LVARRAY_BOUNDS_CHECK
147  LVARRAY_ERROR_IF_GT( 0, buf.capacity() );
148  LVARRAY_ERROR_IF_GT( 0, size );
149  LVARRAY_ERROR_IF_GT( size, buf.capacity() );
150 #else
151  LVARRAY_DEBUG_VAR( buf );
152  LVARRAY_DEBUG_VAR( size );
153 #endif
154 }
155 
164 template< typename BUFFER >
165 inline
166 void checkInsert( BUFFER const & buf, std::ptrdiff_t const size, std::ptrdiff_t const pos )
167 {
168 #ifdef LVARRAY_BOUNDS_CHECK
169  check( buf, size );
170  LVARRAY_ERROR_IF_GT( 0, pos );
171  LVARRAY_ERROR_IF_GT( pos, size );
172 #else
173  LVARRAY_DEBUG_VAR( buf );
174  LVARRAY_DEBUG_VAR( size );
175  LVARRAY_DEBUG_VAR( pos );
176 #endif
177 }
178 
186 template< typename BUFFER >
188 void free( BUFFER & buf, std::ptrdiff_t const size )
189 {
190  using T = typename BUFFER::value_type;
191 
192  check( buf, size );
193 
194  if( !std::is_trivially_destructible< T >::value )
195  {
196  buf.move( MemorySpace::host, true );
197  arrayManipulation::destroy( buf.data(), size );
198  }
199 
200  buf.free();
201 }
202 
212 template< typename BUFFER >
214 void setCapacity( BUFFER & buf, std::ptrdiff_t const size, MemorySpace const space, std::ptrdiff_t const newCapacity )
215 {
216  check( buf, size );
217  buf.reallocate( size, space, newCapacity );
218 }
219 
228 template< typename BUFFER >
230 void reserve( BUFFER & buf, std::ptrdiff_t const size, MemorySpace const space, std::ptrdiff_t const newCapacity )
231 {
232  check( buf, size );
233 
234  if( newCapacity > buf.capacity() )
235  {
236  setCapacity( buf, size, space, newCapacity );
237  }
238 }
239 
250 template< typename BUFFER >
251 void dynamicReserve( BUFFER & buf, std::ptrdiff_t const size, std::ptrdiff_t const newCapacity )
252 {
253  check( buf, size );
254 
255  if( newCapacity > buf.capacity() )
256  {
257  setCapacity( buf, size, MemorySpace::host, 2 * newCapacity );
258  }
259 }
260 
270 template< typename BUFFER, typename ... ARGS >
272 void resize( BUFFER & buf, std::ptrdiff_t const size, std::ptrdiff_t const newSize, ARGS && ... args )
273 {
274  check( buf, size );
275 
276  reserve( buf, size, MemorySpace::host, newSize );
277 
278  arrayManipulation::resize( buf.data(), size, newSize, std::forward< ARGS >( args )... );
279 
280 #if !defined(LVARRAY_DEVICE_COMPILE)
281  if( newSize > 0 )
282  {
283  buf.registerTouch( MemorySpace::host );
284  }
285 #endif
286 }
287 
296 template< typename BUFFER, typename ... ARGS >
297 void emplaceBack( BUFFER & buf, std::ptrdiff_t const size, ARGS && ... args )
298 {
299  check( buf, size );
300 
301  dynamicReserve( buf, size, size + 1 );
302  arrayManipulation::emplaceBack( buf.data(), size, std::forward< ARGS >( args ) ... );
303 }
304 
314 template< typename BUFFER, typename ... ARGS >
315 void emplace( BUFFER & buf,
316  std::ptrdiff_t const size,
317  std::ptrdiff_t const pos,
318  ARGS && ... args )
319 {
320  checkInsert( buf, size, pos );
321 
322  dynamicReserve( buf, size, size + 1 );
323  arrayManipulation::emplace( buf.data(), size, pos, std::forward< ARGS >( args ) ... );
324 }
325 
337 template< typename BUFFER, typename ITER >
338 std::ptrdiff_t insert( BUFFER & buf,
339  std::ptrdiff_t const size,
340  std::ptrdiff_t const pos,
341  ITER const first,
342  ITER const last )
343 {
344  checkInsert( buf, size, pos );
345 
346  std::ptrdiff_t const nVals = arrayManipulation::iterDistance( first, last );
347  dynamicReserve( buf, size, size + nVals );
348  arrayManipulation::insert( buf.data(), size, pos, first, nVals );
349  return nVals;
350 }
351 
358 template< typename BUFFER >
359 void popBack( BUFFER & buf, std::ptrdiff_t const size )
360 {
361  check( buf, size );
362  arrayManipulation::popBack( buf.data(), size );
363 }
364 
372 template< typename BUFFER >
373 void erase( BUFFER & buf, std::ptrdiff_t const size, std::ptrdiff_t const pos )
374 {
375  check( buf, size );
376  LVARRAY_ERROR_IF_GE( pos, size );
377 
378  arrayManipulation::erase( buf.data(), size, pos, std::ptrdiff_t( 1 ) );
379 }
380 
391 template< typename DST_BUFFER, typename SRC_BUFFER >
393 void copyInto( DST_BUFFER & dst,
394  std::ptrdiff_t const dstSize,
395  SRC_BUFFER const & src,
396  std::ptrdiff_t const srcSize )
397 {
398  check( dst, dstSize );
399  check( src, srcSize );
400 
401  resize( dst, dstSize, srcSize );
402 
403  using T = typename DST_BUFFER::value_type;
404  T * const LVARRAY_RESTRICT dstData = dst.data();
405  T const * const LVARRAY_RESTRICT srcData = src.data();
406 
407  for( std::ptrdiff_t i = 0; i < srcSize; ++i )
408  {
409  dstData[ i ] = srcData[ i ];
410  }
411 }
412 
413 } // namespace bufferManipulations
414 } // namespace LvArray
#define LVARRAY_UNUSED_VARIABLE(X)
Mark X as an unused variable, used to silence compiler warnings.
Definition: Macros.hpp:79
LVARRAY_HOST_DEVICE void resize(BUFFER &buf, std::ptrdiff_t const size, std::ptrdiff_t const newSize, ARGS &&... args)
Resize the buffer to the given size.
Definition: bufferManipulation.hpp:272
void emplace(BUFFER &buf, std::ptrdiff_t const size, std::ptrdiff_t const pos, ARGS &&... args)
Construct a new value at position pos.
Definition: bufferManipulation.hpp:315
std::ptrdiff_t insert(BUFFER &buf, std::ptrdiff_t const size, std::ptrdiff_t const pos, ITER const first, ITER const last)
Insert multiple values into the buffer.
Definition: bufferManipulation.hpp:338
void emplaceBack(BUFFER &buf, std::ptrdiff_t const size, ARGS &&... args)
Construct a new value at the end of the buffer.
Definition: bufferManipulation.hpp:297
DISABLE_HD_WARNING LVARRAY_HOST_DEVICE void emplaceBack(T *const LVARRAY_RESTRICT ptr, std::ptrdiff_t const size, ARGS &&... args)
Append the to the array constructing the new value in place.
Definition: arrayManipulation.hpp:425
DISABLE_HD_WARNING LVARRAY_HOST_DEVICE void insert(T *const LVARRAY_RESTRICT ptr, std::ptrdiff_t const size, std::ptrdiff_t const index, ITERATOR first, std::ptrdiff_t const n)
Insert the given values into the array at the given position.
Definition: arrayManipulation.hpp:505
LVARRAY_HOST_DEVICE void setName(std::string const &name)
Set the name associated with this buffer.
Definition: bufferManipulation.hpp:131
This class implements the default behavior for the Buffer methods related to execution space...
Definition: bufferManipulation.hpp:78
void dynamicReserve(BUFFER &buf, std::ptrdiff_t const size, std::ptrdiff_t const newCapacity)
If the buffer&#39;s capacity is greater than newCapacity this is a no-op. Otherwise the buffer&#39;s capacity...
Definition: bufferManipulation.hpp:251
Contains templates useful for type manipulation.
#define LVARRAY_ERROR_IF_NE_MSG(lhs, rhs, msg)
Raise a hard error if two values are not equal.
Definition: Macros.hpp:344
DISABLE_HD_WARNING LVARRAY_HOST_DEVICE void resize(T *const LVARRAY_RESTRICT ptr, std::ptrdiff_t const size, std::ptrdiff_t const newSize, ARGS &&... args)
Resize the give array.
Definition: arrayManipulation.hpp:283
void popBack(BUFFER &buf, std::ptrdiff_t const size)
Remove a value from the end of the buffer.
Definition: bufferManipulation.hpp:359
#define CONSTEXPR_WITHOUT_BOUNDS_CHECK
Expands to constexpr when array bound checking is disabled.
Definition: Macros.hpp:662
DISABLE_HD_WARNING LVARRAY_HOST_DEVICE void erase(T *const LVARRAY_RESTRICT ptr, std::ptrdiff_t const size, std::ptrdiff_t const index, std::ptrdiff_t const n=1)
Shift the values in the array at or above the given position down by the given amount overwriting the...
Definition: arrayManipulation.hpp:396
#define LVARRAY_ERROR_IF_GT(lhs, rhs)
Raise a hard error if one value compares greater than the other.
Definition: Macros.hpp:392
void checkInsert(BUFFER const &buf, std::ptrdiff_t const size, std::ptrdiff_t const pos)
Check that given Buffer, size, and insertion position, are valid.
Definition: bufferManipulation.hpp:166
LVARRAY_HOST_DEVICE CONSTEXPR_WITHOUT_BOUNDS_CHECK void check(BUFFER const &buf, std::ptrdiff_t const size)
Check that given Buffer and size are valid.
Definition: bufferManipulation.hpp:144
DISABLE_HD_WARNING LVARRAY_HOST_DEVICE void popBack(T *const LVARRAY_RESTRICT ptr, std::ptrdiff_t const size)
Destroy the value at the end of the array.
Definition: arrayManipulation.hpp:533
#define LVARRAY_ERROR(MSG)
Abort execution.
Definition: Macros.hpp:176
DISABLE_HD_WARNING LVARRAY_HOST_DEVICE void free(BUFFER &buf, std::ptrdiff_t const size)
Destroy the values in the buffer and free it&#39;s memory.
Definition: bufferManipulation.hpp:188
camp::resources::Platform MemorySpace
an alias for camp::resources::Platform.
Definition: bufferManipulation.hpp:31
Contains functions for manipulating a contiguous array of values.
void move(MemorySpace const space, bool const touch) const
Move the buffer to the given execution space, optionally touching it.
Definition: bufferManipulation.hpp:102
#define LVARRAY_DEBUG_VAR(X)
Mark X as an debug variable, used to silence compiler warnings.
Definition: Macros.hpp:85
void moveNested(MemorySpace const space, std::ptrdiff_t const size, bool const touch) const
Move the buffer to the given execution space, optionally touching it.
Definition: bufferManipulation.hpp:88
The top level namespace.
Definition: Array.hpp:24
LVARRAY_HOST_DEVICE void reserve(BUFFER &buf, std::ptrdiff_t const size, MemorySpace const space, std::ptrdiff_t const newCapacity)
Reserve space in the buffer for at least the given capacity.
Definition: bufferManipulation.hpp:230
Contains a bunch of macro definitions.
std::ostream & operator<<(std::ostream &os, MemorySpace const space)
Output a Platform enum to a stream.
Definition: bufferManipulation.hpp:39
#define LVARRAY_ERROR_IF_GE(lhs, rhs)
Raise a hard error if one value compares greater than or equal to the other.
Definition: Macros.hpp:424
DISABLE_HD_WARNING LVARRAY_HOST_DEVICE void destroy(T *const LVARRAY_RESTRICT ptr, std::ptrdiff_t const size)
Destory the values in the array.
Definition: arrayManipulation.hpp:152
MemorySpace getPreviousSpace() const
Definition: bufferManipulation.hpp:112
DISABLE_HD_WARNING LVARRAY_HOST_DEVICE void copyInto(DST_BUFFER &dst, std::ptrdiff_t const dstSize, SRC_BUFFER const &src, std::ptrdiff_t const srcSize)
Copy values from the source buffer into the destination buffer.
Definition: bufferManipulation.hpp:393
DISABLE_HD_WARNING LVARRAY_HOST_DEVICE void setCapacity(BUFFER &buf, std::ptrdiff_t const size, MemorySpace const space, std::ptrdiff_t const newCapacity)
Set the capacity of the buffer.
Definition: bufferManipulation.hpp:214
#define DISABLE_HD_WARNING
Disable host device warnings.
Definition: Macros.hpp:614
HAS_MEMBER_FUNCTION_NO_RTYPE(move, MemorySpace::host, true)
Defines a static constexpr bool HasMemberFunction_move< CLASS > that is true iff the class has a meth...
DISABLE_HD_WARNING constexpr LVARRAY_HOST_DEVICE std::iterator_traits< ITER >::difference_type iterDistance(ITER first, ITER const last, std::input_iterator_tag)
Definition: arrayManipulation.hpp:105
void erase(BUFFER &buf, std::ptrdiff_t const size, std::ptrdiff_t const pos)
Erase a value from the buffer.
Definition: bufferManipulation.hpp:373
void registerTouch(MemorySpace const space) const
Touch the buffer in the given space.
Definition: bufferManipulation.hpp:121
DISABLE_HD_WARNING LVARRAY_HOST_DEVICE void emplace(T *const LVARRAY_RESTRICT ptr, std::ptrdiff_t const size, std::ptrdiff_t const index, ARGS &&... args)
Insert into the array constructing the new value in place.
Definition: arrayManipulation.hpp:478
#define LVARRAY_HOST_DEVICE
Mark a function for both host and device usage.
Definition: Macros.hpp:600