diff --git a/dart-impl/mpi/src/dart_communication.c b/dart-impl/mpi/src/dart_communication.c index ef5d4032e..944a0664d 100644 --- a/dart-impl/mpi/src/dart_communication.c +++ b/dart-impl/mpi/src/dart_communication.c @@ -190,7 +190,7 @@ dart_ret_t dart_get( dart_segment_info_t *seginfo = dart_segment_get_info( &(team_data->segdata), seg_id); if (dart__unlikely(seginfo == NULL)) { - DART_LOG_ERROR("dart_get_blocking ! " + DART_LOG_ERROR("dart_get ! " "Unknown segment %i on team %i", seg_id, teamid); return DART_ERR_INVAL; } @@ -199,7 +199,7 @@ dart_ret_t dart_get( // use direct memcpy if we are on the same unit memcpy(dest, seginfo->selfbaseptr + offset, nelem * dart__mpi__datatype_sizeof(dtype)); - DART_LOG_DEBUG("dart_get_blocking: memcpy nelem:%zu " + DART_LOG_DEBUG("dart_get: memcpy nelem:%zu " "source (coll.): offset:%lu -> dest: %p", nelem, offset, dest); return DART_OK; @@ -286,7 +286,7 @@ dart_ret_t dart_put( dart_segment_info_t *seginfo = dart_segment_get_info( &(team_data->segdata), seg_id); if (dart__unlikely(seginfo == NULL)) { - DART_LOG_ERROR("dart_get_blocking ! " + DART_LOG_ERROR("dart_put ! " "Unknown segment %i on team %i", seg_id, teamid); return DART_ERR_INVAL; } @@ -307,7 +307,7 @@ dart_ret_t dart_put( team_unit_id, nelem, dtype); } #else - DART_LOG_DEBUG("dart_get_blocking: shared windows disabled"); + DART_LOG_DEBUG("dart_put: shared windows disabled"); #endif /* !defined(DART_MPI_DISABLE_SHARED_WINDOWS) */ // source on another node or shared memory windows disabled @@ -384,7 +384,7 @@ dart_ret_t dart_accumulate( dart_segment_info_t *seginfo = dart_segment_get_info( &(team_data->segdata), seg_id); if (dart__unlikely(seginfo == NULL)) { - DART_LOG_ERROR("dart_get_blocking ! " + DART_LOG_ERROR("dart_accumulate ! " "Unknown segment %i on team %i", seg_id, teamid); return DART_ERR_INVAL; } @@ -528,7 +528,7 @@ dart_ret_t dart_compare_and_swap( dart_segment_info_t *seginfo = dart_segment_get_info( &(team_data->segdata), seg_id); if (dart__unlikely(seginfo == NULL)) { - DART_LOG_ERROR("dart_get_blocking ! " + DART_LOG_ERROR("dart_compare_and_swap ! " "Unknown segment %i on team %i", seg_id, teamid); return DART_ERR_INVAL; } @@ -578,7 +578,7 @@ dart_ret_t dart_get_handle( dart_segment_info_t *seginfo = dart_segment_get_info( &(team_data->segdata), seg_id); if (dart__unlikely(seginfo == NULL)) { - DART_LOG_ERROR("dart_get_blocking ! " + DART_LOG_ERROR("dart_get_handle ! " "Unknown segment %i on team %i", seg_id, teamid); return DART_ERR_INVAL; } @@ -619,7 +619,7 @@ dart_ret_t dart_get_handle( handle->needs_flush = false; if (nchunks > 0) { - DART_LOG_TRACE("dart_get_blocking: MPI_Rget (dest %p, size %zu)", + DART_LOG_TRACE("dart_get_handle: MPI_Rget (dest %p, size %zu)", dest_ptr, nchunks * MAX_CONTIG_ELEMENTS); if (MPI_Rget(dest_ptr, nchunks, @@ -631,7 +631,7 @@ dart_ret_t dart_get_handle( win, &handle->reqs[handle->num_reqs++]) != MPI_SUCCESS) { free(handle); - DART_LOG_ERROR("dart_get_blocking ! MPI_Rget failed"); + DART_LOG_ERROR("dart_get_handle ! MPI_Rget failed"); return DART_ERR_INVAL; } offset += nchunks * MAX_CONTIG_ELEMENTS; @@ -641,7 +641,7 @@ dart_ret_t dart_get_handle( if (remainder > 0) { MPI_Datatype mpi_dtype = dart__mpi__datatype(dtype); DART_LOG_TRACE( - "dart_get_blocking: MPI_Rget (dest %p, size %zu)", dest_ptr, remainder); + "dart_get_handle: MPI_Rget (dest %p, size %zu)", dest_ptr, remainder); if (MPI_Rget(dest_ptr, remainder, mpi_dtype, @@ -652,7 +652,7 @@ dart_ret_t dart_get_handle( win, &handle->reqs[handle->num_reqs++]) != MPI_SUCCESS) { free(handle); - DART_LOG_ERROR("dart_get_blocking ! MPI_Rget failed"); + DART_LOG_ERROR("dart_get_handle ! MPI_Rget failed"); return DART_ERR_INVAL; } } @@ -690,7 +690,7 @@ dart_ret_t dart_put_handle( dart_segment_info_t *seginfo = dart_segment_get_info( &(team_data->segdata), seg_id); if (dart__unlikely(seginfo == NULL)) { - DART_LOG_ERROR("dart_get_blocking ! " + DART_LOG_ERROR("dart_put_handle ! " "Unknown segment %i on team %i", seg_id, teamid); return DART_ERR_INVAL; } @@ -741,7 +741,7 @@ dart_ret_t dart_put_handle( win, &handle->reqs[handle->num_reqs++]) != MPI_SUCCESS) { free(handle); - DART_LOG_ERROR("dart_get ! MPI_Put failed"); + DART_LOG_ERROR("dart_put_handle ! MPI_Put failed"); return DART_ERR_INVAL; } } @@ -779,7 +779,7 @@ dart_ret_t dart_put_blocking( dart_segment_info_t *seginfo = dart_segment_get_info( &(team_data->segdata), seg_id); if (dart__unlikely(seginfo == NULL)) { - DART_LOG_ERROR("dart_get_blocking ! " + DART_LOG_ERROR("dart_put_blocking ! " "Unknown segment %i on team %i", seg_id, teamid); return DART_ERR_INVAL; } @@ -792,7 +792,7 @@ dart_ret_t dart_put_blocking( if (team_unit_id.id == team_data->unitid) { memcpy(seginfo->selfbaseptr + offset, src, nelem * dart__mpi__datatype_sizeof(dtype)); - DART_LOG_DEBUG("dart_put: memcpy nelem:%zu (from global allocation)" + DART_LOG_DEBUG("dart_put_blocking: memcpy nelem:%zu (from global allocation)" "offset: %"PRIu64"", nelem, offset); return DART_OK; } @@ -804,7 +804,7 @@ dart_ret_t dart_put_blocking( team_unit_id, nelem, dtype); } #else - DART_LOG_DEBUG("dart_get_blocking: shared windows disabled"); + DART_LOG_DEBUG("dart_put_blocking: shared windows disabled"); #endif /* !defined(DART_MPI_DISABLE_SHARED_WINDOWS) */ MPI_Win win = seginfo->win; @@ -929,7 +929,7 @@ dart_ret_t dart_get_blocking( const size_t nchunks = nelem / MAX_CONTIG_ELEMENTS; const size_t remainder = nelem % MAX_CONTIG_ELEMENTS; char * dest_ptr = (char*) dest; - MPI_Request reqs[2]; + MPI_Request reqs[2] = {MPI_REQUEST_NULL, MPI_REQUEST_NULL}; int nreqs = 0; if (nchunks > 0) { diff --git a/dash/include/dash/Array.h b/dash/include/dash/Array.h index 0f5e45151..1c9813ca9 100644 --- a/dash/include/dash/Array.h +++ b/dash/include/dash/Array.h @@ -384,40 +384,33 @@ class AsyncArrayRef _array->m_globmem->flush(); } - inline void flush_local() const { - // could also call _array->flush_local(); - _array->m_globmem->flush_local(); - } - - inline void flush_all() const { + /** + * Complete all outstanding asynchronous operations on the referenced array + * to the specified unit. + */ + inline void flush(dash::team_unit_t target) const { // could also call _array->flush(); - _array->m_globmem->flush_all(); - } - - inline void flush_local_all() const { - // could also call _array->flush_local_all(); - _array->m_globmem->flush_local_all(); + _array->m_globmem->flush(target); } /** - * Block until all locally invoked operations on global memory have been - * communicated. - * - * \see DashAsyncProxyConcept + * Locally complete all outstanding asynchronous operations on the referenced array + * on all units. */ - inline void push() const { - _array->m_globmem->flush_local_all(); + inline void flush_local() const { + // could also call _array->flush_local(); + _array->m_globmem->flush_local(); } /** - * Block until all remote operations on this unit's local memory have been - * completed. - * - * \see DashAsyncProxyConcept + * Locally complete all outstanding asynchronous operations on the referenced array + * to the specified unit. */ - inline void fetch() const { - _array->m_globmem->flush_all(); + inline void flush_local(dash::team_unit_t target) const { + // could also call _array->flush_local(); + _array->m_globmem->flush_local(target); } + }; #endif // DOXYGEN @@ -894,7 +887,7 @@ class Array * \code * dash::Array a1(1024 * dash::size()); * dash::fill(a1.begin(), a1.end(), 123); - * + * * // create copy of array a1: * dash::Array a2(a1.size()); * dash::copy(a1.begin(), a1.end(), a2.begin()); @@ -923,7 +916,7 @@ class Array * \code * dash::Array a1(1024 * dash::size()); * dash::fill(a1.begin(), a1.end(), 123); - * + * * // create copy of array a1: * dash::Array a2(a1.size()); * dash::copy(a1.begin(), a1.end(), a2.begin()); @@ -1193,7 +1186,7 @@ class Array { DASH_LOG_TRACE_VAR("Array.barrier()", m_team); if (nullptr != m_globmem) { - m_globmem->flush_all(); + m_globmem->flush(); } if (nullptr != m_team && *m_team != dash::Team::Null()) { m_team->barrier(); @@ -1202,7 +1195,7 @@ class Array } /** - * Complete all outstanding non-blocking operations executed by all units + * Complete all outstanding non-blocking operations to all units * on the array's underlying global memory. */ inline void flush() const { @@ -1210,27 +1203,28 @@ class Array } /** - * Complete all outstanding non-blocking operations executed by the - * local unit on the array's underlying global memory. + * Complete all outstanding non-blocking operations to the specified unit + * on the array's underlying global memory. */ - inline void flush_local() const { - m_globmem->flush_local(); + inline void flush(dash::team_unit_t target) const { + m_globmem->flush(target); } /** - * Complete all outstanding non-blocking operations executed by all units - * on the array's underlying global memory. + * Locally complete all outstanding non-blocking operations to all units on + * the array's underlying global memory. */ - inline void flush_all() const { - m_globmem->flush_all(); + inline void flush_local() const { + m_globmem->flush_local(); } + /** - * Complete all outstanding non-blocking operations executed by the - * local unit on the array's underlying global memory. + * Locally complete all outstanding non-blocking operations to the + * specified unit on the array's underlying global memory. */ - inline void flush_local_all() const { - m_globmem->flush_local_all(); + inline void flush_local(dash::team_unit_t target) const { + m_globmem->flush_local(target); } /** diff --git a/dash/include/dash/GlobAsyncRef.h b/dash/include/dash/GlobAsyncRef.h index b21fe168c..e56325750 100644 --- a/dash/include/dash/GlobAsyncRef.h +++ b/dash/include/dash/GlobAsyncRef.h @@ -18,20 +18,17 @@ namespace dash { * GlobAsyncRef gar1 = array.async[1]; * gar0 = 123; * gar1 = 456; - * // Changes are is visible locally but not published to other - * // units, yet: - * assert(gar0 == 123); - * assert(gar1 == 456); - * assert(array[0] == 123); - * assert(array[1] == 456); - * assert(array.local[0] == 123); - * assert(array.local[1] == 456); + * // Changes are not guaranteed to be visible locally + * int val = array.async[0].get(); // might yield the old value + * // Values can be read asynchronously, which will not block. + * // Instead, the value will be available after `flush()`. + * array.async[0].get(&val); * // Changes can be published (committed) directly using a GlobAsyncRef * // object: * gar0.flush(); * // New value of array[0] is published to all units, array[1] is not * // committed yet - * // Changes on a container can be publiched in bulk: + * // Changes on a container can be published in bulk: * array.flush(); * // From here, all changes are published * \endcode @@ -60,15 +57,11 @@ class GlobAsyncRef private: /// Pointer to referenced element in global memory - dart_gptr_t _gptr = DART_GPTR_NULL; - /// Pointer to referenced element in local memory - T * _lptr = nullptr; - /// Value of the referenced element, initially not loaded - mutable nonconst_value_type _value; - /// Whether the referenced element is located local memory - bool _is_local = false; - /// Whether the value of the referenced element is known - mutable bool _has_value = false; + dart_gptr_t _gptr; + /// Temporary value required for non-blocking put + nonconst_value_type _value; + /// DART handle for asynchronous transfers + dart_handle_t _handle = DART_HANDLE_NULL; private: @@ -82,15 +75,7 @@ class GlobAsyncRef const GlobAsyncRef & parent, /// offset of member in struct size_t offset) - : _gptr(parent._gptr), - _lptr(parent._is_local ? reinterpret_cast( - reinterpret_cast(parent._lptr)+offset) - : nullptr), - _value(parent._has_value ? *(reinterpret_cast( - reinterpret_cast(&(parent._value))+offset)) - : T()), - _is_local(parent._is_local), - _has_value(parent._has_value) + : _gptr(parent._gptr) { DASH_ASSERT_RETURNS( dart_gptr_incaddr(&_gptr, offset), @@ -98,19 +83,6 @@ class GlobAsyncRef } public: - /** - * Conctructor, creates an GlobRefAsync object referencing an element in - * local memory. - */ - explicit constexpr GlobAsyncRef( - /// Pointer to referenced object in local memory - nonconst_value_type * lptr) - : _lptr(lptr), - _value(*lptr), - _is_local(true), - _has_value(true) - { } - /** * Conctructor, creates an GlobRefAsync object referencing an element in * global memory. @@ -120,12 +92,7 @@ class GlobAsyncRef /// Pointer to referenced object in global memory GlobPtr & gptr) : _gptr(gptr.dart_gptr()) - { - _is_local = gptr.is_local(); - if (_is_local) { - _lptr = (T*)(gptr); - } - } + { } /** * Conctructor, creates an GlobRefAsync object referencing an element in @@ -135,13 +102,7 @@ class 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) { - _lptr = (T*)(gptr); - } - } + { } /** * Constructor, creates an GlobRef object referencing an element in global @@ -172,6 +133,12 @@ class GlobAsyncRef */ GlobAsyncRef(const self_t & other) = delete; + ~GlobAsyncRef() { + if (_handle != DART_HANDLE_NULL) { + dart_wait_local(&_handle); + } + } + /** * Unlike native reference types, global reference types are moveable. */ @@ -182,7 +149,7 @@ class GlobAsyncRef */ inline bool is_local() const noexcept { - return _is_local; + return dash::internal::is_local(this->_gptr); } /** @@ -205,86 +172,27 @@ class GlobAsyncRef } /** - * Conversion operator to referenced element value. - */ - operator nonconst_value_type() const - { - DASH_LOG_TRACE_VAR("GlobAsyncRef.T()", _gptr); - if (!_has_value) { - if (_is_local) { - _value = *_lptr; - } else { - dash::dart_storage ds(1); - DASH_ASSERT_RETURNS( - dart_get_blocking( - static_cast(&_value), _gptr, ds.nelem, ds.dtype), - DART_OK - ); - } - _has_value = true; - } - return _value; - } - - /** - * Comparison operator, true if both GlobAsyncRef objects points to same - * element in local / global memory. - */ - bool operator==(const self_t & other) const noexcept - { - return (_lptr == other._lptr && - _gptr == other._gptr); - } - - /** - * Inequality comparison operator, true if both GlobAsyncRef objects points - * to different elements in local / global memory. - */ - template - constexpr bool operator!=(const GlobRefT & other) const noexcept - { - return !(*this == other); - } - - /** - * Value-based comparison operator, true if the value refernced by the - * GlobAsyncRef object is equal to \c value. - */ - constexpr bool operator==(const_value_type & value) const - { - return static_cast(*this) == value; - } - - /** - * Value-based inequality comparison operator, true if the value refernced - * by the GlobAsyncRef object is not equal to \c value. + * Swap values with synchronous reads and asynchronous writes. */ - constexpr bool operator!=(const nonconst_value_type & value) const - { - return !(*this == value); - } - - friend void swap(GlobAsyncRef a, GlobAsyncRef b) { - nonconst_value_type temp = static_cast(a); - a = b; + friend void swap(self_t & a, self_t & b) { + nonconst_value_type temp = a->get(); + a = b->get(); b = temp; } - - /** - * Set the value referenced by this \c GlobAsyncRef to \c val. - * - * \see operator= - */ - void set(const_value_type & val) { - operator=(val); - } - /** * Return the value referenced by this \c GlobAsyncRef. + * This operation will block until the value has been transfered. */ nonconst_value_type get() const { - return operator nonconst_value_type(); + nonconst_value_type value; + DASH_LOG_TRACE_VAR("GlobAsyncRef.T()", _gptr); + dash::dart_storage ds(1); + DASH_ASSERT_RETURNS( + dart_get_blocking(static_cast(&value), _gptr, ds.nelem, ds.dtype), + DART_OK + ); + return value; } /** @@ -294,16 +202,15 @@ class GlobAsyncRef * at which point the referenced value can be used. */ void get(nonconst_value_type *tptr) const { - if (_is_local) { - *tptr = *_lptr; - } else { - dash::dart_storage ds(1); - dart_get(static_cast(tptr), _gptr, ds.nelem, ds.dtype); - } + dash::dart_storage ds(1); + DASH_ASSERT_RETURNS( + dart_get(static_cast(tptr), _gptr, ds.nelem, ds.dtype), + DART_OK + ); } /** - * Asynchronously write the value referenced by this \c GlobAsyncRef + * Asynchronously write the value referenced by this \c GlobAsyncRef * into \c tref. * This operation is guaranteed to be complete after a call to \ref flush, * at which point the referenced value can be used. @@ -315,203 +222,72 @@ class GlobAsyncRef /** * Asynchronously set the value referenced by this \c GlobAsyncRef * to the value pointed to by \c tptr. - * This operation is guaranteed to be complete after a call to \ref flush, - * but the pointer \c tptr can be re-used immediately. + * This operation is guaranteed to be complete after a call to \ref flush + * and the pointer \c tptr should not be reused before completion. */ - void put(const_value_type* tptr) { - operator=(*tptr); + void set(const_value_type* tptr) { + DASH_LOG_TRACE_VAR("GlobAsyncRef.set()", *tptr); + DASH_LOG_TRACE_VAR("GlobAsyncRef.set()", _gptr); + dash::dart_storage ds(1); + DASH_ASSERT_RETURNS( + dart_put(_gptr, static_cast(tptr), ds.nelem, ds.dtype), + DART_OK + ); } /** * Asynchronously set the value referenced by this \c GlobAsyncRef - * to the value pointed to by \c tref. + * to the value pointed to by \c new_value. * This operation is guaranteed to be complete after a call to \ref flush, - * but the value referenced by \c tref can be re-used immediately. - */ - void put(const_value_type& tref) { - operator=(tref); - } - - /** - * Value assignment operator, sets new value in local memory or calls - * non-blocking put on remote memory. This operator is only used for - * types which are comparable - */ - template - typename std::enable_if::value, self_t & >::type - operator=(const_value_type & new_value) - { - DASH_LOG_TRACE_VAR("GlobAsyncRef.=()", new_value); - DASH_LOG_TRACE_VAR("GlobAsyncRef.=", _gptr); - // TODO: Comparison with current value could be inconsistent - if (!_has_value || _value != new_value) { - _value = new_value; - _has_value = true; - if (_is_local) { - *_lptr = _value; - } else { - dash::dart_storage ds(1); - DASH_ASSERT_RETURNS( - dart_put( - _gptr, static_cast(&_value), ds.nelem, ds.dtype), - DART_OK - ); - } + * but the value referenced by \c new_value can be re-used immediately. + */ + void set(const_value_type& new_value) { + DASH_LOG_TRACE_VAR("GlobAsyncRef.set()", new_value); + DASH_LOG_TRACE_VAR("GlobAsyncRef.set()", _gptr); + dash::dart_storage ds(1); + _value = new_value; + // check that we do not overwrite the handle if it has been used before + if (this->_handle != DART_HANDLE_NULL) { + DASH_ASSERT_RETURNS( + dart_wait_local(&this->_handle), + DART_OK + ); } - return *this; + DASH_ASSERT_RETURNS( + dart_put_handle(_gptr, static_cast(&_value), + ds.nelem, ds.dtype, &_handle), + DART_OK + ); } /** - * Value assignment operator, sets new value in local memory or calls - * non-blocking put on remote memory. This operator is only used for - * types which are not comparable + * Value assignment operator, calls non-blocking put. + * This operation is guaranteed to be complete after a call to \ref flush, + * but the value referenced by \c new_value can be re-used immediately. */ - template - typename std::enable_if::value, self_t & >::type + self_t & operator=(const_value_type & new_value) { - DASH_LOG_TRACE_VAR("GlobAsyncRef.=()", new_value); - DASH_LOG_TRACE_VAR("GlobAsyncRef.=", _gptr); - // TODO: Comparison with current value could be inconsistent - if (!_has_value) { - _value = new_value; - _has_value = true; - if (_is_local) { - *_lptr = _value; - } else { - dash::dart_storage ds(1); - DASH_ASSERT_RETURNS( - dart_put( - _gptr, static_cast(&_value), ds.nelem, ds.dtype), - DART_OK - ); - } - } - return *this; - } - - /** - * Value increment operator. - */ - self_t & operator+=(const_value_type & ref) - { - T val = operator nonconst_value_type(); - val += ref; - operator=(val); - return *this; - } - - /** - * Prefix increment operator. - */ - self_t & operator++() - { - nonconst_value_type val = operator nonconst_value_type(); - ++val; - operator=(val); - return *this; - } - - /** - * Postfix increment operator. - */ - self_t operator++(int) - { - self_t result = *this; - nonconst_value_type val = operator nonconst_value_type(); - ++val; - operator=(val); - return result; - } - - /** - * Value decrement operator. - */ - self_t & operator-=(const_value_type & ref) - { - nonconst_value_type val = operator nonconst_value_type(); - val -= ref; - operator=(val); - return *this; - } - - /** - * Prefix decrement operator. - */ - self_t & operator--() - { - nonconst_value_type val = operator nonconst_value_type(); - --val; - operator=(val); - return *this; - } - - /** - * Postfix decrement operator. - */ - self_t operator--(int) - { - self_t result = *this; - nonconst_value_type val = operator nonconst_value_type(); - --val; - operator=(val); - return result; - } - - - /** - * Multiplication operator. - */ - self_t & operator*=(const_value_type& ref) { - nonconst_value_type val = operator nonconst_value_type(); - val *= ref; - operator=(val); - return *this; - } - - /** - * Division operator. - */ - self_t & operator/=(const_value_type& ref) { - nonconst_value_type val = operator nonconst_value_type(); - val /= ref; - operator=(val); + set(new_value); return *this; } /** - * Binary XOR operator. + * Returns the underlying DART global pointer. */ - self_t & operator^=(const_value_type& ref) { - nonconst_value_type val = operator nonconst_value_type(); - val ^= ref; - operator=(val); - return *this; + dart_gptr_t dart_gptr() const { + return this->_gptr; } /** - * Return the underlying DART pointer. - */ - constexpr dart_gptr_t dart_gptr() const noexcept { - return _gptr; - } - - - /** - * Flush all pending asynchronous operations on this asynchronous reference - * and invalidate cached copies. + * Flush all pending asynchronous operations on this asynchronous reference. */ void flush() { - // perform a flush irregardless of whether the reference is local or not - if (!DART_GPTR_ISNULL(_gptr)) { - DASH_ASSERT_RETURNS( - dart_flush(_gptr), - DART_OK - ); - // require a re-read upon next reference - _has_value = false; - } + DASH_ASSERT_RETURNS( + dart_flush(_gptr), + DART_OK + ); } }; // class GlobAsyncRef @@ -520,11 +296,7 @@ template std::ostream & operator<<( std::ostream & os, const GlobAsyncRef & gar) { - if (gar._is_local) { - os << "dash::GlobAsyncRef(" << gar._lptr << ")"; - } else { - os << "dash::GlobAsyncRef(" << gar._gptr << ")"; - } + os << "dash::GlobAsyncRef(" << gar._gptr << ")"; return os; } diff --git a/dash/include/dash/GlobPtr.h b/dash/include/dash/GlobPtr.h index cc10efa3f..e69612750 100644 --- a/dash/include/dash/GlobPtr.h +++ b/dash/include/dash/GlobPtr.h @@ -29,6 +29,17 @@ bool operator!=( namespace dash { +namespace internal { + static bool is_local(dart_gptr_t gptr) { + dart_team_unit_t luid; + DASH_ASSERT_RETURNS( + dart_team_myid(gptr.teamid, &luid), + DART_OK); + return gptr.unitid == luid.id; + } +} + + // Forward-declarations template class GlobRef; template diff --git a/dash/include/dash/Matrix.h b/dash/include/dash/Matrix.h index d84c8115e..992b09ba6 100644 --- a/dash/include/dash/Matrix.h +++ b/dash/include/dash/Matrix.h @@ -417,30 +417,32 @@ class Matrix inline void barrier() const; /** - * Complete all outstanding non-blocking operations executed by all units - * on the array's underlying global memory. + * Complete all outstanding non-blocking operations to all units + * on the container's underlying global memory. * * \see DashContainerConcept */ inline void flush(); /** - * Complete all outstanding non-blocking operations executed by the - * local unit on the narray's underlying global memory. + * Complete all outstanding non-blocking operations to the specified unit + * on the container's underlying global memory. + * + * \see DashContainerConcept */ - inline void flush_local(); + inline void flush(dash::team_unit_t target); /** - * Complete all outstanding non-blocking operations executed by all units - * on the narray's underlying global memory. + * Locally complete all outstanding non-blocking operations to all units + * on the container's underlying global memory. */ - inline void flush_all(); + inline void flush_local(); /** - * Complete all outstanding non-blocking operations executed by the - * local unit on the narray's underlying global memory. + * Locally complete all outstanding non-blocking operations to the specified + * unit on the container's underlying global memory. */ - inline void flush_local_all(); + inline void flush_local(dash::team_unit_t target); /** * The pattern used to distribute matrix elements to units in its @@ -520,7 +522,7 @@ class Matrix constexpr operator[]( size_type n ///< Offset in highest matrix dimension. ) const; - + /** * Subscript operator, returns a \ref GlobRef if matrix has only one dimension */ diff --git a/dash/include/dash/matrix/internal/Matrix-inl.h b/dash/include/dash/matrix/internal/Matrix-inl.h index 2eaf881a8..8d7d4c487 100644 --- a/dash/include/dash/matrix/internal/Matrix-inl.h +++ b/dash/include/dash/matrix/internal/Matrix-inl.h @@ -362,22 +362,22 @@ ::flush() { template inline void Matrix -::flush_local() { - _glob_mem->flush_local(); +::flush(dash::team_unit_t target) { + _glob_mem->flush(target); } template inline void Matrix -::flush_all() { - _glob_mem->flush_all(); +::flush_local() { + _glob_mem->flush_local(); } template inline void Matrix -::flush_local_all() { - _glob_mem->flush_local_all(); +::flush_local(dash::team_unit_t target) { + _glob_mem->flush_local(target); } template diff --git a/dash/include/dash/memory/GlobStaticMem.h b/dash/include/dash/memory/GlobStaticMem.h index 3d3060be2..2d461380b 100644 --- a/dash/include/dash/memory/GlobStaticMem.h +++ b/dash/include/dash/memory/GlobStaticMem.h @@ -254,7 +254,7 @@ class GlobStaticMem /** * Move constructor * - * \TODO make move constructor defaultable by using RAII + * \TODO make move constructor defaultable by using RAII */ GlobStaticMem(self_t && other) : _allocator(std::move(other._allocator)), @@ -284,7 +284,7 @@ class GlobStaticMem /** * Move-assignment operator. * - * \TODO make move constructor defaultable by using RAII + * \TODO make move constructor defaultable by using RAII */ self_t & operator=(self_t && other) { // deallocate old memory @@ -458,39 +458,43 @@ class GlobStaticMem } /** - * Complete all outstanding non-blocking operations executed by all units. + * Complete all outstanding non-blocking operations to all units. */ void flush() noexcept { - dart_flush(_begptr); + dart_flush_all(_begptr); } /** - * Complete all outstanding non-blocking operations executed by all units. + * Complete all outstanding non-blocking operations to the specified unit. */ - void flush_all() noexcept + void flush(dash::team_unit_t target) noexcept { - dart_flush_all(_begptr); + dart_gptr_t gptr = _begptr; + gptr.unitid = target.id; + dart_flush(gptr); } /** - * Complete all outstanding non-blocking operations executed by the - * local unit. + * Locally complete all outstanding non-blocking operations to all units. */ void flush_local() noexcept { - dart_flush_local(_begptr); + dart_flush_local_all(_begptr); } /** - * Complete all outstanding non-blocking operations executed by the - * local unit. + * Locally complete all outstanding non-blocking operations to the specified + * unit. */ - void flush_local_all() noexcept + void flush_local(dash::team_unit_t target) noexcept { - dart_flush_local_all(_begptr); + dart_gptr_t gptr = _begptr; + gptr.unitid = target.id; + dart_flush_local(gptr); } + /** * Resolve the global pointer from an element position in a unit's * local memory. diff --git a/dash/test/iterator/GlobAsyncRefTest.cc b/dash/test/iterator/GlobAsyncRefTest.cc index 909b849cf..d43e74c22 100644 --- a/dash/test/iterator/GlobAsyncRefTest.cc +++ b/dash/test/iterator/GlobAsyncRefTest.cc @@ -14,9 +14,6 @@ TEST_F(GlobAsyncRefTest, IsLocal) { } array.barrier(); // Test global async references on array elements: - dash::GlobAsyncRef gar_local_l(&array.local[0]); - ASSERT_EQ_U(true, gar_local_l.is_local()); - // Test global async references on array elements: auto global_offset = array.pattern().global(0); // Reference first local element in global memory: dash::GlobRef gref = array[global_offset]; @@ -31,23 +28,22 @@ TEST_F(GlobAsyncRefTest, Push) { int num_elem_per_unit = 20; // Initialize values: dash::Array array(dash::size() * num_elem_per_unit); - for (auto li = 0; li < array.lcapacity(); ++li) { - array.local[li] = dash::myid().id; - } array.barrier(); - // Assign values asynchronously: - for (auto gi = 0; gi < array.size(); ++gi) { - if (array[gi].is_local()) { - // Changes local value only - ++(array.async[gi]); - } + size_t lneighbor = (dash::myid() + dash::size() - 1) % dash::size(); + size_t rneighbor = (dash::myid() + 1) % dash::size(); + // Assign values at left neighbor asynchronously: + size_t start_idx = lneighbor * num_elem_per_unit; + for (auto gi = start_idx; gi < (start_idx + num_elem_per_unit); ++gi) { + // Changes local value only + array.async[gi] = dash::myid().id; } // Flush local window: - array.async.push(); + array.async.flush(); + dash::barrier(); // Test values in local window. Changes by all units should be visible: for (auto li = 0; li < array.lcapacity(); ++li) { // All local values incremented once by all units - ASSERT_EQ_U(dash::myid().id + 1, + ASSERT_EQ_U(rneighbor, array.local[li]); } } @@ -78,67 +74,17 @@ TEST_F(GlobAsyncRefTest, GetSet) { array.barrier(); garef.set(dash::myid()); - ASSERT_EQ_U(static_cast(garef), dash::myid().id); garef.flush(); + ASSERT_EQ_U(garef.get(), dash::myid().id); array.barrier(); - garef.put(dash::myid()); - ASSERT_EQ_U(static_cast(garef), dash::myid().id); + garef.set(dash::myid()); garef.flush(); + ASSERT_EQ_U(garef.get(), dash::myid().id); array.barrier(); int left_neighbor = (dash::myid() + dash::size() - 1) % dash::size(); ASSERT_EQ_U(left_neighbor, array.local[0]); } -TEST_F(GlobAsyncRefTest, Operations) { - // Initialize values: - dash::Array array(dash::size()); - for (auto li = 0; li < array.lcapacity(); ++li) { - array.local[li] = dash::myid().id; - } - array.barrier(); - - int neighbor = (dash::myid() + 1) % dash::size(); - - // Reference a neighbors element in global memory: - dash::GlobAsyncRef garef = array.async[neighbor]; - - ++garef; - garef.flush(); - array.barrier(); - ASSERT_EQ_U(dash::myid().id + 1, array.local[0]); - array.barrier(); - - --garef; - garef.flush(); - array.barrier(); - ASSERT_EQ_U(dash::myid().id, array.local[0]); - array.barrier(); - - garef += 2; - garef.flush(); - array.barrier(); - ASSERT_EQ_U(dash::myid().id + 2, array.local[0]); - array.barrier(); - - garef -= 2; - garef.flush(); - array.barrier(); - ASSERT_EQ_U(dash::myid().id, array.local[0]); - array.barrier(); - - garef *= 2; - garef.flush(); - array.barrier(); - ASSERT_EQ_U(dash::myid().id * 2, array.local[0]); - array.barrier(); - - - garef /= 2; - garef.flush(); - array.barrier(); - ASSERT_EQ_U(dash::myid().id, array.local[0]); -} - TEST_F(GlobAsyncRefTest, Conversion) { // Initialize values: @@ -196,14 +142,15 @@ TEST_F(GlobAsyncRefTest, RefOfStruct) { mytype data {1, 2.0}; garef_rem = data; + garef_rem.flush(); auto garef_a_rem = garef_rem.member(&mytype::a); auto garef_b_rem = garef_rem.member(&mytype::b); // GlobRefAsync is constructed after data is set, so it stores value - int a = garef_a_rem; - int b = garef_b_rem; + int a = garef_a_rem.get(); + int b = garef_b_rem.get(); ASSERT_EQ_U(a, 1); - ASSERT_EQ_U(b, 2.0); + ASSERT_EQ_U(b, 2); } } diff --git a/dash/test/memory/GlobStaticMemTest.cc b/dash/test/memory/GlobStaticMemTest.cc index 7c08de4ac..1bb01d446 100644 --- a/dash/test/memory/GlobStaticMemTest.cc +++ b/dash/test/memory/GlobStaticMemTest.cc @@ -56,9 +56,9 @@ TEST_F(GlobStaticMemTest, GlobalRandomAccess) if (g < globmem.size()) { int gvalue = *gbegin; EXPECT_EQ((g % 3) + 1, gvalue); + EXPECT_EQ(*gbegin, globmem.begin()[g]); } EXPECT_EQ( gbegin, globmem.begin() + g); - EXPECT_EQ(*gbegin, globmem.begin()[g]); EXPECT_EQ( (globmem.size() - g), dash::distance(gbegin, gend)); EXPECT_EQ(-(globmem.size() - g), dash::distance(gend, gbegin));