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