#ifndef VTKMDIY_MPI_WINODW_HPP #define VTKMDIY_MPI_WINODW_HPP #include "config.hpp" #include "communicator.hpp" #include "operations.hpp" #include #include namespace diy { namespace mpi { #ifndef VTKMDIY_MPI_AS_LIB constexpr int nocheck = MPI_MODE_NOCHECK; #else VTKMDIY_MPI_EXPORT extern const int nocheck; #endif namespace detail { VTKMDIY_MPI_EXPORT_FUNCTION DIY_MPI_Win win_create(const communicator& comm, void* base, unsigned size, int disp); VTKMDIY_MPI_EXPORT_FUNCTION void win_free(DIY_MPI_Win& win); VTKMDIY_MPI_EXPORT_FUNCTION void put(const DIY_MPI_Win& win, const void* data, int count, const datatype& type, int rank, unsigned offset); VTKMDIY_MPI_EXPORT_FUNCTION void get(const DIY_MPI_Win& win, void* data, int count, const datatype& type, int rank, unsigned offset); VTKMDIY_MPI_EXPORT_FUNCTION void fence(const DIY_MPI_Win& win, int assert); VTKMDIY_MPI_EXPORT_FUNCTION void lock(const DIY_MPI_Win& win, int lock_type, int rank, int assert); VTKMDIY_MPI_EXPORT_FUNCTION void unlock(const DIY_MPI_Win& win, int rank); VTKMDIY_MPI_EXPORT_FUNCTION void lock_all(const DIY_MPI_Win& win, int assert); VTKMDIY_MPI_EXPORT_FUNCTION void unlock_all(const DIY_MPI_Win& win); VTKMDIY_MPI_EXPORT_FUNCTION void fetch_and_op(const DIY_MPI_Win& win, const void* origin, void* result, const datatype& type, int rank, unsigned offset, const operation& op); VTKMDIY_MPI_EXPORT_FUNCTION void fetch(const DIY_MPI_Win& win, void* result, const datatype& type, int rank, unsigned offset); VTKMDIY_MPI_EXPORT_FUNCTION void replace(const DIY_MPI_Win& win, const void* value, const datatype& type, int rank, unsigned offset); VTKMDIY_MPI_EXPORT_FUNCTION void sync(const DIY_MPI_Win& win); VTKMDIY_MPI_EXPORT_FUNCTION void flush(const DIY_MPI_Win& win, int rank); VTKMDIY_MPI_EXPORT_FUNCTION void flush_all(const DIY_MPI_Win& win); VTKMDIY_MPI_EXPORT_FUNCTION void flush_local(const DIY_MPI_Win& win, int rank); VTKMDIY_MPI_EXPORT_FUNCTION void flush_local_all(const DIY_MPI_Win& win); } // detail //! \ingroup MPI //! Simple wrapper around MPI window functions. template class window { static_assert(std::is_same::type, detail::true_type>::value, "Only MPI datatypes are allowed in windows"); public: inline window(const communicator& comm, unsigned size); inline ~window(); // moving is Ok window(window&&) = default; window& operator=(window&&) = default; // cannot copy because of the buffer_ window(const window&) = delete; window& operator=(const window&) = delete; inline void put(const T& x, int rank, unsigned offset); inline void put(const std::vector& x, int rank, unsigned offset); inline void get(T& x, int rank, unsigned offset); inline void get(std::vector& x, int rank, unsigned offset); inline void fence(int assert); inline void lock(int lock_type, int rank, int assert = 0); inline void unlock(int rank); inline void lock_all(int assert = 0); inline void unlock_all(); inline void fetch_and_op(const T* origin, T* result, int rank, unsigned offset, const operation& op); inline void fetch(T& result, int rank, unsigned offset); inline void replace(const T& value, int rank, unsigned offset); inline void sync(); inline void flush(int rank); inline void flush_all(); inline void flush_local(int rank); inline void flush_local_all(); private: std::vector buffer_; int rank_; DIY_MPI_Win window_; }; } // mpi } // diy template diy::mpi::window:: window(const diy::mpi::communicator& comm, unsigned size): buffer_(size), rank_(comm.rank()) { window_ = detail::win_create(comm, buffer_.data(), static_cast(buffer_.size()*sizeof(T)), static_cast(sizeof(T))); } template diy::mpi::window:: ~window() { detail::win_free(window_); } template void diy::mpi::window:: put(const T& x, int rank, unsigned offset) { detail::put(window_, address(x), count(x), datatype_of(x), rank, offset); } template void diy::mpi::window:: put(const std::vector& x, int rank, unsigned offset) { detail::put(window_, address(x), count(x), datatype_of(x), rank, offset); } template void diy::mpi::window:: get(T& x, int rank, unsigned offset) { detail::get(window_, address(x), count(x), datatype_of(x), rank, offset); } template void diy::mpi::window:: get(std::vector& x, int rank, unsigned offset) { detail::get(window_, address(x), count(x), datatype_of(x), rank, offset); } template void diy::mpi::window:: fence(int assert) { detail::fence(window_, assert); } template void diy::mpi::window:: lock(int lock_type, int rank, int assert) { detail::lock(window_, lock_type, rank, assert); } template void diy::mpi::window:: unlock(int rank) { detail::unlock(window_, rank); } template void diy::mpi::window:: lock_all(int assert) { detail::lock_all(window_, assert); } template void diy::mpi::window:: unlock_all() { detail::unlock_all(window_); } template void diy::mpi::window:: fetch_and_op(const T* origin, T* result, int rank, unsigned offset, const diy::mpi::operation& op) { detail::fetch_and_op(window_, origin, result, datatype_of(*origin), rank, offset, op); } template void diy::mpi::window:: fetch(T& result, int rank, unsigned offset) { detail::fetch(window_, &result, datatype_of(result), rank, offset); } template void diy::mpi::window:: replace(const T& value, int rank, unsigned offset) { detail::replace(window_, &value, datatype_of(value), rank, offset); } template void diy::mpi::window:: sync() { detail::sync(window_); } template void diy::mpi::window:: flush(int rank) { detail::flush(window_, rank); } template void diy::mpi::window:: flush_all() { detail::flush_all(window_); } template void diy::mpi::window:: flush_local(int rank) { detail::flush_local(window_, rank); } template void diy::mpi::window:: flush_local_all() { detail::flush_local_all(window_); } #ifndef VTKMDIY_MPI_AS_LIB #include "window.cpp" #endif #endif // VTKMDIY_MPI_WINODW_HPP