5 #ifndef GKO_PUBLIC_CORE_BASE_MPI_HPP_
6 #define GKO_PUBLIC_CORE_BASE_MPI_HPP_
10 #include <type_traits>
13 #include <ginkgo/config.hpp>
14 #include <ginkgo/core/base/exception.hpp>
15 #include <ginkgo/core/base/exception_helpers.hpp>
16 #include <ginkgo/core/base/executor.hpp>
17 #include <ginkgo/core/base/half.hpp>
18 #include <ginkgo/core/base/types.hpp>
19 #include <ginkgo/core/base/utils_helper.hpp>
29 namespace experimental {
43 #if GINKGO_HAVE_GPU_AWARE_MPI
61 #define GKO_REGISTER_MPI_TYPE(input_type, mpi_type) \
63 struct type_impl<input_type> { \
64 static MPI_Datatype get_type() { return mpi_type; } \
79 GKO_REGISTER_MPI_TYPE(
char, MPI_CHAR);
80 GKO_REGISTER_MPI_TYPE(
unsigned char, MPI_UNSIGNED_CHAR);
81 GKO_REGISTER_MPI_TYPE(
unsigned, MPI_UNSIGNED);
82 GKO_REGISTER_MPI_TYPE(
int, MPI_INT);
83 GKO_REGISTER_MPI_TYPE(
unsigned short, MPI_UNSIGNED_SHORT);
84 GKO_REGISTER_MPI_TYPE(
unsigned long, MPI_UNSIGNED_LONG);
85 GKO_REGISTER_MPI_TYPE(
long, MPI_LONG);
86 GKO_REGISTER_MPI_TYPE(
long long, MPI_LONG_LONG_INT);
87 GKO_REGISTER_MPI_TYPE(
unsigned long long, MPI_UNSIGNED_LONG_LONG);
88 GKO_REGISTER_MPI_TYPE(
float, MPI_FLOAT);
89 GKO_REGISTER_MPI_TYPE(
double, MPI_DOUBLE);
90 GKO_REGISTER_MPI_TYPE(
long double, MPI_LONG_DOUBLE);
91 #if GINKGO_ENABLE_HALF
95 GKO_REGISTER_MPI_TYPE(
half, MPI_UNSIGNED_SHORT);
96 GKO_REGISTER_MPI_TYPE(std::complex<half>, MPI_FLOAT);
97 #endif // GKO_ENABLE_HALF
98 #if GINKGO_ENABLE_BFLOAT16
99 GKO_REGISTER_MPI_TYPE(
bfloat16, MPI_UNSIGNED_SHORT);
100 GKO_REGISTER_MPI_TYPE(std::complex<bfloat16>, MPI_FLOAT);
101 #endif // GKO_ENABLE_BFLOAT16
102 GKO_REGISTER_MPI_TYPE(std::complex<float>, MPI_C_FLOAT_COMPLEX);
103 GKO_REGISTER_MPI_TYPE(std::complex<double>, MPI_C_DOUBLE_COMPLEX);
122 GKO_ASSERT_NO_MPI_ERRORS(MPI_Type_contiguous(count, old_type, &type_));
123 GKO_ASSERT_NO_MPI_ERRORS(MPI_Type_commit(&type_));
148 *
this = std::move(other);
160 if (
this != &other) {
161 this->type_ = std::exchange(other.type_, MPI_DATATYPE_NULL);
171 if (type_ != MPI_DATATYPE_NULL) {
172 MPI_Type_free(&type_);
181 MPI_Datatype
get()
const {
return type_; }
193 serialized = MPI_THREAD_SERIALIZED,
194 funneled = MPI_THREAD_FUNNELED,
195 single = MPI_THREAD_SINGLE,
196 multiple = MPI_THREAD_MULTIPLE
211 static bool is_finalized()
214 GKO_ASSERT_NO_MPI_ERRORS(MPI_Finalized(&flag));
218 static bool is_initialized()
221 GKO_ASSERT_NO_MPI_ERRORS(MPI_Initialized(&flag));
241 const thread_type thread_t = thread_type::serialized)
243 this->required_thread_support_ = static_cast<int>(thread_t);
244 GKO_ASSERT_NO_MPI_ERRORS(
245 MPI_Init_thread(&argc, &argv, this->required_thread_support_,
246 &(this->provided_thread_support_)));
260 int required_thread_support_;
261 int provided_thread_support_;
274 using pointer = MPI_Comm*;
275 void operator()(pointer comm)
const
277 GKO_ASSERT(*comm != MPI_COMM_NULL);
278 GKO_ASSERT_NO_MPI_ERRORS(MPI_Comm_free(comm));
301 MPI_Status*
get() {
return &this->status_; }
313 template <
typename T>
347 this->req_ = std::exchange(o.req_, MPI_REQUEST_NULL);
354 if (req_ != MPI_REQUEST_NULL) {
355 if (MPI_Request_free(&req_) != MPI_SUCCESS) {
367 MPI_Request*
get() {
return &this->req_; }
378 GKO_ASSERT_NO_MPI_ERRORS(MPI_Wait(&req_,
status.
get()));
394 inline std::vector<status>
wait_all(std::vector<request>& req)
396 std::vector<status> stat;
397 for (std::size_t i = 0; i < req.size(); ++i) {
398 stat.emplace_back(req[i].wait());
431 : comm_(), force_host_buffer_(force_host_buffer)
433 this->comm_.reset(
new MPI_Comm(comm));
447 GKO_ASSERT_NO_MPI_ERRORS(MPI_Comm_split(comm, color, key, &comm_out));
448 this->comm_.reset(
new MPI_Comm(comm_out), comm_deleter{});
462 GKO_ASSERT_NO_MPI_ERRORS(
463 MPI_Comm_split(comm.
get(), color, key, &comm_out));
464 this->comm_.reset(
new MPI_Comm(comm_out), comm_deleter{});
477 bool force_host_buffer =
false)
479 communicator comm_out(MPI_COMM_NULL, force_host_buffer);
480 comm_out.comm_.reset(
new MPI_Comm(comm), comm_deleter{});
509 if (
this != &other) {
510 comm_ = std::exchange(other.comm_,
511 std::make_shared<MPI_Comm>(MPI_COMM_NULL));
512 force_host_buffer_ = other.force_host_buffer_;
522 const MPI_Comm&
get()
const {
return *(this->comm_.get()); }
524 bool force_host_buffer()
const {
return force_host_buffer_; }
531 int size()
const {
return get_num_ranks(); }
538 int rank()
const {
return get_my_rank(); };
572 if (
get() == MPI_COMM_NULL || rhs.get() == MPI_COMM_NULL) {
573 return get() == rhs.get();
576 GKO_ASSERT_NO_MPI_ERRORS(MPI_Comm_compare(
get(), rhs.get(), &flag));
577 return flag == MPI_IDENT;
594 if (
get() == MPI_COMM_NULL || rhs.get() == MPI_COMM_NULL) {
595 return get() == rhs.get();
598 GKO_ASSERT_NO_MPI_ERRORS(MPI_Comm_compare(
get(), rhs.get(), &flag));
599 return flag == MPI_CONGRUENT;
608 GKO_ASSERT_NO_MPI_ERRORS(MPI_Barrier(this->
get()));
624 template <
typename SendType>
625 void send(std::shared_ptr<const Executor> exec,
const SendType* send_buffer,
626 const int send_count,
const int destination_rank,
627 const int send_tag)
const
629 auto guard = exec->get_scoped_device_id_guard();
630 GKO_ASSERT_NO_MPI_ERRORS(
632 destination_rank, send_tag, this->
get()));
651 template <
typename SendType>
653 const SendType* send_buffer,
const int send_count,
654 const int destination_rank,
const int send_tag)
const
656 auto guard = exec->get_scoped_device_id_guard();
658 GKO_ASSERT_NO_MPI_ERRORS(
660 destination_rank, send_tag, this->
get(), req.
get()));
679 template <
typename RecvType>
680 status recv(std::shared_ptr<const Executor> exec, RecvType* recv_buffer,
681 const int recv_count,
const int source_rank,
682 const int recv_tag)
const
684 auto guard = exec->get_scoped_device_id_guard();
686 GKO_ASSERT_NO_MPI_ERRORS(
688 source_rank, recv_tag, this->
get(), st.
get()));
707 template <
typename RecvType>
709 const int recv_count,
const int source_rank,
710 const int recv_tag)
const
712 auto guard = exec->get_scoped_device_id_guard();
714 GKO_ASSERT_NO_MPI_ERRORS(
716 source_rank, recv_tag, this->
get(), req.
get()));
732 template <
typename BroadcastType>
733 void broadcast(std::shared_ptr<const Executor> exec, BroadcastType* buffer,
734 int count,
int root_rank)
const
736 auto guard = exec->get_scoped_device_id_guard();
737 GKO_ASSERT_NO_MPI_ERRORS(MPI_Bcast(buffer, count,
739 root_rank, this->
get()));
757 template <
typename BroadcastType>
759 BroadcastType* buffer,
int count,
int root_rank)
const
761 auto guard = exec->get_scoped_device_id_guard();
763 GKO_ASSERT_NO_MPI_ERRORS(
765 root_rank, this->
get(), req.
get()));
784 template <
typename ReduceType>
785 void reduce(std::shared_ptr<const Executor> exec,
786 const ReduceType* send_buffer, ReduceType* recv_buffer,
787 int count, MPI_Op operation,
int root_rank)
const
789 auto guard = exec->get_scoped_device_id_guard();
790 GKO_ASSERT_NO_MPI_ERRORS(MPI_Reduce(send_buffer, recv_buffer, count,
792 operation, root_rank, this->
get()));
812 template <
typename ReduceType>
814 const ReduceType* send_buffer, ReduceType* recv_buffer,
815 int count, MPI_Op operation,
int root_rank)
const
817 auto guard = exec->get_scoped_device_id_guard();
819 GKO_ASSERT_NO_MPI_ERRORS(MPI_Ireduce(
821 operation, root_rank, this->
get(), req.
get()));
838 template <
typename ReduceType>
840 ReduceType* recv_buffer,
int count, MPI_Op operation)
const
842 auto guard = exec->get_scoped_device_id_guard();
843 GKO_ASSERT_NO_MPI_ERRORS(MPI_Allreduce(
845 operation, this->
get()));
863 template <
typename ReduceType>
865 ReduceType* recv_buffer,
int count,
866 MPI_Op operation)
const
868 auto guard = exec->get_scoped_device_id_guard();
870 GKO_ASSERT_NO_MPI_ERRORS(MPI_Iallreduce(
872 operation, this->
get(), req.
get()));
890 template <
typename ReduceType>
892 const ReduceType* send_buffer, ReduceType* recv_buffer,
893 int count, MPI_Op operation)
const
895 auto guard = exec->get_scoped_device_id_guard();
896 GKO_ASSERT_NO_MPI_ERRORS(MPI_Allreduce(
898 operation, this->
get()));
917 template <
typename ReduceType>
919 const ReduceType* send_buffer, ReduceType* recv_buffer,
920 int count, MPI_Op operation)
const
922 auto guard = exec->get_scoped_device_id_guard();
924 GKO_ASSERT_NO_MPI_ERRORS(MPI_Iallreduce(
926 operation, this->
get(), req.
get()));
946 template <
typename SendType,
typename RecvType>
947 void gather(std::shared_ptr<const Executor> exec,
948 const SendType* send_buffer,
const int send_count,
949 RecvType* recv_buffer,
const int recv_count,
952 auto guard = exec->get_scoped_device_id_guard();
953 GKO_ASSERT_NO_MPI_ERRORS(
956 root_rank, this->
get()));
978 template <
typename SendType,
typename RecvType>
980 const SendType* send_buffer,
const int send_count,
981 RecvType* recv_buffer,
const int recv_count,
984 auto guard = exec->get_scoped_device_id_guard();
986 GKO_ASSERT_NO_MPI_ERRORS(MPI_Igather(
1011 template <
typename SendType,
typename RecvType>
1013 const SendType* send_buffer,
const int send_count,
1014 RecvType* recv_buffer,
const int* recv_counts,
1015 const int* displacements,
int root_rank)
const
1017 auto guard = exec->get_scoped_device_id_guard();
1018 GKO_ASSERT_NO_MPI_ERRORS(MPI_Gatherv(
1020 recv_buffer, recv_counts, displacements,
1044 template <
typename SendType,
typename RecvType>
1046 const SendType* send_buffer,
const int send_count,
1047 RecvType* recv_buffer,
const int* recv_counts,
1048 const int* displacements,
int root_rank)
const
1050 auto guard = exec->get_scoped_device_id_guard();
1052 GKO_ASSERT_NO_MPI_ERRORS(MPI_Igatherv(
1054 recv_buffer, recv_counts, displacements,
1075 template <
typename SendType,
typename RecvType>
1077 const SendType* send_buffer,
const int send_count,
1078 RecvType* recv_buffer,
const int recv_count)
const
1080 auto guard = exec->get_scoped_device_id_guard();
1081 GKO_ASSERT_NO_MPI_ERRORS(MPI_Allgather(
1105 template <
typename SendType,
typename RecvType>
1107 const SendType* send_buffer,
const int send_count,
1108 RecvType* recv_buffer,
const int recv_count)
const
1110 auto guard = exec->get_scoped_device_id_guard();
1112 GKO_ASSERT_NO_MPI_ERRORS(MPI_Iallgather(
1115 this->
get(), req.
get()));
1135 template <
typename SendType,
typename RecvType>
1136 void scatter(std::shared_ptr<const Executor> exec,
1137 const SendType* send_buffer,
const int send_count,
1138 RecvType* recv_buffer,
const int recv_count,
1139 int root_rank)
const
1141 auto guard = exec->get_scoped_device_id_guard();
1142 GKO_ASSERT_NO_MPI_ERRORS(MPI_Scatter(
1167 template <
typename SendType,
typename RecvType>
1169 const SendType* send_buffer,
const int send_count,
1170 RecvType* recv_buffer,
const int recv_count,
1171 int root_rank)
const
1173 auto guard = exec->get_scoped_device_id_guard();
1175 GKO_ASSERT_NO_MPI_ERRORS(MPI_Iscatter(
1178 this->
get(), req.
get()));
1200 template <
typename SendType,
typename RecvType>
1202 const SendType* send_buffer,
const int* send_counts,
1203 const int* displacements, RecvType* recv_buffer,
1204 const int recv_count,
int root_rank)
const
1206 auto guard = exec->get_scoped_device_id_guard();
1207 GKO_ASSERT_NO_MPI_ERRORS(MPI_Scatterv(
1208 send_buffer, send_counts, displacements,
1233 template <
typename SendType,
typename RecvType>
1235 const SendType* send_buffer,
const int* send_counts,
1236 const int* displacements, RecvType* recv_buffer,
1237 const int recv_count,
int root_rank)
const
1239 auto guard = exec->get_scoped_device_id_guard();
1241 GKO_ASSERT_NO_MPI_ERRORS(
1242 MPI_Iscatterv(send_buffer, send_counts, displacements,
1245 root_rank, this->
get(), req.
get()));
1265 template <
typename RecvType>
1266 void all_to_all(std::shared_ptr<const Executor> exec, RecvType* recv_buffer,
1267 const int recv_count)
const
1269 auto guard = exec->get_scoped_device_id_guard();
1270 GKO_ASSERT_NO_MPI_ERRORS(MPI_Alltoall(
1294 template <
typename RecvType>
1296 RecvType* recv_buffer,
const int recv_count)
const
1298 auto guard = exec->get_scoped_device_id_guard();
1300 GKO_ASSERT_NO_MPI_ERRORS(MPI_Ialltoall(
1303 this->
get(), req.
get()));
1323 template <
typename SendType,
typename RecvType>
1325 const SendType* send_buffer,
const int send_count,
1326 RecvType* recv_buffer,
const int recv_count)
const
1328 auto guard = exec->get_scoped_device_id_guard();
1329 GKO_ASSERT_NO_MPI_ERRORS(MPI_Alltoall(
1353 template <
typename SendType,
typename RecvType>
1355 const SendType* send_buffer,
const int send_count,
1356 RecvType* recv_buffer,
const int recv_count)
const
1358 auto guard = exec->get_scoped_device_id_guard();
1360 GKO_ASSERT_NO_MPI_ERRORS(MPI_Ialltoall(
1363 this->
get(), req.
get()));
1386 template <
typename SendType,
typename RecvType>
1388 const SendType* send_buffer,
const int* send_counts,
1389 const int* send_offsets, RecvType* recv_buffer,
1390 const int* recv_counts,
const int* recv_offsets)
const
1392 this->
all_to_all_v(std::move(exec), send_buffer, send_counts,
1394 recv_buffer, recv_counts, recv_offsets,
1414 const void* send_buffer,
const int* send_counts,
1415 const int* send_offsets, MPI_Datatype send_type,
1416 void* recv_buffer,
const int* recv_counts,
1417 const int* recv_offsets, MPI_Datatype recv_type)
const
1419 auto guard = exec->get_scoped_device_id_guard();
1420 GKO_ASSERT_NO_MPI_ERRORS(MPI_Alltoallv(
1421 send_buffer, send_counts, send_offsets, send_type, recv_buffer,
1422 recv_counts, recv_offsets, recv_type, this->
get()));
1445 const void* send_buffer,
const int* send_counts,
1446 const int* send_offsets, MPI_Datatype send_type,
1447 void* recv_buffer,
const int* recv_counts,
1448 const int* recv_offsets,
1449 MPI_Datatype recv_type)
const
1451 auto guard = exec->get_scoped_device_id_guard();
1453 GKO_ASSERT_NO_MPI_ERRORS(MPI_Ialltoallv(
1454 send_buffer, send_counts, send_offsets, send_type, recv_buffer,
1455 recv_counts, recv_offsets, recv_type, this->
get(), req.
get()));
1479 template <
typename SendType,
typename RecvType>
1481 const SendType* send_buffer,
const int* send_counts,
1482 const int* send_offsets, RecvType* recv_buffer,
1483 const int* recv_counts,
1484 const int* recv_offsets)
const
1487 std::move(exec), send_buffer, send_counts, send_offsets,
1506 template <
typename ScanType>
1507 void scan(std::shared_ptr<const Executor> exec,
const ScanType* send_buffer,
1508 ScanType* recv_buffer,
int count, MPI_Op operation)
const
1510 auto guard = exec->get_scoped_device_id_guard();
1511 GKO_ASSERT_NO_MPI_ERRORS(MPI_Scan(send_buffer, recv_buffer, count,
1513 operation, this->
get()));
1532 template <
typename ScanType>
1534 const ScanType* send_buffer, ScanType* recv_buffer,
1535 int count, MPI_Op operation)
const
1537 auto guard = exec->get_scoped_device_id_guard();
1539 GKO_ASSERT_NO_MPI_ERRORS(MPI_Iscan(send_buffer, recv_buffer, count,
1541 operation, this->
get(), req.
get()));
1546 std::shared_ptr<MPI_Comm> comm_;
1547 bool force_host_buffer_;
1549 int get_my_rank()
const
1552 GKO_ASSERT_NO_MPI_ERRORS(MPI_Comm_rank(
get(), &my_rank));
1556 int get_node_local_rank()
const
1558 MPI_Comm local_comm;
1560 GKO_ASSERT_NO_MPI_ERRORS(MPI_Comm_split_type(
1561 this->
get(), MPI_COMM_TYPE_SHARED, 0, MPI_INFO_NULL, &local_comm));
1562 GKO_ASSERT_NO_MPI_ERRORS(MPI_Comm_rank(local_comm, &
rank));
1563 MPI_Comm_free(&local_comm);
1567 int get_num_ranks()
const
1570 GKO_ASSERT_NO_MPI_ERRORS(MPI_Comm_size(this->
get(), &size));
1581 const communicator& comm);
1600 template <
typename ValueType>
1606 enum class create_type { allocate = 1, create = 2, dynamic_create = 3 };
1628 window(
window&& other) : window_{std::exchange(other.window_, MPI_WIN_NULL)}
1639 window_ = std::exchange(other.window_, MPI_WIN_NULL);
1654 window(std::shared_ptr<const Executor> exec, ValueType* base,
int num_elems,
1655 const communicator& comm,
const int disp_unit =
sizeof(ValueType),
1656 MPI_Info input_info = MPI_INFO_NULL,
1659 auto guard = exec->get_scoped_device_id_guard();
1660 unsigned size = num_elems *
sizeof(ValueType);
1661 if (c_type == create_type::create) {
1662 GKO_ASSERT_NO_MPI_ERRORS(MPI_Win_create(
1663 base, size, disp_unit, input_info, comm.
get(), &this->window_));
1664 }
else if (c_type == create_type::dynamic_create) {
1665 GKO_ASSERT_NO_MPI_ERRORS(
1666 MPI_Win_create_dynamic(input_info, comm.
get(), &this->window_));
1667 }
else if (c_type == create_type::allocate) {
1668 GKO_ASSERT_NO_MPI_ERRORS(MPI_Win_allocate(
1669 size, disp_unit, input_info, comm.
get(), base, &this->window_));
1671 GKO_NOT_IMPLEMENTED;
1690 GKO_ASSERT_NO_MPI_ERRORS(MPI_Win_fence(assert, this->window_));
1702 int assert = 0)
const
1704 if (lock_t == lock_type::shared) {
1705 GKO_ASSERT_NO_MPI_ERRORS(
1706 MPI_Win_lock(MPI_LOCK_SHARED, rank, assert, this->window_));
1707 }
else if (lock_t == lock_type::exclusive) {
1708 GKO_ASSERT_NO_MPI_ERRORS(
1709 MPI_Win_lock(MPI_LOCK_EXCLUSIVE, rank, assert, this->window_));
1711 GKO_NOT_IMPLEMENTED;
1723 GKO_ASSERT_NO_MPI_ERRORS(MPI_Win_unlock(rank, this->window_));
1734 GKO_ASSERT_NO_MPI_ERRORS(MPI_Win_lock_all(assert, this->window_));
1743 GKO_ASSERT_NO_MPI_ERRORS(MPI_Win_unlock_all(this->window_));
1754 GKO_ASSERT_NO_MPI_ERRORS(MPI_Win_flush(rank, this->window_));
1765 GKO_ASSERT_NO_MPI_ERRORS(MPI_Win_flush_local(rank, this->window_));
1774 GKO_ASSERT_NO_MPI_ERRORS(MPI_Win_flush_all(this->window_));
1783 GKO_ASSERT_NO_MPI_ERRORS(MPI_Win_flush_local_all(this->window_));
1789 void sync()
const { GKO_ASSERT_NO_MPI_ERRORS(MPI_Win_sync(this->window_)); }
1796 if (this->window_ && this->window_ != MPI_WIN_NULL) {
1797 MPI_Win_free(&this->window_);
1811 template <
typename PutType>
1812 void put(std::shared_ptr<const Executor> exec,
const PutType* origin_buffer,
1813 const int origin_count,
const int target_rank,
1814 const unsigned int target_disp,
const int target_count)
const
1816 auto guard = exec->get_scoped_device_id_guard();
1817 GKO_ASSERT_NO_MPI_ERRORS(
1819 target_rank, target_disp, target_count,
1835 template <
typename PutType>
1837 const PutType* origin_buffer,
const int origin_count,
1838 const int target_rank,
const unsigned int target_disp,
1839 const int target_count)
const
1841 auto guard = exec->get_scoped_device_id_guard();
1843 GKO_ASSERT_NO_MPI_ERRORS(MPI_Rput(
1845 target_rank, target_disp, target_count,
1861 template <
typename PutType>
1863 const PutType* origin_buffer,
const int origin_count,
1864 const int target_rank,
const unsigned int target_disp,
1865 const int target_count, MPI_Op operation)
const
1867 auto guard = exec->get_scoped_device_id_guard();
1868 GKO_ASSERT_NO_MPI_ERRORS(MPI_Accumulate(
1870 target_rank, target_disp, target_count,
1887 template <
typename PutType>
1889 const PutType* origin_buffer,
const int origin_count,
1890 const int target_rank,
const unsigned int target_disp,
1891 const int target_count, MPI_Op operation)
const
1893 auto guard = exec->get_scoped_device_id_guard();
1895 GKO_ASSERT_NO_MPI_ERRORS(MPI_Raccumulate(
1897 target_rank, target_disp, target_count,
1913 template <
typename GetType>
1914 void get(std::shared_ptr<const Executor> exec, GetType* origin_buffer,
1915 const int origin_count,
const int target_rank,
1916 const unsigned int target_disp,
const int target_count)
const
1918 auto guard = exec->get_scoped_device_id_guard();
1919 GKO_ASSERT_NO_MPI_ERRORS(
1921 target_rank, target_disp, target_count,
1937 template <
typename GetType>
1938 request r_get(std::shared_ptr<const Executor> exec, GetType* origin_buffer,
1939 const int origin_count,
const int target_rank,
1940 const unsigned int target_disp,
const int target_count)
const
1942 auto guard = exec->get_scoped_device_id_guard();
1944 GKO_ASSERT_NO_MPI_ERRORS(MPI_Rget(
1946 target_rank, target_disp, target_count,
1964 template <
typename GetType>
1966 GetType* origin_buffer,
const int origin_count,
1967 GetType* result_buffer,
const int result_count,
1968 const int target_rank,
const unsigned int target_disp,
1969 const int target_count, MPI_Op operation)
const
1971 auto guard = exec->get_scoped_device_id_guard();
1972 GKO_ASSERT_NO_MPI_ERRORS(MPI_Get_accumulate(
1975 target_rank, target_disp, target_count,
1994 template <
typename GetType>
1996 GetType* origin_buffer,
const int origin_count,
1997 GetType* result_buffer,
const int result_count,
1998 const int target_rank,
1999 const unsigned int target_disp,
2000 const int target_count, MPI_Op operation)
const
2002 auto guard = exec->get_scoped_device_id_guard();
2004 GKO_ASSERT_NO_MPI_ERRORS(MPI_Rget_accumulate(
2007 target_rank, target_disp, target_count,
2024 template <
typename GetType>
2026 GetType* origin_buffer, GetType* result_buffer,
2027 const int target_rank,
const unsigned int target_disp,
2028 MPI_Op operation)
const
2030 auto guard = exec->get_scoped_device_id_guard();
2031 GKO_ASSERT_NO_MPI_ERRORS(MPI_Fetch_and_op(
2033 target_rank, target_disp, operation, this->
get_window()));
2046 #endif // GKO_HAVE_MPI
2049 #endif // GKO_PUBLIC_CORE_BASE_MPI_HPP_