3 #ifndef SYNCHRONIZED_HEAP_OPENCL_H
4 #define SYNCHRONIZED_HEAP_OPENCL_H
14 #if ( SETTING_OPENCL != 0 )
19 #include "synchronized_heap_base.h"
24 #include <boost/bimap.hpp>
25 #include <boost/bimap/multiset_of.hpp>
26 #include <boost/bimap/set_of.hpp>
28 #include <unordered_set>
36 namespace Synchronized {
49 template<
typename t_Type >
52 typedef cl_mem OpenCLType;
55 inline Heap( std::shared_ptr< OpenCL::State >
const& pState,
size_t const size );
58 template<
typename t_Type >
59 inline Pointer< t_Type > Allocate();
61 template<
typename t_Type >
62 inline Pointer< t_Type[] > Allocate(
size_t const count );
65 inline void Synchronize();
68 inline OpenCLType OpenCLConvert()
const;
75 inline ObjectBase( Heap*
const pParent, std::pair< size_t, size_t >
const& span );
77 virtual ~ObjectBase() = 0;
80 virtual void OpenCLWrite(
void*
const destination )
const = 0;
83 inline unsigned int References()
const;
85 inline void AddReference();
86 inline void ReleaseReference();
89 inline std::pair< size_t, size_t >
const& Span()
const;
91 inline void Mark()
const;
96 unsigned int m_refcount;
99 std::pair< size_t, size_t > m_span;
102 template<
typename t_Type >
103 struct Object :
public ObjectBase {
108 inline Object( Heap*
const pParent, std::pair< size_t, size_t >
const& span );
113 virtual void OpenCLWrite(
void*
const destination )
const;
116 inline t_Type
const* Get()
const;
117 inline void Set( t_Type
const& value );
125 template<
typename t_Type >
126 struct Object< t_Type[] > :
public ObjectBase {
131 inline Object( Heap*
const pParent, std::pair< size_t, size_t >
const& span,
size_t const count );
136 virtual void OpenCLWrite(
void*
const destination )
const;
139 inline t_Type
const* Get(
size_t const index = 0 )
const;
140 inline void Set(
size_t const index, t_Type
const& value );
152 template<
typename t_Type >
155 typedef typename Object< t_Type >::Type
const element_type;
156 typedef cl_uint OpenCLType;
160 inline Pointer( Pointer
const& other );
166 inline void swap( Pointer& other );
168 inline unsigned int use_count()
const;
169 inline bool unique()
const;
172 inline element_type*
get()
const;
174 inline void Assign( element_type
const& data )
const;
175 inline void Assign(
size_t const index, element_type
const& data )
const;
178 inline Pointer
const& operator=( Pointer
const& other );
181 inline operator bool()
const;
183 inline element_type* operator->()
const;
184 inline element_type& operator*()
const;
186 inline element_type& operator[](
size_t const index )
const;
188 inline bool operator==( Pointer
const& other )
const;
189 inline bool operator!=( Pointer
const& other )
const;
192 inline OpenCLType OpenCLConvert()
const;
197 inline Pointer( Object< t_Type >* pointer );
200 Object< t_Type >* m_pointer;
203 friend struct Heap< PLATFORM_OPENCL >;
209 struct ObjectComparison {
211 inline bool operator()( ObjectBase
const*
const pLeft, ObjectBase
const*
const pRight )
const;
215 template<
typename t_Type >
216 inline std::pair< size_t, size_t > AllocateSpan(
size_t const count = 1 );
218 inline void FreeObject( ObjectBase
const* pObject );
220 inline void MarkObject( ObjectBase
const* pObject );
223 typedef boost::bimap< boost::bimaps::set_of< size_t >, boost::bimaps::multiset_of< size_t > > FreeSpans;
224 typedef std::unordered_set< ObjectBase const* > MarkedObjects;
227 std::shared_ptr< OpenCL::State > m_pState;
228 std::unique_ptr< _cl_mem, OpenCL::Deleter< _cl_mem > > m_buffer;
230 FreeSpans m_freeSpans;
231 MarkedObjects m_markedObjects;
242 Heap< PLATFORM_OPENCL >::ObjectBase::ObjectBase( Heap*
const pParent, std::pair< size_t, size_t >
const& span ) :
244 m_pParent( pParent ),
250 unsigned int Heap< PLATFORM_OPENCL >::ObjectBase::References()
const {
256 void Heap< PLATFORM_OPENCL >::ObjectBase::AddReference() {
262 void Heap< PLATFORM_OPENCL >::ObjectBase::ReleaseReference() {
264 assert( m_refcount > 0 );
265 if ( --m_refcount == 0 )
270 std::pair< size_t, size_t >
const& Heap< PLATFORM_OPENCL >::ObjectBase::Span()
const {
276 void Heap< PLATFORM_OPENCL >::ObjectBase::Mark()
const {
278 assert( m_pParent != NULL );
279 m_pParent->MarkObject(
this );
290 template<
typename t_Type >
291 Heap< PLATFORM_OPENCL >::Object< t_Type >::Object( Heap*
const pParent, std::pair< size_t, size_t >
const& span ) :
292 ObjectBase( pParent, span )
297 template<
typename t_Type >
298 Heap< PLATFORM_OPENCL >::Object< t_Type >::~Object() {
302 template<
typename t_Type >
303 void Heap< PLATFORM_OPENCL >::Object< t_Type >::OpenCLWrite(
void*
const destination )
const {
305 typedef typename OpenCL::Converter< t_Type >::Type OpenCLType;
310 template<
typename t_Type >
311 t_Type
const* Heap< PLATFORM_OPENCL >::Object< t_Type >::Get()
const {
317 template<
typename t_Type >
318 void Heap< PLATFORM_OPENCL >::Object< t_Type >::Set( t_Type
const& data ) {
325 template<
typename t_Type >
326 Heap< PLATFORM_OPENCL >::Object< t_Type[] >::Object( Heap*
const pParent, std::pair< size_t, size_t >
const& span,
size_t const count ) :
327 ObjectBase( pParent, span ),
329 m_array( new t_Type[ m_count ] )
334 template<
typename t_Type >
335 Heap< PLATFORM_OPENCL >::Object< t_Type[] >::~Object() {
341 template<
typename t_Type >
342 void Heap< PLATFORM_OPENCL >::Object< t_Type[] >::OpenCLWrite(
void*
const destination )
const {
344 typedef typename OpenCL::Converter< t_Type >::Type OpenCLType;
346 OpenCLType* ii =
reinterpret_cast< OpenCLType*
>( destination );
347 OpenCLType* iiEnd = ii + m_count;
348 t_Type
const* jj = m_array;
349 for ( ; ii != iiEnd; ++ii, ++jj )
354 template<
typename t_Type >
355 t_Type
const* Heap< PLATFORM_OPENCL >::Object< t_Type[] >::Get(
size_t const index )
const {
357 assert( index < m_count );
358 return( m_array + index );
362 template<
typename t_Type >
363 void Heap< PLATFORM_OPENCL >::Object< t_Type[] >::Set(
size_t const index, t_Type
const& data ) {
365 assert( index < m_count );
366 m_array[ index ] = data;
378 template<
typename t_Type >
379 Heap< PLATFORM_OPENCL >::Pointer< t_Type >::Pointer() : m_pointer( NULL ) {
383 template<
typename t_Type >
384 Heap< PLATFORM_OPENCL >::Pointer< t_Type >::Pointer( Pointer
const& other ) : m_pointer( other.m_pointer ) {
386 if ( m_pointer != NULL )
387 m_pointer->AddReference();
391 template<
typename t_Type >
392 Heap< PLATFORM_OPENCL >::Pointer< t_Type >::~Pointer() {
398 template<
typename t_Type >
399 void Heap< PLATFORM_OPENCL >::Pointer< t_Type >::reset() {
401 if ( m_pointer != NULL ) {
403 m_pointer->ReleaseReference();
409 template<
typename t_Type >
410 void Heap< PLATFORM_OPENCL >::Pointer< t_Type >::swap( Pointer& other ) {
412 std::swap( m_pointer, other.m_pointer );
416 template<
typename t_Type >
417 unsigned int Heap< PLATFORM_OPENCL >::Pointer< t_Type >::use_count()
const {
419 unsigned int result = 0;
420 if ( m_pointer != NULL )
421 result = m_pointer->References();
426 template<
typename t_Type >
427 bool Heap< PLATFORM_OPENCL >::Pointer< t_Type >::unique()
const {
429 return( use_count() == 1 );
433 template<
typename t_Type >
434 typename Heap< PLATFORM_OPENCL >::Object< t_Type >::Type
const* Heap< PLATFORM_OPENCL >::Pointer< t_Type >::get()
const {
436 return m_pointer->Get();
440 template<
typename t_Type >
441 void Heap< PLATFORM_OPENCL >::Pointer< t_Type >::Assign( element_type
const& data )
const {
443 m_pointer->Set( data );
447 template<
typename t_Type >
448 void Heap< PLATFORM_OPENCL >::Pointer< t_Type >::Assign(
size_t const index, element_type
const& data )
const {
450 m_pointer->Set( index, data );
454 template<
typename t_Type >
455 Heap< PLATFORM_OPENCL >::Pointer< t_Type >
const& Heap< PLATFORM_OPENCL >::Pointer< t_Type >::operator=( Pointer
const& other ) {
457 if ( m_pointer != other.m_pointer ) {
460 m_pointer = other.m_pointer;
461 if ( m_pointer != NULL )
462 m_pointer->AddReference();
469 template<
typename t_Type >
470 Heap< PLATFORM_OPENCL >::Pointer< t_Type >::operator bool()
const {
472 return( m_pointer != NULL );
476 template<
typename t_Type >
477 typename Heap< PLATFORM_OPENCL >::Object< t_Type >::Type
const* Heap< PLATFORM_OPENCL >::Pointer< t_Type >::operator->()
const {
479 return m_pointer->Get();
483 template<
typename t_Type >
484 typename Heap< PLATFORM_OPENCL >::Object< t_Type >::Type
const& Heap< PLATFORM_OPENCL >::Pointer< t_Type >::operator*()
const {
486 return *m_pointer->Get();
490 template<
typename t_Type >
491 typename Heap< PLATFORM_OPENCL >::Object< t_Type >::Type
const& Heap< PLATFORM_OPENCL >::Pointer< t_Type >::operator[](
size_t const index )
const {
493 return *m_pointer->Get( index );
497 template<
typename t_Type >
498 bool Heap< PLATFORM_OPENCL >::Pointer< t_Type >::operator==( Pointer
const& other )
const {
500 return( m_pointer == other.m_pointer );
504 template<
typename t_Type >
505 bool Heap< PLATFORM_OPENCL >::Pointer< t_Type >::operator!=( Pointer
const& other )
const {
507 return( m_pointer != other.m_pointer );
511 template<
typename t_Type >
512 Heap< PLATFORM_OPENCL >::Pointer< t_Type >::Pointer( Object< t_Type >* pointer ) : m_pointer( pointer ) {
514 if ( m_pointer != NULL )
515 m_pointer->AddReference();
519 template<
typename t_Type >
520 typename Heap< PLATFORM_OPENCL >::Pointer< t_Type >::OpenCLType Heap< PLATFORM_OPENCL >::Pointer< t_Type >::OpenCLConvert()
const {
522 return( ( m_pointer != NULL ) ? m_pointer->Span().first : OPENCL_NULL );
533 bool Heap< PLATFORM_OPENCL >::ObjectComparison::operator()( ObjectBase
const*
const pLeft, ObjectBase
const*
const pRight )
const {
535 assert( ( pLeft != NULL ) && ( pRight != NULL ) );
536 return( pLeft->Span() < pRight->Span() );
547 Heap< PLATFORM_OPENCL >::Heap( std::shared_ptr< OpenCL::State >
const& pState,
size_t const size ) : m_pState( pState ) {
549 cl_int result = CL_SUCCESS;
550 m_buffer.reset( clCreateBuffer( m_pState->Context(), CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR, size, NULL, &result ) );
551 if ( result != CL_SUCCESS )
554 m_freeSpans.insert( FreeSpans::value_type( 0, size ) );
558 template<
typename t_Type >
559 Heap< PLATFORM_OPENCL >::Pointer< t_Type > Heap< PLATFORM_OPENCL >::Allocate() {
561 std::pair< size_t, size_t >
const span = AllocateSpan< t_Type >();
562 Object< t_Type >* pObject =
new Object< t_Type >(
this, span );
563 MarkObject( pObject );
564 return Pointer< t_Type >( pObject );
568 template<
typename t_Type >
569 Heap< PLATFORM_OPENCL >::Pointer< t_Type[] > Heap< PLATFORM_OPENCL >::Allocate(
size_t const count ) {
571 std::pair< size_t, size_t >
const span = AllocateSpan< t_Type >( count );
572 Object< t_Type[] >* pObject =
new Object< t_Type[] >(
this, span, count );
573 MarkObject( pObject );
574 return Pointer< t_Type[] >( pObject );
578 void Heap< PLATFORM_OPENCL >::Synchronize() {
580 if ( ! m_markedObjects.empty() ) {
582 MarkedObjects::size_type
const size = m_markedObjects.size();
583 std::unique_ptr< ObjectBase const* > markedObjects(
new ObjectBase
const*[ size ] );
584 std::copy( m_markedObjects.begin(), m_markedObjects.end(), markedObjects.get() );
585 std::sort( markedObjects.get(), markedObjects.get() + size, ObjectComparison() );
587 ObjectBase
const*
const* ii = markedObjects.get();
588 ObjectBase
const*
const* iiEnd = markedObjects.get() + size;
589 while ( ii != iiEnd ) {
591 ObjectBase
const*
const* iiNext = ii;
592 std::pair< size_t, size_t > span = ( *ii )->Span();
593 for ( ++iiNext; iiNext != iiEnd; ++iiNext ) {
595 std::pair< size_t, size_t >
const spanNext = ( *iiNext )->Span();
596 assert( span.first + span.second <= spanNext.first );
597 if ( span.first + span.second == spanNext.first )
598 span.second += spanNext.second;
603 cl_int result = CL_SUCCESS;
604 void*
const buffer = clEnqueueMapBuffer(
616 if ( result != CL_SUCCESS )
619 for (
void* destination = buffer; ii != iiNext; ++ii ) {
621 ( *ii )->OpenCLWrite( destination );
622 destination =
reinterpret_cast< uint8_t*
>( destination ) + ( *ii )->Span().second;
625 clEnqueueUnmapMemObject(
637 m_markedObjects.clear();
642 Heap< PLATFORM_OPENCL >::OpenCLType Heap< PLATFORM_OPENCL >::OpenCLConvert()
const {
644 return m_buffer.get();
648 template<
typename t_Type >
649 std::pair< size_t, size_t > Heap< PLATFORM_OPENCL >::AllocateSpan(
size_t const count ) {
651 size_t const size =
sizeof(
typename OpenCL::Converter< t_Type >::Type ) * count;
653 FreeSpans::right_map::iterator ii = m_freeSpans.right.lower_bound( size );
654 if ( ii == m_freeSpans.right.end() )
657 std::pair< size_t, size_t > span( ii->second, ii->first );
658 m_freeSpans.right.erase( ii );
660 assert( span.second >= size );
661 if ( span.second > size ) {
663 m_freeSpans.insert( FreeSpans::value_type( span.first + size, span.second - size ) );
671 void Heap< PLATFORM_OPENCL >::FreeObject( ObjectBase
const* pObject ) {
673 m_markedObjects.erase( pObject );
675 { std::pair< size_t, size_t > span = pObject->Span();
677 FreeSpans::left_map::iterator ii = m_freeSpans.left.lower_bound( span.first );
679 if ( ii != m_freeSpans.left.begin() ) {
681 FreeSpans::left_map::iterator iiPrev = ii;
684 assert( iiPrev->first + iiPrev->second <= span.first );
685 if ( iiPrev->first + iiPrev->second == span.first ) {
687 span.first -= iiPrev->second;
688 span.second += iiPrev->second;
689 m_freeSpans.left.erase( iiPrev );
693 if ( ii != m_freeSpans.left.end() ) {
695 assert( span.first + span.second <= ii->first );
696 if ( span.first + span.second == ii->first ) {
698 span.second += ii->second;
699 m_freeSpans.left.erase( ii );
703 m_freeSpans.insert( FreeSpans::value_type( span.first, span.second ) );
708 void Heap< PLATFORM_OPENCL >::MarkObject( ObjectBase
const* pObject ) {
710 m_markedObjects.insert( pObject );
721 #endif // SETTING_OPENCL
726 #endif // SYNCHRONIZED_HEAP_OPENCL_H