File: test_ring.cpp

package info (click to toggle)
boost1.90 1.90.0-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 593,120 kB
  • sloc: cpp: 4,190,908; xml: 196,648; python: 34,618; ansic: 23,145; asm: 5,468; sh: 3,774; makefile: 1,161; perl: 1,020; sql: 728; ruby: 676; yacc: 478; java: 77; lisp: 24; csh: 6
file content (130 lines) | stat: -rw-r--r-- 4,650 bytes parent folder | download | duplicates (8)
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
// Copyright (C) 2005, 2006 Douglas Gregor.

// Use, modification and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

// A test of the communicator that passes data around a ring and
// verifies that the same data makes it all the way. Should test all
// of the various kinds of data that can be sent (primitive types, POD
// types, serializable objects, etc.)
#include <boost/mpi/communicator.hpp>
#include <boost/mpi/environment.hpp>
#include <algorithm>
#include "gps_position.hpp"
#include <boost/serialization/string.hpp>
#include <boost/serialization/list.hpp>
//#include "debugger.cpp"

#include "mpi_test_utils.hpp"

using boost::mpi::communicator;
using boost::mpi::status;

template<typename T>
int
ring_test(const communicator& comm, const T& pass_value, const char* kind,
          int root = 0)
{
  int failed  = 0;
  T transferred_value;

  int rank = comm.rank();
  int size = comm.size();

  if (rank == root) {
    std::cout << "Passing " << kind << " around a ring from root " << root
              << "...";
    comm.send((rank + 1) % size, 0, pass_value);
    comm.recv((rank + size - 1) % size, 0, transferred_value);
    BOOST_MPI_CHECK(transferred_value == pass_value, failed);
    if (transferred_value == pass_value) std::cout << " OK." << std::endl;
  } else {
    comm.recv((rank + size - 1) % size, 0, transferred_value);
    BOOST_MPI_CHECK(transferred_value == pass_value, failed);
    comm.send((rank + 1) % size, 0, transferred_value);
  }
  
  (comm.barrier)();
  return failed;
}


template<typename T>
int
ring_array_test(const communicator& comm, const T* pass_values,
                int n, const char* kind, int root = 0)
{
  int failed = 0;
  T* transferred_values = new T[n];
  int rank = comm.rank();
  int size = comm.size();

  if (rank == root) {

    std::cout << "Passing " << kind << " array around a ring from root "
              << root  << "...";
    comm.send((rank + 1) % size, 0, pass_values, n);
    comm.recv((rank + size - 1) % size, 0, transferred_values, n);
    bool okay = std::equal(pass_values, pass_values + n,
                           transferred_values);
    BOOST_MPI_CHECK(okay, failed);
    if (okay) std::cout << " OK." << std::endl;
  } else {
    status stat = comm.probe(boost::mpi::any_source, 0);
    boost::optional<int> num_values = stat.template count<T>();
    if (boost::mpi::is_mpi_datatype<T>()) {
      BOOST_MPI_CHECK(num_values && *num_values == n, failed);
    } else {
      BOOST_MPI_CHECK(!num_values || *num_values == n, failed);     
    }
    comm.recv(stat.source(), 0, transferred_values, n);
    BOOST_MPI_CHECK(std::equal(pass_values, pass_values + n,
                         transferred_values), failed);
    comm.send((rank + 1) % size, 0, transferred_values, n);
  }
  (comm.barrier)();
  delete [] transferred_values;
  return failed;
}

enum color_t {red, green, blue};
BOOST_IS_MPI_DATATYPE(color_t)

int main()
{
  boost::mpi::environment env;
  communicator comm;
  int failed = 0;
  BOOST_MPI_CHECK(comm.size() > 1, failed);
  if (failed == 0) {
    // Check transfer of individual objects
    BOOST_MPI_COUNT_FAILED(ring_test(comm, 17, "integers", 0), failed);
    BOOST_MPI_COUNT_FAILED(ring_test(comm, 17, "integers", 1), failed);
    BOOST_MPI_COUNT_FAILED(ring_test(comm, red, "enums", 1), failed);
    BOOST_MPI_COUNT_FAILED(ring_test(comm, red, "enums", 1), failed);
    BOOST_MPI_COUNT_FAILED(ring_test(comm, gps_position(39,16,20.2799), "GPS positions", 0), failed);
    BOOST_MPI_COUNT_FAILED(ring_test(comm, gps_position(26,25,30.0), "GPS positions", 1), failed);
    BOOST_MPI_COUNT_FAILED(ring_test(comm, std::string("Rosie"), "string", 0), failed);
    
    std::list<std::string> strings;
    strings.push_back("Hello");
    strings.push_back("MPI");
    strings.push_back("World");
    BOOST_MPI_COUNT_FAILED(ring_test(comm, strings, "list of strings", 1), failed);
    
    // Check transfer of arrays
    int int_array[2] = { 17, 42 };
    BOOST_MPI_COUNT_FAILED(ring_array_test(comm, int_array, 2, "integer", 1), failed);
    gps_position gps_position_array[2] = {
      gps_position(39,16,20.2799),
      gps_position(26,25,30.0)
    };
    BOOST_MPI_COUNT_FAILED(ring_array_test(comm, gps_position_array, 2, "GPS position", 1), failed);
    
    std::string string_array[3] = { "Hello", "MPI", "World" };
    BOOST_MPI_COUNT_FAILED(ring_array_test(comm, string_array, 3, "string", 0), failed);
    BOOST_MPI_COUNT_FAILED(ring_array_test(comm, string_array, 3, "string", 1), failed);
  }
  return failed;
}