FreeNOS
MpiHost.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 <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <errno.h>
22 #include <libgen.h>
23 #include <sys/stat.h>
24 #include <sys/socket.h>
25 #include <Log.h>
26 #include <List.h>
27 #include <ListIterator.h>
28 #include <String.h>
29 #include <MpiProxy.h>
30 #include "MpiHost.h"
31 
33 {
34  return new MpiHost();
35 }
36 
38 {
39 }
40 
42  char ***argv)
43 {
44  // Verify input arguments
45  if ((*argc) < 2)
46  {
47  ERROR("invalid number of arguments given");
48  return MPI_ERR_ARG;
49  }
50 
51  // Add ourselves as the master node
52  Node *master = new Node;
53  master->ipAddress = 0;
54  master->udpPort = 0;
55  master->coreId = 0;
56 
57  // Register the master
58  if (!m_nodes.insert(master))
59  {
60  ERROR("failed to add master Node object");
61  return MPI_ERR_IO;
62  }
63 
64  // Read list of hosts from the given file
65  const Result hostsResult = parseHostsFile((*argv)[1]);
66  if (hostsResult != MPI_SUCCESS)
67  {
68  ERROR("failed to parse hosts file at path " << (*argv)[1] <<
69  ": result = " << (int) hostsResult);
70  return hostsResult;
71  }
72 
73  // Pass the rest of the arguments to the user program
74  (*argc) -= 1;
75  (*argv)[1] = (*argv)[0];
76  (*argv) += 1;
77 
78  // Create UDP socket
79  m_sock = socket(AF_INET, SOCK_DGRAM, 0);
80  if (m_sock < 0)
81  {
82  ERROR("failed to create UDP socket: " << strerror(errno));
83  return MPI_ERR_IO;
84  }
85 
86  // Prepare local address and port to bind to
87  struct sockaddr_in addr;
88  memset((char *)&addr, 0, sizeof(addr));
89  addr.sin_family = AF_INET;
90  addr.sin_addr.s_addr = htonl(INADDR_ANY);
91  addr.sin_port = htons(0);
92 
93  // Bind the UDP socket
94  int bindResult = bind(m_sock, (struct sockaddr *) &addr, sizeof(addr));
95  if (bindResult < 0)
96  {
97  ERROR("failed to bind UDP socket: " << strerror(errno));
98  return MPI_ERR_IO;
99  }
100 
101  // Launch remote programs
102  return startProcesses(*argc, *argv);
103 }
104 
106 {
107  // Loop all nodes
108  for (Size i = 1; i < m_nodes.count(); i++)
109  {
110  static u8 packet[MpiProxy::MaximumPacketSize];
111  Size packetSize = sizeof(MpiProxy::Header);
112 
113  // Send terminate request to the remote node
114  MpiProxy::Header *hdr = (MpiProxy::Header *) packet;
116  hdr->coreId = m_nodes[i]->coreId;
117  hdr->rankId = i;
118 
119  // Send the packet
120  const Result sendResult = sendPacket(i, packet, sizeof(MpiProxy::Header));
121  if (sendResult != MPI_SUCCESS)
122  {
123  ERROR("failed to send packet to nodeId " << i << ": result = " << (int) sendResult);
124  return sendResult;
125  }
126 
127  // Wait for reply
128  const Result recvResult = receivePacket(i, MpiProxy::MpiOpTerminate, packet, packetSize);
129  if (recvResult != MPI_SUCCESS)
130  {
131  ERROR("failed to receive UDP packet for rankId = " << i << ": result = " << (int) recvResult);
132  return recvResult;
133  }
134 
135  // The packet must be a terminate response
136  const MpiProxy::Header *header = (const MpiProxy::Header *) packet;
137  if (header->operation != MpiProxy::MpiOpTerminate)
138  {
139  ERROR("invalid response received: op = " << header->operation);
140  continue;
141  }
142 
143  // Verify the result code
144  if (header->result != MPI_SUCCESS)
145  {
146  ERROR("rankId " << i << " failed to terminate with result = " << header->result);
147  continue;
148  }
149 
150  NOTICE("rankId " << i << " terminated");
151  }
152 
153  return MPI_SUCCESS;
154 }
155 
157  int *rank)
158 {
159  *rank = 0;
160  return MPI_SUCCESS;
161 }
162 
164  int *size)
165 {
166  *size = m_nodes.count();
167  return MPI_SUCCESS;
168 }
169 
171  int count,
172  MPI_Datatype datatype,
173  int dest,
174  int tag,
175  MPI_Comm comm)
176 {
177  Size datasize = 0;
178 
179  // Get datatype size
180  switch (datatype)
181  {
182  case MPI_INT:
183  datasize = sizeof(int);
184  break;
185 
186  case MPI_UNSIGNED_CHAR:
187  datasize = sizeof(u8);
188  break;
189 
190  default: {
191  ERROR("unsupported datatype = " << (int) datatype);
192  return MPI_ERR_ARG;
193  }
194  }
195 
196  // Large payloads are not yet supported
197  if ((count * datasize) + sizeof(MpiProxy::Header) > MpiProxy::MaximumPacketSize)
198  {
199  ERROR("data count too high: maximum is " <<
201  return MPI_ERR_ARG;
202  }
203 
204  // Find the destination node
205  const Node *node = m_nodes.get(dest);
206  if (node == ZERO)
207  {
208  ERROR("nodeId " << dest << " not found");
209  return MPI_ERR_ARG;
210  }
211 
212  // Construct packet to send
214  MpiProxy::Header *hdr = (MpiProxy::Header *) packet;
216  hdr->result = 0;
217  hdr->coreId = node->coreId;
218  hdr->rankId = dest;
219  hdr->datatype = datatype;
220  hdr->datacount = count;
221 
222  // Append payload after the header
223  MemoryBlock::copy(packet + sizeof(MpiProxy::Header), buf, count * datasize);
224 
225  // Send the packet
226  const Result sendResult = sendPacket(dest, packet, sizeof(MpiProxy::Header) + (count * datasize));
227  if (sendResult != MPI_SUCCESS)
228  {
229  ERROR("failed to send packet to nodeId " << dest << ": result = " << (int) sendResult);
230  return sendResult;
231  }
232 
233  return MPI_SUCCESS;
234 }
235 
237  int count,
238  MPI_Datatype datatype,
239  int source,
240  int tag,
241  MPI_Comm comm,
242  MPI_Status *status)
243 {
244  static u8 packet[MpiProxy::MaximumPacketSize];
245 
246  // Find the source node
247  const Node *node = m_nodes.get(source);
248  if (node == ZERO)
249  {
250  ERROR("nodeId " << source << " not found");
251  return MPI_ERR_RANK;
252  }
253 
254  // Send receive data request to the remote node
255  MpiProxy::Header *hdr = (MpiProxy::Header *) packet;
257  hdr->coreId = node->coreId;
258  hdr->rankId = source;
259  hdr->datatype = datatype;
260  hdr->datacount = count;
261 
262  // Send the packet
263  const Result sendResult = sendPacket(source, packet, sizeof(MpiProxy::Header));
264  if (sendResult != MPI_SUCCESS)
265  {
266  ERROR("failed to send packet to nodeId " << source << ": result = " << (int) sendResult);
267  return sendResult;
268  }
269 
270  // Now receive the data response(s)
271  for (int i = 0; i < count;)
272  {
273  Size packetSize = sizeof(packet);
274 
275  // Receive data packet from the source node
276  const Result recvResult = receivePacket(source, MpiProxy::MpiOpRecv, packet, packetSize);
277  if (recvResult != MPI_SUCCESS)
278  {
279  ERROR("failed to receive UDP packet for rankId = " << source << ": result = " << (int) recvResult);
280  return recvResult;
281  }
282 
283  // The packet must be a data response
284  const MpiProxy::Header *header = (const MpiProxy::Header *) packet;
285  if (header->operation != MpiProxy::MpiOpRecv)
286  {
287  ERROR("invalid response received: op = " << header->operation);
288  continue;
289  }
290 
291  // Process all the received data
292  for (Size j = 0; j < header->datacount; j++, i++)
293  {
294  const u8 *data = ((const u8 *)(header + 1)) + j;
295 
296  switch (datatype)
297  {
298  case MPI_INT:
299  *(((int *) buf) + i) = *(int *)(data);
300  break;
301 
302  case MPI_UNSIGNED_CHAR:
303  *(((u8 *) buf) + i) = *data;
304  break;
305 
306  default:
308  }
309  }
310  }
311 
312  return MPI_SUCCESS;
313 }
314 
316 {
317  struct stat st;
318  FILE *fp;
319 
320  DEBUG("hostsfile = " << hostsfile);
321 
322  if (stat(hostsfile, &st) != 0)
323  {
324  ERROR("failed to stat() `" << hostsfile << "': " << strerror(errno));
325  return MPI_ERR_IO;
326  }
327 
328  // Open file
329  if ((fp = fopen(hostsfile, "r")) == NULL)
330  {
331  ERROR("failed to fopen() `" << hostsfile << "': " << strerror(errno));
332  return MPI_ERR_IO;
333  }
334 
335  // Allocate buffer storage
336  char *contents = new char[st.st_size + 1];
337  if (!contents)
338  {
339  ERROR("failed to allocate memory buffer for hostsfile: " << strerror(errno));
340  return MPI_ERR_NO_MEM;
341  }
342 
343  // Read the entire file into memory
344  if (fread(contents, st.st_size, 1, fp) != (size_t) 1U)
345  {
346  ERROR("failed to fread() `" << hostsfile << "': " << strerror(errno));
347  fclose(fp);
348  return MPI_ERR_IO;
349  }
350  fclose(fp);
351 
352  // Null terminate
353  contents[st.st_size] = 0;
354 
355  // Parse it into lines
356  String contentString(contents);
357  List<String> lines = contentString.split('\n');
358 
359  // Add each line as IP address of Execute each command
360  for (ListIterator<String> i(lines); i.hasCurrent(); i++)
361  {
362  // Skip comment lines
363  if (i.current()[0] == '#')
364  {
365  continue;
366  }
367 
368  List<String> nodeLine = i.current().split(':');
369  Size idx;
370 
371  // Nodes must be listed in the format: <ip>:<port>:<core>
372  if (nodeLine.count() != 3)
373  {
374  ERROR("invalid host format '" << *i.current() << "' in hosts file at " << hostsfile);
375  delete[] contents;
376  return MPI_ERR_ARG;
377  }
378 
379  Node *node = new Node();
380  if (!node)
381  {
382  ERROR("failed to allocate Node object: " << strerror(errno));
383  delete[] contents;
384  return MPI_ERR_NO_MEM;
385  }
386 
387  // Add the node
388  node->ipAddress = inet_addr(*nodeLine[0]);
389  node->udpPort = atoi(*nodeLine[1]);
390  node->coreId = atoi(*nodeLine[2]);
391 
392  if (!m_nodes.insert(idx, node))
393  {
394  ERROR("failed to insert Node object");
395  delete[] contents;
396  return MPI_ERR_IO;
397  }
398 
399  // Add packet buffer list
400  List<Packet *> *lst = new List<Packet *>();
401  if (!lst)
402  {
403  ERROR("failed to allocate List<..> object: " << strerror(errno));
404  delete[] contents;
405  return MPI_ERR_NO_MEM;
406  }
407  m_packetBuffers.insertAt(idx, lst);
408 
409  DEBUG("m_nodes[" << idx << "]: ip = " << *nodeLine[0] << ", port = " << *nodeLine[1] <<
410  ", core = " << *nodeLine[2]);
411  }
412 
413  // Cleanup
414  delete[] contents;
415  return MPI_SUCCESS;
416 }
417 
419  char **argv)
420 {
421  const Size NumOfParallelStart = 32;
422  static u8 packet[MpiProxy::MaximumPacketSize];
423  MpiProxy::Header *hdr = (MpiProxy::Header *) packet;
424  String cmdline;
425  Size startIndex = 1, startCount = 0;
426 
427  DEBUG("argc = " << argc);
428 
429  // First add the program name
430  cmdline << basename(argv[0]);
431  if (argc > 1)
432  {
433  cmdline << " ";
434  }
435 
436  // Append any extra arguments
437  for (int i = 1; i < argc; i++)
438  {
439  cmdline << argv[i];
440 
441  if (i != argc - 1)
442  {
443  cmdline << " ";
444  }
445  }
446 
447  // Start remote processes with the constructed command line
448  NOTICE("cmdline = " << *cmdline);
449 
450  // Send out packets to all the hosts
451  while (startIndex < m_nodes.count())
452  {
453  const Size receiveIndex = startIndex;
454 
455  // Limit the number of parallel requests
456  while (startIndex < m_nodes.count() && startCount < NumOfParallelStart)
457  {
458  in_addr nodeAddr;
459  nodeAddr.s_addr = m_nodes[startIndex]->ipAddress;
460 
461  NOTICE("nodes[" << startIndex << "] = " << inet_ntoa(nodeAddr) <<
462  ":" << m_nodes[startIndex]->udpPort << ":" << m_nodes[startIndex]->coreId);
463 
464  // Construct packet to send
466  hdr->result = 0;
467  hdr->rankId = startIndex;
468  hdr->coreId = m_nodes[startIndex]->coreId;
469  hdr->coreCount = m_nodes.count();
470 
471  // Append command-line after the header
472  MemoryBlock::copy((char *)packet + sizeof(MpiProxy::Header), *cmdline,
473  sizeof(packet) - sizeof(MpiProxy::Header));
474 
475  // Send the packet
476  const Result sendResult = sendPacket(startIndex, packet, sizeof(MpiProxy::Header) + cmdline.length());
477  if (sendResult != MPI_SUCCESS)
478  {
479  ERROR("failed to send packet to nodeId " << startIndex << ": result = " << (int) sendResult);
480  return sendResult;
481  }
482  startIndex++;
483  startCount++;
484  }
485 
486  // Wait for acknowledge of each node
487  for (Size i = receiveIndex; i < startIndex; i++)
488  {
489  Size sz;
490  sz = sizeof(MpiProxy::Header);
491 
492  const Result recvResult = receivePacket(i, MpiProxy::MpiOpExec, &packet, sz);
493  if (recvResult != MPI_SUCCESS)
494  {
495  ERROR("failed to receive acknowledge for MpiOpExec from nodeId " <<
496  i << ": result = " << (int) recvResult);
497  return recvResult;
498  }
499  }
500  startCount = 0;
501  }
502 
503  return MPI_SUCCESS;
504 }
505 
507  const void *packet,
508  const Size size) const
509 {
510  DEBUG("nodeId = " << nodeId << " size = " << size);
511 
512  const Node *node = m_nodes.get(nodeId);
513  if (node == ZERO)
514  {
515  ERROR("nodeId " << nodeId << " not found");
516  return MPI_ERR_ARG;
517  }
518 
519  // Prepare UDP broadcast datagram
520  struct sockaddr_in addr;
521  addr.sin_family = AF_INET;
522  addr.sin_addr.s_addr = node->ipAddress;
523  addr.sin_port = htons(node->udpPort);
524 
525  // Send the packet
526  int result = ::sendto(m_sock, packet, size, 0,
527  (const sockaddr *) &addr, sizeof(addr));
528  if (result <= 0)
529  {
530  ERROR("failed to send UDP datagram: " << strerror(errno));
531  return MPI_ERR_IO;
532  }
533 
534  return MPI_SUCCESS;
535 }
536 
538  const MpiProxy::Operation operation,
539  void *packet,
540  Size & size)
541 {
542  // Lookup the given node
543  const Node *node = m_nodes.get(nodeId);
544  if (node == ZERO)
545  {
546  ERROR("nodeId " << nodeId << " not found");
547  return MPI_ERR_ARG;
548  }
549 
550  in_addr nodeAddr;
551  nodeAddr.s_addr = node->ipAddress;
552  DEBUG("nodeId = " << nodeId << " addr = " << inet_ntoa(nodeAddr) <<
553  " operation = " << (int) operation << " size = " << size);
554 
555  // Process buffered packets first
556  for (ListIterator<Packet *> i(m_packetBuffers[nodeId]); i.hasCurrent(); i++)
557  {
558  Packet *pkt = i.current();
559  const MpiProxy::Header *hdr = (const MpiProxy::Header *) pkt->data;
560 
561  if (hdr->operation == operation)
562  {
563  MemoryBlock::copy(packet, pkt->data, pkt->size);
564  size = pkt->size;
565  delete[] pkt->data;
566  delete pkt;
567  i.remove();
568  return MPI_SUCCESS;
569  }
570  }
571 
572 
573  // Keep receiving new packets until we have a matching packet
574  while (true)
575  {
576  struct sockaddr_in addr;
577  socklen_t len = sizeof(addr);
578  const Size recvSize = size;
579 
580  // Receive UDP datagram
581  int r = recvfrom(m_sock, packet, recvSize, 0,
582  (struct sockaddr *) &addr, &len);
583  if (r < 0)
584  {
585  ERROR("failed to receive UDP datagram on socket " << m_sock << ": " << strerror(errno));
586  return MPI_ERR_IO;
587  }
588 
589  const MpiProxy::Header *hdr = (const MpiProxy::Header *) packet;
590 
591  DEBUG("received " << r << " bytes from " << inet_ntoa(addr.sin_addr) <<
592  ":" << htons(addr.sin_port) << " with coreId = " << hdr->coreId <<
593  " rankId = " << hdr->rankId);
594 
595  // Is this packet targeted for the given node?
596  if (addr.sin_addr.s_addr == node->ipAddress &&
597  htons(addr.sin_port) == node->udpPort &&
598  hdr->coreId == node->coreId)
599  {
600  // Verify the MPI operation
601  if (hdr->operation != operation)
602  {
603  ERROR("invalid MPI operation received in packet from node" << nodeId <<
604  " (" << inet_ntoa(nodeAddr) << "): " << (int) hdr->operation <<
605  " != " << (int) operation);
606  return MPI_ERR_IO;
607  }
608 
609  DEBUG("done");
610  size = r;
611  return MPI_SUCCESS;
612  }
613  // Add the packet to internal buffers for later retrieval
614  else
615  {
616  Size otherNodeId = 0;
617 
618  // Find the corresponding node
619  for (Size i = 0; i < m_nodes.count(); i++)
620  {
621  if (addr.sin_addr.s_addr == m_nodes[i]->ipAddress &&
622  htons(addr.sin_port) == m_nodes[i]->udpPort &&
623  hdr->coreId == m_nodes[i]->coreId)
624  {
625  otherNodeId = i;
626  break;
627  }
628  }
629 
630  if (otherNodeId == 0)
631  {
632  ERROR("nodeId not found for packet from " << inet_ntoa(addr.sin_addr) <<
633  " at port " << htons(addr.sin_port));
634  }
635  else
636  {
637  Packet *pkt = new Packet;
638  if (!pkt)
639  {
640  ERROR("failed to allocate Packet struct for buffering: " << strerror(errno));
641  return MPI_ERR_NO_MEM;
642  }
643 
644  pkt->data = new u8[r];
645  if (!pkt->data)
646  {
647  ERROR("failed to allocate memory for buffered packet: " << strerror(errno));
648  return MPI_ERR_NO_MEM;
649  }
650 
651  MemoryBlock::copy(pkt->data, hdr, r);
652  pkt->size = r;
653  m_packetBuffers[otherNodeId]->append(pkt);
654  }
655  }
656  }
657 
658  return MPI_SUCCESS;
659 }
MpiHost::m_nodes
Index< Node, MaximumNodes > m_nodes
Contains all known nodes that participate in the computation.
Definition: MpiHost.h:210
MpiHost::Packet::data
u8 * data
Definition: MpiHost.h:63
stat::st_size
off_t st_size
For regular files, the file size in bytes.
Definition: stat.h:226
stat
The <sys/stat.h> header shall define the stat structure.
Definition: stat.h:176
MemoryBlock::copy
static Size copy(void *dest, const void *src, Size count)
Copy memory from one place to another.
Definition: MemoryBlock.cpp:36
MPI_INT
@ MPI_INT
Definition: mpi.h:51
MpiProxy::Header::rankId
u16 rankId
Definition: MpiProxy.h:86
MpiHost.h
socklen_t
Size socklen_t
Definition: socket.h:50
errno
C int errno
The lvalue errno is used by many functions to return error values.
NOTICE
#define NOTICE(msg)
Output a notice message.
Definition: Log.h:75
MPI_ERR_RANK
@ MPI_ERR_RANK
Definition: mpi.h:79
MpiHost::receivePacket
Result receivePacket(const Size nodeId, const MpiProxy::Operation operation, void *packet, Size &size)
Receive UDP packet from remote node.
Definition: MpiHost.cpp:537
String::length
Size length() const
Same as count().
Definition: String.cpp:105
MPI_ERR_NO_MEM
@ MPI_ERR_NO_MEM
Definition: mpi.h:112
fopen
FILE * fopen(const char *filename, const char *mode)
Open a stream.
Definition: fopen.cpp:24
string.h
MpiProxy::Header::coreId
u16 coreId
Definition: MpiProxy.h:87
MPI_SUCCESS
@ MPI_SUCCESS
Definition: mpi.h:73
MPI_Comm
uint MPI_Comm
Communicator identifier.
Definition: mpi.h:38
MpiHost::initialize
virtual Result initialize(int *argc, char ***argv)
Initialize the backend.
Definition: MpiHost.cpp:41
MpiBackend::Result
int Result
Result code.
Definition: MpiBackend.h:47
String
Abstraction of strings.
Definition: String.h:41
atoi
C int atoi(const char *nptr)
Convert a string to an integer.
Definition: atoi.cpp:21
libgen.h
MpiProxy::MpiOpExec
@ MpiOpExec
Definition: MpiProxy.h:75
MpiHost::startProcesses
Result startProcesses(int argc, char **argv)
Start remote processes.
Definition: MpiHost.cpp:418
MPI_ERR_IO
@ MPI_ERR_IO
Definition: mpi.h:108
List::count
Size count() const
Get the number of items on the list.
Definition: List.h:402
MpiHost::Packet::size
Size size
< Payload data
Definition: MpiHost.h:64
MpiHost
Implements a MPI backend for the host OS which communicates with mpiproxy servers.
Definition: MpiHost.h:39
MPI_Status
uint MPI_Status
Status holder.
Definition: mpi.h:41
sockaddr
Defines a socket address and port pair.
Definition: socket.h:35
MpiHost::receive
virtual Result receive(void *buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Status *status)
Synchronous receive data.
Definition: MpiHost.cpp:236
MpiHost::sendPacket
Result sendPacket(const Size nodeId, const void *packet, const Size size) const
Send UDP packet to a remote node.
Definition: MpiHost.cpp:506
Log.h
MpiProxy::MaximumPacketSize
static const Size MaximumPacketSize
Maximum size of packet payload.
Definition: MpiProxy.h:66
String::split
List< String > split(const char delimiter) const
Split the String into parts separated by a delimiter.
Definition: String.cpp:408
recvfrom
C int recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *addr, socklen_t addrlen)
Receive a single datagram from a socket.
Definition: recvfrom.cpp:25
MPI_ERR_ARG
@ MPI_ERR_ARG
Definition: mpi.h:86
MpiProxy::Header
Packet payload header for MPI messages via IP/UDP.
Definition: MpiProxy.h:82
MpiHost::Node::udpPort
u16 udpPort
< IP address of the node
Definition: MpiHost.h:54
DEBUG
#define DEBUG(msg)
Output a debug message to standard output.
Definition: Log.h:89
basename
char * basename(char *path)
Return the last component of a pathname.
Definition: basename.cpp:21
ListIterator::hasCurrent
virtual bool hasCurrent() const
Check if there is a current item on the List.
Definition: ListIterator.h:104
header
SystemDescriptorHeader header
Definition: IntelACPI.h:63
MpiProxy::Header::datatype
u16 datatype
Definition: MpiProxy.h:92
stdio.h
strerror
char * strerror(int errnum)
The strerror function maps the number in errnum to a message string.
Definition: strerror.cpp:20
NULL
#define NULL
NULL means zero.
Definition: Macros.h:39
MpiHost::send
virtual Result send(const void *buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm)
Synchronous send data.
Definition: MpiHost.cpp:170
Size
unsigned int Size
Any sane size indicator cannot go negative.
Definition: Types.h:128
sendto
C int sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *addr, socklen_t addrlen)
Send a single datagram to a remote host.
Definition: sendto.cpp:25
AbstractFactory::create
static T * create()
Abstract function to create an instance of T.
MpiProxy::MpiOpRecv
@ MpiOpRecv
Definition: MpiProxy.h:74
MpiHost::Node
Describes a remote CPU node accessible via MPI.
Definition: MpiHost.h:51
MPI_Datatype
MPI_Datatype
Named Predefined Datatypes.
Definition: mpi.h:46
stat
int stat(const char *path, struct stat *buf)
Get file status.
Definition: stat.cpp:25
MpiHost::MpiHost
MpiHost()
Constructor.
Definition: MpiHost.cpp:37
MpiProxy::Header::datacount
u32 datacount
Definition: MpiProxy.h:94
MpiHost::m_packetBuffers
Index< List< Packet * >, MaximumNodes > m_packetBuffers
Buffers incoming packets for later processing.
Definition: MpiHost.h:213
MPI_UNSIGNED_CHAR
@ MPI_UNSIGNED_CHAR
Definition: mpi.h:52
stat.h
MpiHost::m_sock
int m_sock
UDP socket for communicating with remote nodes.
Definition: MpiHost.h:207
ListIterator.h
MpiBackend
Represents a Message Passing Interface (MPI) implementation backend.
Definition: MpiBackend.h:36
MpiProxy::MpiOpTerminate
@ MpiOpTerminate
Definition: MpiProxy.h:76
MpiProxy::Header::result
u8 result
Definition: MpiProxy.h:85
ERROR
#define ERROR(msg)
Output an error message.
Definition: Log.h:61
MpiHost::terminate
virtual Result terminate()
Terminate the backend.
Definition: MpiHost.cpp:105
MpiHost::Node::ipAddress
in_addr_t ipAddress
Definition: MpiHost.h:53
u8
unsigned char u8
Unsigned 8-bit number.
Definition: Types.h:59
MpiProxy::Header::coreCount
u16 coreCount
Definition: MpiProxy.h:91
socket.h
MpiProxy.h
String.h
memset
void * memset(void *dest, int ch, size_t count)
Fill memory with a constant byte.
Definition: memset.cpp:20
MpiHost::Node::coreId
u32 coreId
< UDP port of the node
Definition: MpiHost.h:55
MpiHost::Packet
Describes data received via UDP.
Definition: MpiHost.h:61
fread
size_t fread(void *ptr, size_t size, size_t nitems, FILE *stream)
Binary input.
Definition: fread.cpp:24
List< String >
FILE
A structure containing information about a file.
Definition: stdio.h:60
stdlib.h
fclose
int fclose(FILE *stream)
Close a stream.
Definition: fclose.cpp:23
MpiProxy::Header::operation
u8 operation
Definition: MpiProxy.h:84
MpiProxy::MpiOpSend
@ MpiOpSend
Definition: MpiProxy.h:73
MpiHost::getCommSize
virtual Result getCommSize(MPI_Comm comm, int *size)
Retrieve communication size (total cores)
Definition: MpiHost.cpp:163
ZERO
#define ZERO
Zero value.
Definition: Macros.h:43
coreId
u8 coreId
Definition: IntelACPI.h:64
MPI_ERR_UNSUPPORTED_DATAREP
@ MPI_ERR_UNSUPPORTED_DATAREP
Definition: mpi.h:128
MpiProxy::Operation
Operation
Encodes various MPI operations.
Definition: MpiProxy.h:71
MpiHost::parseHostsFile
Result parseHostsFile(const char *hostsfile)
Parse the given hosts file.
Definition: MpiHost.cpp:315
MpiHost::getCommRank
virtual Result getCommRank(MPI_Comm comm, int *rank)
Retrieve communication rank (core id)
Definition: MpiHost.cpp:156
errno.h
List.h
ListIterator
Iterate through a List.
Definition: ListIterator.h:37