From a26b27ea142449d0a9f4beb4d201f7a912aad002 Mon Sep 17 00:00:00 2001 From: Tobias Fuchs Date: Sat, 25 Mar 2017 12:55:39 +0100 Subject: [PATCH] Integrating strict random-access semantics on global address range --- dash/include/dash/Array.h | 2 - dash/include/dash/GlobAsyncRef.h | 90 ++------ dash/include/dash/GlobPtr.h | 276 +++++++++++------------ dash/include/dash/GlobRef.h | 13 -- dash/include/dash/memory/GlobHeapMem.h | 17 ++ dash/include/dash/memory/GlobStaticMem.h | 25 +- dash/include/dash/memory/GlobUnitMem.h | 7 + dash/include/dash/memory/MemorySpace.h | 18 ++ dash/test/memory/GlobStaticMemTest.cc | 59 +++++ 9 files changed, 275 insertions(+), 232 deletions(-) create mode 100644 dash/include/dash/memory/MemorySpace.h diff --git a/dash/include/dash/Array.h b/dash/include/dash/Array.h index a3e109ed5..5c972d0c3 100644 --- a/dash/include/dash/Array.h +++ b/dash/include/dash/Array.h @@ -351,7 +351,6 @@ class AsyncArrayRef */ constexpr const_async_reference operator[](const size_t n) const { return async_reference( - _array->m_globmem, (*(_array->begin() + n)).dart_gptr()); } @@ -360,7 +359,6 @@ class AsyncArrayRef */ async_reference operator[](const size_t n) { return async_reference( - _array->m_globmem, (*(_array->begin() + n)).dart_gptr()); } diff --git a/dash/include/dash/GlobAsyncRef.h b/dash/include/dash/GlobAsyncRef.h index b9dc9a0bd..48511cd0c 100644 --- a/dash/include/dash/GlobAsyncRef.h +++ b/dash/include/dash/GlobAsyncRef.h @@ -44,15 +44,17 @@ class GlobAsyncRef std::ostream & os, const GlobAsyncRef & gar); + template < + typename ElementT > + friend class GlobAsyncRef; + private: typedef GlobAsyncRef self_t; - typedef GlobStaticMem > - GlobMem_t; + typedef typename std::remove_const::type + nonconst_value_type; private: - /// Instance of GlobStaticMem that issued this global reference - GlobMem_t * _globmem; /// Value of the referenced element, initially not loaded mutable T _value; /// Pointer to referenced element in global memory @@ -67,26 +69,11 @@ class GlobAsyncRef mutable bool _has_value = false; public: - /** - * Conctructor, creates an GlobRefAsync object referencing an element in - * global memory. - */ - GlobAsyncRef( - /// Instance of GlobStaticMem that issued this global reference - GlobMem_t * globmem, - /// Pointer to referenced object in global memory - T * lptr) - : _value(*lptr), - _lptr(lptr), - _is_local(true), - _has_value(true) - { } - /** * Conctructor, creates an GlobRefAsync object referencing an element in * local memory. */ - GlobAsyncRef( + explicit GlobAsyncRef( /// Pointer to referenced object in local memory T * lptr) : _value(*lptr), @@ -99,30 +86,10 @@ class GlobAsyncRef * Conctructor, creates an GlobRefAsync object referencing an element in * global memory. */ - template - GlobAsyncRef( - /// Instance of GlobStaticMem that issued this global reference - GlobMem_t * globmem, - /// Pointer to referenced object in global memory - GlobPtr & gptr) - : _gptr(gptr.dart_gptr()) - { - _is_local = gptr.is_local(); - if (_is_local) { - _value = *gptr; - _lptr = (T*)(gptr); - _has_value = true; - } - } - - /** - * Conctructor, creates an GlobRefAsync object referencing an element in - * global memory. - */ - template - GlobAsyncRef( + template + explicit GlobAsyncRef( /// Pointer to referenced object in global memory - GlobPtr & gptr) + GlobPtr & gptr) : _gptr(gptr.dart_gptr()) { _is_local = gptr.is_local(); @@ -137,9 +104,7 @@ class GlobAsyncRef * Conctructor, creates an GlobRefAsync object referencing an element in * global memory. */ - GlobAsyncRef( - /// Instance of GlobStaticMem that issued this global reference - GlobMem_t * globmem, + explicit GlobAsyncRef( /// Pointer to referenced object in global memory dart_gptr_t dart_gptr) : _gptr(dart_gptr) @@ -154,40 +119,21 @@ class GlobAsyncRef } /** - * Conctructor, creates an GlobRefAsync object referencing an element in - * global memory. + * Constructor, creates an GlobRef object referencing an element in global + * memory. */ - GlobAsyncRef( + template + explicit GlobAsyncRef( /// Pointer to referenced object in global memory - dart_gptr_t dart_gptr) - : _gptr(dart_gptr) - { - GlobConstPtr gptr(dart_gptr); - _is_local = gptr.is_local(); - if (_is_local) { - _value = *gptr; - _lptr = (T*)(gptr); - _has_value = true; - } - } - - /** - * Conctructor, creates an GlobRefAsync object referencing an element in - * global memory. - */ - GlobAsyncRef( - /// Instance of GlobStaticMem that issued this global reference - GlobMem_t * globmem, - /// Pointer to referenced object in global memory - GlobRef & gref) - : GlobAsyncRef(globmem, gref.gptr()) + const GlobConstPtr & gptr) + : GlobAsyncRef(gptr.dart_gptr()) { } /** * Conctructor, creates an GlobRefAsync object referencing an element in * global memory. */ - GlobAsyncRef( + explicit GlobAsyncRef( /// Pointer to referenced object in global memory GlobRef & gref) : GlobAsyncRef(gref.dart_gptr()) diff --git a/dash/include/dash/GlobPtr.h b/dash/include/dash/GlobPtr.h index 7b407f632..86b83e9aa 100644 --- a/dash/include/dash/GlobPtr.h +++ b/dash/include/dash/GlobPtr.h @@ -85,9 +85,14 @@ class GlobPtr }; private: + // Raw global pointer used to initialize this pointer instance dart_gptr_t _rbegin_gptr = DART_GPTR_NULL; + // Memory space refernced by this global pointer const MemorySpace * _mem_space = nullptr; - index_type _rindex = 0; + // Size of the local section at the current position of this pointer + index_type _lsize = 0; + // Unit id of last unit in referenced global memory space + dart_team_unit_t _unit_end = 0; public: template @@ -105,14 +110,24 @@ class GlobPtr * Allows to instantiate GlobPtr without a valid memory * space reference. */ - constexpr GlobPtr( + GlobPtr( const MemorySpace * mem_space, - dart_gptr_t gptr, - index_type rindex = 0) + dart_gptr_t gptr, + index_type rindex = 0) : _rbegin_gptr(gptr) , _mem_space(reinterpret_cast(mem_space)) - , _rindex(rindex) - { } + , _lsize( + mem_space == nullptr + ? 0 + : mem_space->local_size(dart_team_unit_t { gptr.unitid })) + , _unit_end( + mem_space == nullptr + ? mem_space->team().size() + : gptr.unitid) + { + if (rindex < 0) { decrement(-rindex); } + if (rindex > 0) { increment(rindex); } + } public: /** @@ -123,35 +138,39 @@ class GlobPtr /** * Constructor, specifies underlying global address. */ - constexpr GlobPtr( + GlobPtr( const MemorySpace & mem_space, dart_gptr_t gptr) : _rbegin_gptr(gptr) , _mem_space(reinterpret_cast(&mem_space)) + , _lsize(mem_space.local_size(dart_team_unit_t { gptr.unitid })) + , _unit_end(mem_space.team().size()) { } /** * Constructor, specifies underlying global address. */ - constexpr GlobPtr( + GlobPtr( MemorySpace && mem_space, dart_gptr_t gptr) : _rbegin_gptr(gptr) , _mem_space(nullptr) + , _lsize(mem_space.local_size(dart_team_unit_t { gptr.unitid })) + , _unit_end(mem_space.team().size()) { + // No need to bind temporary as value type member: + // The memory space instance can only be passed as temporary if + // it is not the owner of its referenced memory range. // For a use case, see dash::memalloc in dash/memory/GlobUnitMem.h. - // No need to bind temporary, the pointer instance would be rather - // heavy-weight with memory space as a member. - - // TODO: save local size as _lsize = _mem_space.local_size() and - // restrict this pointer's iteration range to the owner of - // _mem_space, the temporary can then be safely destroyed. + // + // We could introduce `GlobSharedPtr` which could act as owners of + // their referenced resource, corresponding to `std::shared_ptr`. } /** * Constructor for conversion of std::nullptr_t. */ - explicit constexpr GlobPtr(std::nullptr_t p) + explicit constexpr GlobPtr(std::nullptr_t) : _rbegin_gptr(DART_GPTR_NULL) , _mem_space(nullptr) { } @@ -168,6 +187,8 @@ class GlobPtr constexpr GlobPtr(const GlobPtr & other) : _rbegin_gptr(other._rbegin_gptr) , _mem_space(reinterpret_cast(other._mem_space)) + , _lsize(other._lsize) + , _unit_end(other._unit_end) { } /** @@ -182,7 +203,9 @@ class GlobPtr self_t & operator=(const GlobPtr & other) { _rbegin_gptr = other._rbegin_gptr; - _mem_space = reinterpret_cast(other._mem_space); + _mem_space = reinterpret_cast(other._mem_space); + _lsize = other._lsize; + _unit_end = other._unit_end; return *this; } @@ -235,7 +258,7 @@ class GlobPtr */ self_t & operator++() { - ++_rindex; + increment(1); return *this; } @@ -244,9 +267,9 @@ class GlobPtr */ self_t operator++(int) { - self_t result = *this; - ++_rindex; - return result; + self_t res = *this; + increment(1); + return res; } /** @@ -254,19 +277,18 @@ class GlobPtr */ self_t operator+(gptrdiff_t n) const { - return self_t(*_mem_space, _rbegin_gptr, _rindex + n); + self_t res = *this; + res += n; + return res; } /** * Pointer increment operator. */ - self_t operator+=(gptrdiff_t n) + self_t & operator+=(gptrdiff_t n) { - self_t result = *this; - DASH_ASSERT_RETURNS( - dart_gptr_incaddr(&_rbegin_gptr, n * sizeof(ElementType)), - DART_OK); - return result; + increment(n); + return *this; } /** @@ -274,9 +296,7 @@ class GlobPtr */ self_t & operator--() { - DASH_ASSERT_RETURNS( - dart_gptr_incaddr(&_rbegin_gptr, -sizeof(ElementType)), - DART_OK); + decrement(1); return *this; } @@ -285,23 +305,22 @@ class GlobPtr */ self_t operator--(int) { - self_t result = *this; - DASH_ASSERT_RETURNS( - dart_gptr_incaddr(&_rbegin_gptr, -sizeof(ElementType)), - DART_OK); - return result; + self_t res = *this; + decrement(1); + return res; } /** - * Pointer distance operator. - * - * \note - * Distance between two global pointers is not well-defined, yet. - * This method is only provided to comply to the pointer concept. + * Pointer offset difference operator. */ constexpr index_type operator-(const self_t & rhs) const noexcept { - return _rbegin_gptr - rhs._rbegin_gptr; + return ( _rbegin_gptr.unitid == rhs._rbegin_gptr.unitid || + _mem_space == nullptr + ? ( _rbegin_gptr.addr_or_offs.offset + - rhs._rbegin_gptr.addr_or_offs.offset ) + / sizeof(value_type) + : _mem_space->distance(rhs, *this) ); } /** @@ -309,23 +328,18 @@ class GlobPtr */ self_t operator-(index_type n) const { - dart_gptr_t gptr = _rbegin_gptr; - DASH_ASSERT_RETURNS( - dart_gptr_incaddr(&gptr, -(n * sizeof(ElementType))), - DART_OK); - return self_t(*_mem_space, gptr); + self_t res = *this; + res -= n; + return res; } /** * Pointer decrement operator. */ - self_t operator-=(index_type n) + self_t & operator-=(index_type n) { - self_t result = *this; - DASH_ASSERT_RETURNS( - dart_gptr_incaddr(&_rbegin_gptr, -(n * sizeof(ElementType))), - DART_OK); - return result; + decrement(n); + return *this; } /** @@ -348,134 +362,70 @@ class GlobPtr /** * Less comparison operator. - * - * \note - * Distance between two global pointers is not well-defined, yet. - * This method is only provided to comply to the pointer concept. */ template constexpr bool operator<(const GlobPtrT & other) const noexcept { - return ( - ( _rbegin_gptr.unitid < other._rbegin_gptr.unitid ) - || - ( _rbegin_gptr.unitid == other._rbegin_gptr.unitid - && - ( _rbegin_gptr.segid < other._rbegin_gptr.segid - || - ( _rbegin_gptr.segid == other._rbegin_gptr.segid - && - _rbegin_gptr.addr_or_offs.offset < - other._rbegin_gptr.addr_or_offs.offset ) ) - ) - ); + return (other - *this) > 0; } /** * Less-equal comparison operator. - * - * \note - * Distance between two global pointers is not well-defined, yet. - * This method is only provided to comply to the pointer concept. */ template constexpr bool operator<=(const GlobPtrT & other) const noexcept { - return ( - ( _rbegin_gptr.unitid < other._rbegin_gptr.unitid ) - || - ( _rbegin_gptr.unitid == other._rbegin_gptr.unitid - && - ( _rbegin_gptr.segid < other._rbegin_gptr.segid - || - ( _rbegin_gptr.segid == other._rbegin_gptr.segid - && - _rbegin_gptr.addr_or_offs.offset <= - other._rbegin_gptr.addr_or_offs.offset ) ) - ) - ); + return (other - *this) >= 0; } /** * Greater comparison operator. - * - * \note - * Distance between two global pointers is not well-defined, yet. - * This method is only provided to comply to the pointer concept. */ template constexpr bool operator>(const GlobPtrT & other) const noexcept { - return ( - ( _rbegin_gptr.unitid > other._rbegin_gptr.unitid ) - || - ( _rbegin_gptr.unitid == other._rbegin_gptr.unitid - && - ( _rbegin_gptr.segid > other._rbegin_gptr.segid - || - ( _rbegin_gptr.segid == other._rbegin_gptr.segid - && - _rbegin_gptr.addr_or_offs.offset > - other._rbegin_gptr.addr_or_offs.offset ) ) - ) - ); + return (*this - other) > 0; } /** * Greater-equal comparison operator. - * - * \note - * Distance between two global pointers is not well-defined, yet. - * This method is only provided to comply to the pointer concept. */ template constexpr bool operator>=(const GlobPtrT & other) const noexcept { - return ( - ( _rbegin_gptr.unitid > other._rbegin_gptr.unitid ) - || - ( _rbegin_gptr.unitid == other._rbegin_gptr.unitid - && - ( _rbegin_gptr.segid > other._rbegin_gptr.segid - || - ( _rbegin_gptr.segid == other._rbegin_gptr.segid - && - _rbegin_gptr.addr_or_offs.offset >= - other._rbegin_gptr.addr_or_offs.offset ) ) - ) - ); + return (*this - other) >= 0; } /** * Subscript operator. */ - constexpr GlobRef operator[](gptrdiff_t n) const + constexpr GlobRef operator[](gptrdiff_t n) const { - return GlobRef(self_t((*this) + n)); + return GlobRef(self_t((*this) + n)); } /** * Subscript assignment operator. */ - GlobRef operator[](gptrdiff_t n) + GlobRef operator[](gptrdiff_t n) { - return GlobRef(self_t((*this) + n)); + return GlobRef(self_t((*this) + n)); } /** * Dereference operator. */ - GlobRef operator*() + GlobRef operator*() { - return GlobRef(*this); + return GlobRef(*this); } /** * Dereference operator. */ - constexpr GlobRef operator*() const + constexpr GlobRef operator*() const { - return GlobRef(*this); + return GlobRef(*this); } /** @@ -490,7 +440,7 @@ class GlobPtr DASH_ASSERT_RETURNS( dart_gptr_getaddr(_rbegin_gptr, &addr), DART_OK); - return static_cast(addr); + return static_cast(addr); } /** @@ -505,7 +455,7 @@ class GlobPtr DASH_ASSERT_RETURNS( dart_gptr_getaddr(_rbegin_gptr, &addr), DART_OK); - return static_cast(addr); + return static_cast(addr); } /** @@ -520,7 +470,7 @@ class GlobPtr DASH_ASSERT_RETURNS( dart_gptr_getaddr(_rbegin_gptr, &addr), DART_OK); - return static_cast(addr); + return static_cast(addr); } /** @@ -538,9 +488,57 @@ class GlobPtr */ bool is_local() const { dart_team_unit_t luid; - dart_team_myid(_rbegin_gptr.teamid, &luid); + DASH_ASSERT_RETURNS( + dart_team_myid(_rbegin_gptr.teamid, &luid), + DART_OK); return _rbegin_gptr.unitid == luid.id; } + +private: + void increment(index_type offs) { + // Pointer position still in same unit space: + if (_mem_space == nullptr || + offs + (_rbegin_gptr.addr_or_offs.offset / sizeof(value_type)) + < _lsize) { + _rbegin_gptr.addr_or_offs.offset += (offs * sizeof(value_type)); + return; + } + // Pointer position moved outside unit space: + while (offs + (_rbegin_gptr.addr_or_offs.offset / sizeof(value_type)) + >= _lsize && + _rbegin_gptr.unitid <= _unit_end.id) { + offs -= (_lsize + - (_rbegin_gptr.addr_or_offs.offset / sizeof(value_type))); + _rbegin_gptr.unitid++; + _rbegin_gptr.addr_or_offs.offset = 0; + _lsize = ( _rbegin_gptr.unitid < _unit_end.id + ? _mem_space->local_size( + dart_team_unit_t { _rbegin_gptr.unitid }) + : 1); + } + _rbegin_gptr.addr_or_offs.offset = (offs * sizeof(value_type)); + } + + void decrement(index_type offs) { + if (_mem_space == nullptr || + (_rbegin_gptr.addr_or_offs.offset / sizeof(value_type)) >= offs) { + _rbegin_gptr.addr_or_offs.offset -= (offs * sizeof(value_type)); + return; + } + // Pointer position moved outside unit space: + while ((_rbegin_gptr.addr_or_offs.offset / sizeof(value_type)) < offs && + _rbegin_gptr.unitid > 0) { + offs -= (_rbegin_gptr.addr_or_offs.offset / sizeof(value_type)) - 1; + _rbegin_gptr.unitid--; + _lsize = ( _rbegin_gptr.unitid < _unit_end.id + ? _mem_space->local_size( + dart_team_unit_t { _rbegin_gptr.unitid }) + : 1); + _rbegin_gptr.addr_or_offs.offset = (_lsize - 1) * sizeof(value_type); + } + _rbegin_gptr.addr_or_offs.offset = (offs * sizeof(value_type)); + } + }; template @@ -552,12 +550,14 @@ std::ostream & operator<<( char buf[100]; sprintf(buf, "u%06X|f%02X|s%04X|t%04X|o%016lX", - gptr._dart_gptr.unitid, - gptr._dart_gptr.flags, - gptr._dart_gptr.segid, - gptr._dart_gptr.teamid, - gptr._dart_gptr.addr_or_offs.offset); - ss << "dash::GlobPtr<" << typeid(T).name() << ">(" << buf << ")"; + gptr._rbegin_gptr.unitid, + gptr._rbegin_gptr.flags, + gptr._rbegin_gptr.segid, + gptr._rbegin_gptr.teamid, + gptr._rbegin_gptr.addr_or_offs.offset); + ss << "dash::GlobPtr<" << typeid(T).name() << ">(" + << "nloc:" << gptr._lsize << " " + << "uend:" << gptr._unit_end << " " << buf << ")"; return operator<<(os, ss.str()); } diff --git a/dash/include/dash/GlobRef.h b/dash/include/dash/GlobRef.h index 4cbfd9dd6..4cb166494 100644 --- a/dash/include/dash/GlobRef.h +++ b/dash/include/dash/GlobRef.h @@ -10,21 +10,8 @@ namespace dash { // Forward declarations template class GlobStaticMem; -template class GlobConstPtr; template class GlobPtr; -#if 0 -template -void put_value(const T & newval, const GlobConstPtr & gptr); -template -void put_value(const T & newval, const GlobPtr & gptr); - -template -void get_value(T* ptr, const GlobConstPtr & gptr); -template -void get_value(T* ptr, const GlobPtr & gptr); -#endif - template struct has_subscript_operator { diff --git a/dash/include/dash/memory/GlobHeapMem.h b/dash/include/dash/memory/GlobHeapMem.h index 3caf9303c..128f6d22e 100644 --- a/dash/include/dash/memory/GlobHeapMem.h +++ b/dash/include/dash/memory/GlobHeapMem.h @@ -429,6 +429,23 @@ class GlobHeapMem return unit_local_size; } + index_type distance(const pointer & gbegin, const pointer & gend) const { + if (gbegin.dart_gptr().unitid > gend.dart_gptr().unitid) { + return -(distance(gend, gbegin)); + } + index_type dist = local_size( + dart_team_unit_t { gbegin.dart_gptr().unitid }) + - (gbegin.dart_gptr().addr_or_offs.offset + / sizeof(value_type)) + + (gend.dart_gptr().addr_or_offs.offset + / sizeof(value_type)); + for (int u = gbegin.dart_gptr().unitid+1; + u < gend.dart_gptr().unitid; ++u) { + dist += local_size(dart_team_unit_t { u }); + } + return dist; + } + /** * The team containing all units accessing the global memory space. * diff --git a/dash/include/dash/memory/GlobStaticMem.h b/dash/include/dash/memory/GlobStaticMem.h index 09553c8df..f3c769b53 100644 --- a/dash/include/dash/memory/GlobStaticMem.h +++ b/dash/include/dash/memory/GlobStaticMem.h @@ -91,17 +91,11 @@ class GlobStaticMem typedef typename allocator_type::difference_type difference_type; typedef typename allocator_type::difference_type index_type; -#if 0 - typedef typename allocator_type::pointer pointer; - typedef typename allocator_type::const_pointer const_pointer; - typedef typename allocator_type::void_pointer void_pointer; - typedef typename allocator_type::const_void_pointer const_void_pointer; -#else typedef GlobPtr< value_type, self_t> pointer; typedef GlobPtr const_pointer; typedef GlobPtr< void, self_t> void_pointer; typedef GlobPtr const_void_pointer; -#endif + typedef value_type * local_pointer; typedef const value_type * const_local_pointer; @@ -294,6 +288,23 @@ class GlobStaticMem return _nlelem; } + index_type distance(const pointer & gbegin, const pointer & gend) const { + if (gbegin.dart_gptr().unitid > gend.dart_gptr().unitid) { + return -(distance(gend, gbegin)); + } + index_type dist = local_size( + dart_team_unit_t { gbegin.dart_gptr().unitid }) + - (gbegin.dart_gptr().addr_or_offs.offset + / sizeof(value_type)) + + (gend.dart_gptr().addr_or_offs.offset + / sizeof(value_type)); + for (int u = gbegin.dart_gptr().unitid+1; + u < gend.dart_gptr().unitid; ++u) { + dist += local_size(dart_team_unit_t { u }); + } + return dist; + } + /** * The team containing all units accessing the global memory space. * diff --git a/dash/include/dash/memory/GlobUnitMem.h b/dash/include/dash/memory/GlobUnitMem.h index ff448436c..b8ff9f94d 100644 --- a/dash/include/dash/memory/GlobUnitMem.h +++ b/dash/include/dash/memory/GlobUnitMem.h @@ -240,6 +240,13 @@ class GlobUnitMem return _nlelem; } + constexpr index_type distance( + const pointer & gbegin, + const pointer & gend) const { + return ( gend.addr_or_offs.offset - gbegin.addr_or_offs.offset ) + / sizeof(value_type); + } + /** * The team containing all units accessing the global memory space. * diff --git a/dash/include/dash/memory/MemorySpace.h b/dash/include/dash/memory/MemorySpace.h new file mode 100644 index 000000000..2d9dc35f4 --- /dev/null +++ b/dash/include/dash/memory/MemorySpace.h @@ -0,0 +1,18 @@ +#ifndef DASH__MEMORY__MEMORY_SPACE_H__INCLUDED +#define DASH__MEMORY__MEMORY_SPACE_H__INCLUDED + +#include +#include + + +namespace dash { + +template +struct pointer_traits { + +}; + + +} // namespace dash + +#endif // DASH__MEMORY__MEMORY_SPACE_H__INCLUDED diff --git a/dash/test/memory/GlobStaticMemTest.cc b/dash/test/memory/GlobStaticMemTest.cc index c426cc03b..6bd9a408c 100644 --- a/dash/test/memory/GlobStaticMemTest.cc +++ b/dash/test/memory/GlobStaticMemTest.cc @@ -30,6 +30,65 @@ TEST_F(GlobStaticMemTest, ConstructorInitializerList) } } +TEST_F(GlobStaticMemTest, GlobalRandomAccess) +{ + auto globmem_local_elements = { 1, 2, 3 }; + auto globmem = dash::GlobStaticMem(globmem_local_elements); + + DASH_LOG_DEBUG_VAR("GlobStaticMemTest", globmem.size()); + EXPECT_EQ_U(globmem.size(), 3 * dash::size()); + + if (dash::myid() == 0) { + auto gbegin = globmem.begin(); + auto glast = gbegin + (globmem.size() - 1); + auto gend = gbegin + globmem.size(); + + DASH_LOG_DEBUG_VAR("GlobStaticMemTest", gbegin); + DASH_LOG_DEBUG_VAR("GlobStaticMemTest", glast); + DASH_LOG_DEBUG_VAR("GlobStaticMemTest", gend); + + // Test distance in global memory over multiple unit spaces: + EXPECT_EQ(gend - gbegin, globmem.size()); + EXPECT_EQ(glast - gbegin, globmem.size() - 1); + + // Iterate entire global memory space, including end pointer: + for (int g = 0; g <= globmem.size(); ++g) { + DASH_LOG_DEBUG_VAR("GlobStaticMemTest", gbegin); + // Do not dereference end pointer: + if (g < globmem.size()) { + int gvalue = *gbegin; + EXPECT_EQ((g % 3) + 1, gvalue); + } + + if (g % 2 == 0) { ++gbegin; } + else { gbegin++; } + EXPECT_EQ( gbegin, globmem.begin() + g + 1); + EXPECT_EQ(*gbegin, globmem.begin()[g+1]); + } + } + + dash::barrier(); + + if (dash::myid() == dash::size() - 1) { + auto gbegin = globmem.begin(); + auto gend = gbegin + globmem.size(); + // Reverse iteratation on entire global memory space, starting at + // end pointer: + for (int g = globmem.size(); g >= 0; --g) { + DASH_LOG_DEBUG_VAR("GlobStaticMemTest", gend); + // Do not dereference end pointer: + if (g < globmem.size()) { + int gvalue = *gend; + EXPECT_EQ((g % 3) + 1, gvalue); + } + + if (g % 2 == 0) { --gend; } + else { gend--; } + EXPECT_EQ(gend, globmem.begin() + g - 1); + } + } +} + TEST_F(GlobStaticMemTest, LocalBegin) { auto target_local_elements = { 1, 2, 3, 4 };