1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
|
// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
// vi: set et ts=4 sw=2 sts=2:
// SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root
// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception
#include <iostream>
#include <map>
#include <vector>
#include <dune/common/classname.hh>
#include <dune/common/parallel/mpihelper.hh>
#include <dune/common/parallel/mpipack.hh>
#include <dune/common/test/testsuite.hh>
constexpr int TAG = 42;
template<typename Comm>
auto testSync(Comm comm)
{
Dune::TestSuite suite("testSync");
int rank = comm.rank();
// we receive from left and right
int src = (rank - 1 + comm.size()) % comm.size();
int dest = (rank + 1) % comm.size();
// send
{
Dune::MPIPack pack(comm);
pack << 3 << comm.rank();
pack << std::vector<int>{4711, 42};
comm.send(pack, dest, TAG);
}
// recv
{
Dune::MPIPack pack = comm.rrecv(Dune::MPIPack(comm), src, TAG);
int drei; pack >> drei;
int rank_src; pack >> rank_src;
std::vector<int> vec;
pack >> vec;
suite.check(drei==3) << "received wrong value";
suite.check(rank_src==src) << "received wrong value";
suite.check(vec.size() == 2) << "vector has wrong size!";
suite.check(vec[0] == 4711 && vec[1] == 42) << "vector contains wrong values!";
}
return suite;
}
template<typename Comm>
auto testASync(Comm comm)
{
Dune::TestSuite suite("testASync");
int rank = comm.rank();
// we receive from left and right
int src = (rank - 1 + comm.size()) % comm.size();
int dest = (rank + 1) % comm.size();
using RecvFuture = Dune::MPIFuture<Dune::MPIPack>;
using SendFuture = Dune::MPIFuture<Dune::MPIPack>;
std::map<int, SendFuture> sendFutures;
std::map<int, RecvFuture> recvFutures;
// recv async
{
const int reserve = 100;
auto future = comm.irecv(Dune::MPIPack(comm,reserve), src, TAG);
// MPIPack is non-copyable, thus we can't use sendFutures[dest] = ...;
recvFutures.emplace(src, std::move(future));
// Alternative: sendFutures.insert( std::make_pair(dest, std::move(future)) );
}
// send async
{
Dune::MPIPack pack(comm);
pack << 3 << comm.rank();
pack << std::vector<int>{4711, 42};
auto future = comm.isend(std::move(pack), dest, TAG);
// MPIPack is non-copyable, thus we can't use sendFutures[dest] = ...;
sendFutures.emplace(dest, std::move(future));
// Alternative: sendFutures.insert( std::make_pair(dest, std::move(future)) );
}
// recv
for (auto & [rank, future] : recvFutures)
{
Dune::MPIPack pack = future.get();
int drei; pack >> drei;
int rank_src; pack >> rank_src;
std::vector<int> vec;
pack >> vec;
suite.check(drei==3) << "received wrong value";
suite.check(rank_src==rank) << "received wrong value";
suite.check(vec.size() == 2) << "vector has wrong size!";
suite.check(vec[0] == 4711 && vec[1] == 42) << "vector contains wrong values!";
}
// wait for send operations to finish
for (auto & [rank, future] : sendFutures)
future.wait();
return suite;
}
template<typename Comm>
auto testASyncVector(Comm comm)
{
Dune::TestSuite suite("testASync");
int rank = comm.rank();
// we receive from left and right
int src = (rank - 1 + comm.size()) % comm.size();
int dest = (rank + 1) % comm.size();
using RecvFuture = Dune::MPIFuture<std::vector<int>>;
using SendFuture = Dune::MPIFuture<std::vector<int>>;
SendFuture sendFuture;
RecvFuture recvFuture;
// recv async
{
const int reserve = 2; // size on the receiving side...
recvFuture = comm.irecv(std::vector<int>(reserve), src, TAG+src);
}
// send async
{
std::vector<int> vec{4711, 42}; // we have to keep the vector until send has finished
sendFuture = comm.isend(std::move(vec), dest, TAG+rank);
}
// recv
{
std::cout << rank << " reading future" << std::endl;
std::vector<int> vec = recvFuture.get();
std::cout << rank << " done" << std::endl;
suite.check(vec.size() == 2) << "vector has wrong size!";
suite.check(vec[0] == 4711 && vec[1] == 42) << "vector contains wrong values!";
}
// wait for send to finish
sendFuture.wait();
return suite;
}
int main(int argc, char** argv){
Dune::MPIHelper& helper = Dune::MPIHelper::instance(argc, argv);
Dune::TestSuite suite;
auto comm = helper.getCommunication();
suite.subTest(testSync(comm));
suite.subTest(testASyncVector(comm));
suite.subTest(testASync(comm));
return suite.exit();
}
|