16 #include "LvArrayConfig.hpp" 24 #include <chai/ArrayManager.hpp> 39 inline chai::ArrayManager & getArrayManager()
41 static chai::ArrayManager & arrayManager = *chai::ArrayManager::getInstance();
46 static std::mutex chaiLock;
52 inline chai::ExecutionSpace toChaiExecutionSpace(
MemorySpace const space )
54 if( space == MemorySpace::NONE )
56 if( space == MemorySpace::CPU )
58 #if defined(LVARRAY_USE_CUDA) 59 if( space == MemorySpace::GPU )
63 LVARRAY_ERROR(
"Unrecognized memory space " << static_cast< int >( space ) );
72 inline MemorySpace toMemorySpace( chai::ExecutionSpace
const space )
74 if( space == chai::NONE )
75 return MemorySpace::NONE;
76 if( space == chai::CPU )
77 return MemorySpace::CPU;
78 #if defined(LVARRAY_USE_CUDA) 79 if( space == chai::GPU )
80 return MemorySpace::GPU;
83 LVARRAY_ERROR(
"Unrecognized execution space " << static_cast< int >( space ) );
85 return MemorySpace::NONE;
103 template<
typename T >
112 constexpr
static bool hasShallowCopy =
true;
124 m_pointer( nullptr ),
126 m_pointerRecord( nullptr )
135 m_pointer( nullptr ),
137 m_pointerRecord( new chai::PointerRecord{} )
139 m_pointerRecord->m_size = 0;
142 for(
int space = chai::CPU; space < chai::NUM_EXECUTION_SPACES; ++space )
144 m_pointerRecord->m_allocators[ space ] = internal::getArrayManager().getAllocatorId( chai::ExecutionSpace( space ) );
156 m_pointer( src.m_pointer ),
157 m_capacity( src.m_capacity ),
158 m_pointerRecord( src.m_pointerRecord )
160 #if defined(LVARRAY_USE_CUDA) && !defined(__CUDA_ARCH__) 161 move( internal::toMemorySpace( internal::getArrayManager().getExecutionSpace() ),
true );
174 m_pointer( src.m_pointer ),
175 m_capacity( src.m_capacity ),
176 m_pointerRecord( src.m_pointerRecord )
178 #if defined(LVARRAY_USE_CUDA) && !defined(__CUDA_ARCH__) 179 moveNested( internal::toMemorySpace( internal::getArrayManager().getExecutionSpace() ), size,
true );
191 m_pointer( src.m_pointer ),
192 m_capacity( src.m_capacity ),
193 m_pointerRecord( src.m_pointerRecord )
196 src.m_pointer =
nullptr;
197 src.m_pointerRecord =
nullptr;
205 template< typename _T=T, typename=std::enable_if_t< std::is_const< _T >::value > >
208 m_pointer( src.data() ),
209 m_capacity( src.capacity() ),
210 m_pointerRecord( &src.pointerRecord() )
221 m_capacity = src.m_capacity;
222 m_pointer = src.m_pointer;
223 m_pointerRecord = src.m_pointerRecord;
235 m_capacity = src.m_capacity;
236 m_pointer = src.m_pointer;
237 m_pointerRecord = src.m_pointerRecord;
240 src.m_pointer =
nullptr;
241 src.m_pointerRecord =
nullptr;
254 void reallocate( std::ptrdiff_t
const size, std::ptrdiff_t
const newCapacity )
256 chai::PointerRecord *
const newRecord =
new chai::PointerRecord{};
257 newRecord->m_size = newCapacity *
sizeof( T );
258 newRecord->m_user_callback = m_pointerRecord->m_user_callback;
260 for(
int space = chai::CPU; space < chai::NUM_EXECUTION_SPACES; ++space )
262 newRecord->m_allocators[ space ] = m_pointerRecord->m_allocators[ space ];
265 internal::chaiLock.lock();
266 internal::getArrayManager().allocate( newRecord, chai::CPU );
267 internal::chaiLock.unlock();
269 T *
const newPointer =
static_cast< T *
>( newRecord->m_pointers[ chai::CPU ] );
271 std::ptrdiff_t
const overlapAmount =
std::min( newCapacity, size );
276 m_capacity = newCapacity;
277 m_pointer = newPointer;
278 m_pointerRecord = newRecord;
279 registerTouch( MemorySpace::CPU );
289 std::lock_guard< std::mutex > lock( internal::chaiLock );
290 internal::getArrayManager().free( m_pointerRecord );
293 m_pointerRecord =
nullptr;
301 {
return m_capacity; }
308 {
return m_pointer; }
316 {
return *m_pointerRecord; }
324 template<
typename INDEX_TYPE >
327 {
return m_pointer[ i ]; }
339 #if defined(LVARRAY_USE_CUDA) 340 chai::ExecutionSpace
const chaiSpace = internal::toChaiExecutionSpace( space );
341 if( m_pointerRecord ==
nullptr ||
343 chaiSpace == chai::NONE )
return;
345 chai::ExecutionSpace
const prevSpace = m_pointerRecord->m_last_space;
347 if( prevSpace == chai::CPU && prevSpace != chaiSpace ) moveInnerData( space, size, touch );
349 move( space, touch );
351 if( prevSpace == chai::GPU && prevSpace != chaiSpace ) moveInnerData( space, size, touch );
367 #if defined(LVARRAY_USE_CUDA) 368 chai::ExecutionSpace
const chaiSpace = internal::toChaiExecutionSpace( space );
369 if( m_pointerRecord ==
nullptr ||
371 chaiSpace == chai::NONE )
return;
373 const_cast< T * &
>( m_pointer ) =
374 static_cast< T * >( internal::getArrayManager().move( const_cast< T_non_const * >( m_pointer ),
378 if( !std::is_const< T >::value && touch ) m_pointerRecord->m_touched[ chaiSpace ] =
true;
379 m_pointerRecord->m_last_space = chaiSpace;
393 chai::ExecutionSpace
const chaiSpace = internal::toChaiExecutionSpace( space );
394 m_pointerRecord->m_touched[ chaiSpace ] =
true;
395 m_pointerRecord->m_last_space = chaiSpace;
403 template<
typename U=ChaiBuffer< T > >
406 std::string const typeString = LvArray::system::demangleType< U >();
407 m_pointerRecord->m_user_callback =
408 [name, typeString]( chai::PointerRecord
const *
const record, chai::Action
const act, chai::ExecutionSpace
const s )
410 if( act == chai::ACTION_MOVE )
414 char const *
const spaceStr = ( s == chai::CPU ) ?
"HOST " :
"DEVICE";
415 LVARRAY_LOG(
"Moved " << paddedSize <<
" to the " << spaceStr <<
": " << typeString <<
" " << name );
431 template<
typename U=T_non_const >
432 std::enable_if_t< bufferManipulation::HasMemberFunction_move< U > >
433 moveInnerData(
MemorySpace const space, std::ptrdiff_t
const size,
bool const touch )
const 435 if( space == MemorySpace::NONE )
return;
437 for( std::ptrdiff_t i = 0; i < size; ++i )
439 const_cast< T_non_const *
>( m_pointer )[ i ].move( space, touch );
449 template<
typename U=T_non_const >
450 std::enable_if_t< !bufferManipulation::HasMemberFunction_move< U > >
451 moveInnerData(
MemorySpace const, std::ptrdiff_t
const,
bool const )
const 455 T * LVARRAY_RESTRICT m_pointer =
nullptr;
458 std::ptrdiff_t m_capacity = 0;
461 chai::PointerRecord * m_pointerRecord =
nullptr;
LVARRAY_INTEL_CONSTEXPR ChaiBuffer & operator=(ChaiBuffer &&src)
Move assignment operator.
#define LVARRAY_UNUSED_VARIABLE(X)
Mark X as an unused variable, used to silence compiler warnings.
void free()
Free the data in the buffer but does not destroy any values.
constexpr ChaiBuffer()
Default constructor, creates an uninitialized ChaiBuffer.
void setName(std::string const &name)
Set the name associated with this buffer which is used in the chai callback.
T value_type
Alias for T used used in the bufferManipulation functions.
constexpr std::ptrdiff_t capacity() const
void uninitializedMove(T *const LVARRAY_RESTRICT dst, std::ptrdiff_t const size, T *const LVARRAY_RESTRICT src)
Move construct values from the source to the destination.
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.
Contains functions that interact with the system or runtime environment.
ChaiBuffer(ChaiBuffer const &src)
Copy constructor.
Contains templates useful for type manipulation.
Implements the Buffer interface using CHAI.
constexpr chai::PointerRecord & pointerRecord() const
Return a reference to the associated CHAI PointerRecord.
void destroy(T *const LVARRAY_RESTRICT ptr, std::ptrdiff_t const size)
Destory the values in the array.
#define LVARRAY_LOG(...)
Print the expression.
void move(MemorySpace const space, bool const touch) const
Move the buffer to the given execution space, optionally touching it.
void free(BUFFER &buf, std::ptrdiff_t const size)
Destroy the values in the buffer and free it's memory.
constexpr ChaiBuffer(ChaiBuffer< std::remove_const_t< T > > const &src)
Create a copy of src with const T.
Contains functions for manipulating buffers.
constexpr ChaiBuffer(ChaiBuffer &&src)
Move constructor.
#define LVARRAY_ERROR(MSG)
Abort execution.
Contains functions for manipulating a contiguous array of values.
ChaiBuffer(bool)
Constructor for creating an empty Buffer.
MemorySpace
An enum containing the available memory spaces.
std::remove_const_t< T > T_non_const
An alias for the non const version of T.
Contains a bunch of macro definitions.
LVARRAY_INTEL_CONSTEXPR ChaiBuffer & operator=(ChaiBuffer const &src)
Copy assignment operator.
constexpr T & operator[](INDEX_TYPE const i) const
std::string string
String type.
constexpr std::enable_if_t< std::is_arithmetic< T >::value, T > min(T const a, T const b)
ChaiBuffer(ChaiBuffer const &src, std::ptrdiff_t const size)
Copy constructor.
#define LVARRAY_ERROR_IF_NE(lhs, rhs)
Raise a hard error if two values are not equal.
void reallocate(std::ptrdiff_t const size, std::ptrdiff_t const newCapacity)
Reallocate the buffer to the new capacity.
constexpr T * data() const
constexpr void registerTouch(MemorySpace const space) const
Touch the buffer in the given space.
std::string calculateSize(size_t const bytes)
#define LVARRAY_HOST_DEVICE
Mark a function for both host and device usage.