1 // Copyright 2009-2021 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
3 
4 #include "MPICommon.h"
5 
6 namespace mpicommon {
7 static std::mutex mpiMutex;
8 
9 bool mpiIsThreaded = false;
10 
11 Group world;
12 Group worker;
13 
14 // Group definitions ////////////////////////////////////////////////////////
15 
16 /*! constructor. sets the 'comm', 'rank', and 'size' fields */
Group(MPI_Comm initComm)17 Group::Group(MPI_Comm initComm)
18 {
19   setTo(initComm);
20 }
21 
22 /*! constructor. sets the 'comm', 'rank', and 'size' fields */
Group(const Group & other)23 Group::Group(const Group &other)
24     : containsMe(other.containsMe),
25       comm(other.comm),
26       rank(other.rank),
27       size(other.size)
28 {}
29 
makeIntraComm()30 void Group::makeIntraComm()
31 {
32   MPI_CALL(Comm_rank(comm, &rank));
33   MPI_CALL(Comm_size(comm, &size));
34   containsMe = true;
35 }
36 
makeIntraComm(MPI_Comm _comm)37 void Group::makeIntraComm(MPI_Comm _comm)
38 {
39   this->comm = _comm;
40   makeIntraComm();
41 }
42 
makeInterComm()43 void Group::makeInterComm()
44 {
45   containsMe = false;
46   rank = MPI_ROOT;
47   MPI_CALL(Comm_remote_size(comm, &size));
48 }
49 
makeInterComm(MPI_Comm _comm)50 void Group::makeInterComm(MPI_Comm _comm)
51 {
52   this->comm = _comm;
53   makeInterComm();
54 }
55 
56 /*! set to given intercomm, and properly set size, root, etc */
setTo(MPI_Comm _comm)57 void Group::setTo(MPI_Comm _comm)
58 {
59   if (this->comm == _comm)
60     return;
61 
62   this->comm = _comm;
63   if (comm == MPI_COMM_NULL) {
64     rank = size = -1;
65   } else {
66     int isInter;
67     MPI_CALL(Comm_test_inter(comm, &isInter));
68     if (isInter)
69       makeInterComm(comm);
70     else
71       makeIntraComm(comm);
72   }
73 }
74 
75 /*! do an MPI_Comm_dup, and return duplicated communicator */
dup() const76 Group Group::dup() const
77 {
78   MPI_Comm duped;
79   MPI_CALL(Comm_dup(comm, &duped));
80   return Group(duped);
81 }
82 
83 // Message definitions //////////////////////////////////////////////////////
84 
85 /*! create a new message with given amount of bytes in storage */
Message(size_t size)86 Message::Message(size_t size) : size(size)
87 {
88   data = (rkcommon::byte_t *)malloc(size);
89 }
90 
91 /*! create a new message with given amount of storage, and copy
92   memory from the given address to it */
Message(const void * copyMem,size_t size)93 Message::Message(const void *copyMem, size_t size) : Message(size)
94 {
95   if (copyMem == nullptr)
96     OSPRAY_THROW("#mpicommon: cannot create a message from a null pointer!");
97 
98   memcpy(data, copyMem, size);
99 }
100 
101 /*! create a new message (addressed to given comm:rank) with given
102     amount of storage, and copy memory from the given address to
103     it */
Message(MPI_Comm comm,int rank,const void * copyMem,size_t size)104 Message::Message(MPI_Comm comm, int rank, const void *copyMem, size_t size)
105     : Message(copyMem, size)
106 {
107   this->comm = comm;
108   this->rank = rank;
109 }
110 
111 /*! destruct message and free allocated memory */
~Message()112 Message::~Message()
113 {
114   free(data);
115 }
116 
isValid() const117 bool Message::isValid() const
118 {
119   return comm != MPI_COMM_NULL && rank >= 0;
120 }
121 
init(int * ac,const char ** av,bool useCommWorld)122 bool init(int *ac, const char **av, bool useCommWorld)
123 {
124   int initialized = false;
125   MPI_CALL(Initialized(&initialized));
126 
127   int provided = 0;
128   if (!initialized) {
129     /* MPI not initialized by the app - it's up to us */
130     MPI_CALL(Init_thread(
131         ac, const_cast<char ***>(&av), MPI_THREAD_MULTIPLE, &provided));
132   } else {
133     /* MPI was already initialized by the app that called us! */
134     MPI_Query_thread(&provided);
135   }
136   if (provided != MPI_THREAD_MULTIPLE && provided != MPI_THREAD_SERIALIZED) {
137     throw std::runtime_error(
138         "MPI initialization error: The MPI runtime must"
139         " support either MPI_THREAD_MULTIPLE or"
140         " MPI_THREAD_SERIALIZED.");
141   }
142   mpiIsThreaded = provided == MPI_THREAD_MULTIPLE;
143 
144   if (useCommWorld) {
145     world.setTo(MPI_COMM_WORLD);
146   }
147   return !initialized;
148 }
149 
isManagedObject(OSPDataType type)150 bool isManagedObject(OSPDataType type)
151 {
152   return type & OSP_OBJECT;
153 }
154 
155 } // namespace mpicommon
156