00001
00002
00003
00004
00005 #include "BcpConfig.h"
00006 #if defined(COIN_HAS_MPI)
00007
00008 #include <cstdio>
00009 #include <cmath>
00010
00011 #define MPICH_SKIP_MPICXX
00012 #include <mpi.h>
00013
00014 #include "BCP_error.hpp"
00015 #include "BCP_process.hpp"
00016 #include "BCP_buffer.hpp"
00017 #include "BCP_vector.hpp"
00018 #include "BCP_message_mpi.hpp"
00019
00020 bool BCP_mpi_environment::mpi_init_called = false;
00021 int BCP_mpi_environment::num_proc = 0;
00022 int BCP_mpi_environment::seqproc = 0;
00023
00024
00025
00026 int BCP_mpi_environment::is_mpi(int argc, char *argv[])
00027 {
00028 int pid;
00029 if (! mpi_init_called) {
00030 MPI_Init(&argc, &argv);
00031
00032
00033 if (MPI_Comm_size(MPI_COMM_WORLD, &num_proc) != MPI_SUCCESS) {
00034
00035 return -1;
00036 }
00037 mpi_init_called = true;
00038 }
00039 MPI_Comm_rank(MPI_COMM_WORLD, &pid);
00040 return pid;
00041 }
00042
00043
00044
00045
00046 BCP_mpi_environment::BCP_mpi_environment(int argc, char *argv[])
00047 {
00048
00049 is_mpi(argc, argv);
00050 }
00051
00052
00053
00054 BCP_mpi_environment::~BCP_mpi_environment()
00055 {
00056 MPI_Finalize();
00057 mpi_init_called = false;
00058 }
00059
00060
00061
00062 void
00063 BCP_mpi_environment::check_error(const int code, const char* str) const
00064 {
00065 if (code != MPI_SUCCESS){
00066 printf("%s returned error code %i.\n", str, code);
00067 throw BCP_fatal_error(" ERROR in mpi -- exiting.\n");
00068 }
00069 }
00070
00071
00072
00073 int
00074 BCP_mpi_environment::register_process(USER_initialize* user_init)
00075 {
00076 int pid;
00077 MPI_Comm_rank(MPI_COMM_WORLD, &pid);
00078 setvbuf(stdout, (char *)NULL, _IOLBF, 0);
00079 return pid;
00080 }
00081
00082 int
00083 BCP_mpi_environment::parent_process()
00084 {
00085 int pid;
00086 MPI_Comm_rank(MPI_COMM_WORLD, &pid);
00087 if (pid == 0)
00088
00089 return -1;
00090
00091 return 0;
00092 }
00093
00094 bool
00095 BCP_mpi_environment::alive(const int pid)
00096 {
00097
00098
00099 return true;
00100 }
00101
00102 const int*
00103 BCP_mpi_environment::alive(int num, const int* pids)
00104 {
00105
00106 return NULL;
00107 }
00108
00109
00110
00111 void
00112 BCP_mpi_environment::send(const int target, const BCP_message_tag tag)
00113 {
00114
00115 void * buf = NULL;
00116 check_error(MPI_Send(&buf, 0, MPI_CHAR,
00117 target, tag, MPI_COMM_WORLD),"MPI_Send");
00118 }
00119
00120 void
00121 BCP_mpi_environment::send(const int target,
00122 const BCP_message_tag tag, const BCP_buffer& buf)
00123 {
00124 check_error(MPI_Send(const_cast<char*>(buf.data()), buf.size(), MPI_CHAR,
00125 target, tag, MPI_COMM_WORLD),"MPI_Send");
00126 }
00127
00128
00129
00130 void
00131 BCP_mpi_environment::multicast(int num, const int* targets,
00132 const BCP_message_tag tag)
00133 {
00134 void * buf = NULL;
00135 for (int i = 0; i < num; ++i) {
00136 check_error(MPI_Send(&buf, 0, MPI_CHAR,
00137 targets[i], tag, MPI_COMM_WORLD),"MPI_Send");
00138 }
00139 }
00140
00141 void
00142 BCP_mpi_environment::multicast(int num, const int* targets,
00143 const BCP_message_tag tag,
00144 const BCP_buffer& buf)
00145 {
00146 for (int i = 0; i < num; ++i) {
00147 check_error(MPI_Send(const_cast<char*>(buf.data()), buf.size(),
00148 MPI_CHAR, targets[i], tag, MPI_COMM_WORLD),
00149 "MPI_Send");
00150 }
00151 }
00152
00153
00154
00155 void
00156 BCP_mpi_environment::receive(const int source,
00157 const BCP_message_tag tag, BCP_buffer& buf,
00158 const double timeout)
00159 {
00160 buf.clear();
00161 buf._sender = -1;
00162 int pid = (source == BCP_AnyProcess ? MPI_ANY_SOURCE : source);
00163 int msgtag = (tag == BCP_Msg_AnyMessage ? MPI_ANY_TAG : tag);
00164 int flag = 0;
00165 MPI_Status status;
00166
00167 if (timeout < 0) {
00168 check_error(MPI_Probe(pid, msgtag, MPI_COMM_WORLD, &status),
00169 "MPI_Probe");
00170 flag = 1;
00171 } else {
00172 check_error(MPI_Iprobe(pid, msgtag, MPI_COMM_WORLD, &flag, &status),
00173 "MPI_Iprobe");
00174 }
00175
00176 if (!flag) {
00177 buf._msgtag = BCP_Msg_NoMessage;
00178 return;
00179 }
00180
00181 int bytes;
00182
00183 check_error(MPI_Get_count( &status, MPI_CHAR, &bytes ),"MPI_Get_Count");
00184 buf.make_fit(bytes);
00185 buf._msgtag = static_cast<BCP_message_tag>(status.MPI_TAG);
00186 buf._sender = status.MPI_SOURCE;
00187 buf._size = bytes;
00188
00189
00190 check_error(MPI_Recv(buf._data, bytes, MPI_CHAR,
00191 pid, msgtag, MPI_COMM_WORLD, &status),"MPI_Recv");
00192 }
00193
00194
00195
00196
00197
00198 bool
00199 BCP_mpi_environment::probe(const int source, const BCP_message_tag tag)
00200 {
00201 MPI_Status status;
00202
00203 int flag = 0;
00204 int pid = (source == BCP_AnyProcess ? MPI_ANY_SOURCE : source);
00205 int msgtag = (tag == BCP_Msg_AnyMessage ? MPI_ANY_TAG : tag);
00206 check_error(MPI_Iprobe(pid, msgtag, MPI_COMM_WORLD, &flag, &status),
00207 "MPI_Iprobe");
00208 return flag > 0;
00209 }
00210
00211
00212
00213 int
00214 BCP_mpi_environment::start_process(const BCP_string& exe, const bool debug)
00215 {
00216 #ifdef COIN_HAS_MPI2
00217
00218 printf("Sorry, MPI2 process spawning is not supported yet...\n");
00219 abort();
00220 #else
00221
00222 return ++seqproc;
00223 #endif
00224 }
00225
00226 int
00227 BCP_mpi_environment::start_process(const BCP_string& exe,
00228 const BCP_string& machine,
00229 const bool debug)
00230 {
00231 #ifdef COIN_HAS_MPI2
00232
00233 printf("Sorry, MPI2 process spawning is not supported yet...\n");
00234 abort();
00235 #else
00236
00237 return ++seqproc;
00238 #endif
00239 }
00240
00241 bool
00242 BCP_mpi_environment::start_processes(const BCP_string& exe,
00243 const int proc_num,
00244 const bool debug,
00245 int* ids)
00246 {
00247 #ifdef COIN_HAS_MPI2
00248
00249 printf("Sorry, MPI2 process spawning is not supported yet...\n");
00250 abort();
00251 #else
00252
00253 for (int i = 0; i < proc_num; ++i) {
00254 ids[i] = ++seqproc;
00255 }
00256 return true;
00257 #endif
00258 }
00259
00260 bool
00261 BCP_mpi_environment::start_processes(const BCP_string& exe,
00262 const int proc_num,
00263 const BCP_vec<BCP_string>& machines,
00264 const bool debug,
00265 int* ids)
00266 {
00267 #ifdef COIN_HAS_MPI2
00268
00269 printf("Sorry, MPI2 process spawning is not supported yet...\n");
00270 abort();
00271 #else
00272
00273 for (int i = 0; i < proc_num; ++i) {
00274 ids[i] = ++seqproc;
00275 }
00276 return true;
00277 #endif
00278 }
00279
00280 int BCP_mpi_environment::num_procs() {
00281 return num_proc;
00282 }
00283
00284
00285 #if 0
00286 struct MPIDI_BGLTS_Request {
00287 MPIDI_Message_match match;
00288 MPI_Datatype datatype;
00289 struct MPID_Datatype *datatype_ptr;
00290 int ca;
00291 char *userbuf;
00292 unsigned userbufcount;
00293 char *uebuf;
00294 unsigned uebuflen;
00295 MPID_Segment segment;
00296 MPIDI_BGLTS_REQUEST_STATE state;
00297 int type;
00298
00299 int msgtype;
00300
00301 BGLML_Message msgdata;
00302 char slack[300];
00303 struct MPID_Request *next;
00304 int cancel_pending;
00305 int dest_rank;
00306 int dest_tag;
00307 int dest_context_id;
00308 } bglts;
00309 #endif
00310
00311 #ifdef MPID_DEV_REQUEST_DECL
00312 int MPIDI_BGLTS_get_num_messages()
00313 {
00314 register MPID_Request * rreq = MPIDI_Process.recv_posted_head;
00315 register int cnt = 0;
00316 while (rreq != NULL) {
00317 ++cnt;
00318 rreq = rreq->bglts.next;
00319 }
00320 rreq = MPIDI_Process.recv_unexpected_head;
00321 while (rreq != NULL) {
00322 ++cnt;
00323 rreq = rreq->bglts.next;
00324 }
00325 return cnt;
00326 }
00327 #else
00328 int MPIDI_BGLTS_get_num_messages()
00329 {
00330 return -1;
00331 }
00332 #endif
00333
00334 #endif