File: mpipacktest.cc

package info (click to toggle)
dune-common 2.11.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 6,048 kB
  • sloc: cpp: 54,403; python: 4,136; sh: 1,657; makefile: 17
file content (157 lines) | stat: -rw-r--r-- 4,554 bytes parent folder | download | duplicates (2)
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();
}