FreeNOS
MpiPing.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2020 Niek Linnenbank
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include <Log.h>
19 #include <mpi.h>
20 #include "MpiPing.h"
21 
22 MpiPing::MpiPing(int argc, char **argv)
23  : POSIXApplication(argc, argv)
24  , m_mpiInitResult(MPI_Init(&m_argc, &m_argv))
25  , m_id(0)
26 {
27  parser().setDescription("Send ping message to cores via MPI");
28 }
29 
31 {
32  DEBUG("");
33 }
34 
36 {
38  {
39  ERROR("failed to initialize MPI: result = " << m_mpiInitResult);
40  return IOError;
41  }
42 
43  int result = MPI_Comm_rank(MPI_COMM_WORLD, &m_id);
44  if (result != MPI_SUCCESS)
45  {
46  ERROR("failed to lookup MPI rank: result = " << result);
47  return IOError;
48  }
49 
50  return Success;
51 }
52 
54 {
55  int result, cores;
56 
57  if (m_id == 0)
58  {
59  result = MPI_Comm_size(MPI_COMM_WORLD, &cores);
60  if (result != MPI_SUCCESS)
61  {
62  ERROR("failed to lookup MPI core count: result = " << result);
63  return IOError;
64  }
65  NOTICE("ping " << (cores - 1) << " cores");
66 
67  // Master send a ping and receives a pong from each node
68  for (int i = 1; i < cores; i++)
69  {
70  const Result pingResult = sendNumber(i, PingMagicNumber);
71  if (pingResult != Success)
72  {
73  ERROR("failed to send ping to core" << i << ": result = " << (int) pingResult);
74  return pingResult;
75  }
76 
77  const Result pongResult = receiveNumber(i, PongMagicNumber);
78  if (pongResult != Success)
79  {
80  ERROR("failed to receive pong from core" << i << ": result = " << (int) pongResult);
81  return pongResult;
82  }
83 
84  NOTICE("pong received from core" << i);
85  }
86  }
87  else
88  {
89  // Slaves first receive a ping from the master, then reply with a pong
90  const Result recvResult = receiveNumber(0, PingMagicNumber);
91  if (recvResult != Success)
92  {
93  ERROR("failed to receive ping from core0: result = " << (int) recvResult);
94  return recvResult;
95  }
96 
97  const Result sendResult = sendNumber(0, PongMagicNumber);
98  if (sendResult != Success)
99  {
100  ERROR("failed to send message to core0: result = " << (int) sendResult);
101  return sendResult;
102  }
103  }
104 
105  result = MPI_Finalize();
106  if (result != MPI_SUCCESS)
107  {
108  ERROR("failed to finalize MPI: result = " << result);
109  return IOError;
110  }
111 
112  return Success;
113 }
114 
116  const int number) const
117 {
118  int buf = number;
119 
120  DEBUG("coreId = " << coreId << " number = " << Number::Hex << number);
121 
122  int result = MPI_Send(&buf, 1, MPI_INT, coreId, 0, MPI_COMM_WORLD);
123  if (result != MPI_SUCCESS)
124  {
125  ERROR("failed to send message to core" << coreId << ": result = " << (int) result);
126  return IOError;
127  }
128 
129  return Success;
130 }
131 
133  const int expectedNumber) const
134 {
135  int buf = 0;
136  MPI_Status status;
137 
138  DEBUG("coreId = " << coreId << " expectedNumber = " << Number::Hex << expectedNumber);
139 
140  int result = MPI_Recv(&buf, 1, MPI_INT, coreId, 0, MPI_COMM_WORLD, &status);
141  if (result != MPI_SUCCESS)
142  {
143  ERROR("failed to receive message from core" << coreId << ": result = " << (int) result);
144  return IOError;
145  }
146 
147  if (buf != expectedNumber)
148  {
149  ERROR("invalid message " << Number::Hex << buf << " != " << Number::Hex << expectedNumber <<
150  " received from core" << coreId);
151  return IOError;
152  }
153 
154  return Success;
155 }
MpiPing::exec
virtual Result exec()
Execute the application.
Definition: MpiPing.cpp:53
MPI_Finalize
C int MPI_Finalize(void)
Definition: mpi.cpp:30
MPI_INT
@ MPI_INT
Definition: mpi.h:51
MpiPing::receiveNumber
Result receiveNumber(const Size coreId, const int expectedNumber) const
Receive a message containing a number.
Definition: MpiPing.cpp:132
MpiPing::PongMagicNumber
static const int PongMagicNumber
Magic number send for the pong message.
Definition: MpiPing.h:39
MpiPing.h
NOTICE
#define NOTICE(msg)
Output a notice message.
Definition: Log.h:75
MPI_SUCCESS
@ MPI_SUCCESS
Definition: mpi.h:73
MPI_Comm_size
C int MPI_Comm_size(MPI_Comm comm, int *size)
Definition: mpi.cpp:66
POSIXApplication
POSIX-compatible application.
Definition: POSIXApplication.h:35
Application::Success
@ Success
Definition: Application.h:55
ArgumentParser::setDescription
void setDescription(const String &desc)
Set program description.
Definition: ArgumentParser.cpp:95
MPI_Status
uint MPI_Status
Status holder.
Definition: mpi.h:41
Log.h
MpiPing::~MpiPing
virtual ~MpiPing()
Destructor.
Definition: MpiPing.cpp:30
Application::IOError
@ IOError
Definition: Application.h:57
DEBUG
#define DEBUG(msg)
Output a debug message to standard output.
Definition: Log.h:89
mpi.h
MPI_Init
C int MPI_Init(int *argc, char ***argv)
Definition: mpi.cpp:24
MpiPing::initialize
virtual Result initialize()
Initialize the application.
Definition: MpiPing.cpp:35
Size
unsigned int Size
Any sane size indicator cannot go negative.
Definition: Types.h:128
Application::Result
Result
Result codes.
Definition: Application.h:53
MPI_Comm_rank
C int MPI_Comm_rank(MPI_Comm comm, int *rank)
Definition: mpi.cpp:59
MpiPing::sendNumber
Result sendNumber(const Size coreId, const int number) const
Send a message containing a number.
Definition: MpiPing.cpp:115
MPI_COMM_WORLD
@ MPI_COMM_WORLD
Definition: mpi.h:64
Application::parser
ArgumentParser & parser()
Get program arguments parser.
Definition: Application.cpp:102
ERROR
#define ERROR(msg)
Output an error message.
Definition: Log.h:61
MPI_Send
C int MPI_Send(const void *buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm)
Definition: mpi.cpp:36
MpiPing::m_mpiInitResult
int m_mpiInitResult
Result of MPI initialization.
Definition: MpiPing.h:97
MPI_Recv
C int MPI_Recv(void *buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Status *status)
Definition: mpi.cpp:47
MpiPing::PingMagicNumber
static const int PingMagicNumber
Magic number to send as ping message.
Definition: MpiPing.h:36
coreId
u8 coreId
Definition: IntelACPI.h:64
Number::Hex
@ Hex
Decimal: 0-10.
Definition: Types.h:171
MpiPing::MpiPing
MpiPing(int argc, char **argv)
Constructor.
Definition: MpiPing.cpp:22
MpiPing::m_id
int m_id
MPI core identifier (rank) of the current process.
Definition: MpiPing.h:100