4 #include "xbt/sysdep.h"
5 #include "xbt/xbt_portability.h"
8 int MPI_Init(int *argc, char ***argv) {
20 // right now this just exits the current node, should send abort signal to all
21 // hosts in the communicator;
22 int MPI_Abort(MPI_Comm comm, int errorcode) {
26 int MPI_Comm_size(MPI_Comm comm, int *size) {
27 int retval = MPI_SUCCESS;
30 retval = MPI_ERR_COMM;
31 } else if (NULL == size) {
40 int MPI_Comm_rank(MPI_Comm comm, int *rank) {
41 int retval = MPI_SUCCESS;
44 retval = MPI_ERR_COMM;
45 } else if (NULL == rank) {
48 *rank = smpi_comm_rank(comm, SIMIX_host_self());
55 int MPI_Comm_split(MPI_Comm comm, int color, int key, MPI_Comm *newcomm) {
56 int retval = MPI_SUCCESS;
57 m_host_t host = SIMIX_host_self();
58 int rank = smpi_comm_rank(comm, host);
59 smpi_mpi_comm_split_table_node_t *split_table;
60 split_table = xbt_malloc(sizeof(smpi_mpi_comm_split_table_node_t) * comm->size);
61 split_table[rank].color = color;
62 split_table[rank].key = key;
63 split_table[rank].host = host;
69 int MPI_Type_size(MPI_Datatype datatype, size_t *size) {
70 int retval = MPI_SUCCESS;
72 if (NULL == datatype) {
73 retval = MPI_ERR_TYPE;
74 } else if (NULL == size) {
77 *size = datatype->size;
83 int MPI_Wait(MPI_Request *request, MPI_Status *status) {
84 int retval = MPI_SUCCESS;
86 if (NULL == request) {
87 retval = MPI_ERR_REQUEST;
88 } else if (NULL == status) {
91 smpi_wait(*request, status);
97 int MPI_Waitall(int count, MPI_Request *requests, MPI_Status *statuses) {
98 int retval = MPI_SUCCESS;
100 if (NULL == requests) {
101 retval = MPI_ERR_REQUEST;
102 } else if (NULL == statuses) {
103 retval = MPI_ERR_ARG;
105 smpi_wait_all(count, requests, statuses);
108 return MPI_ERR_INTERN;
111 int MPI_Irecv(void *buf, int count, MPI_Datatype datatype, int src, int tag, MPI_Comm comm, MPI_Request *request) {
112 int retval = MPI_SUCCESS;
114 smpi_mpi_request_t *recvreq;
116 dst = smpi_comm_rank(comm, SIMIX_host_self());
117 retval = smpi_create_request(buf, count, datatype, src, dst, tag, comm, &recvreq);
118 if (NULL != recvreq) {
120 if (NULL != request) {
128 int MPI_Recv(void *buf, int count, MPI_Datatype datatype, int src, int tag, MPI_Comm comm, MPI_Status *status) {
129 int retval = MPI_SUCCESS;
131 smpi_mpi_request_t *recvreq;
133 dst = smpi_comm_rank(comm, SIMIX_host_self());
134 retval = smpi_create_request(buf, count, datatype, src, dst, tag, comm, &recvreq);
135 if (NULL != recvreq) {
137 smpi_wait(recvreq, status);
144 int MPI_Isend(void *buf, int count, MPI_Datatype datatype, int dst, int tag, MPI_Comm comm, MPI_Request *request) {
145 int retval = MPI_SUCCESS;
147 smpi_mpi_request_t *sendreq;
149 src = smpi_comm_rank(comm, SIMIX_host_self());
150 retval = smpi_create_request(buf, count, datatype, src, dst, tag, comm, &sendreq);
151 if (NULL != sendreq) {
153 if (NULL != request) {
161 int MPI_Send(void *buf, int count, MPI_Datatype datatype, int dst, int tag, MPI_Comm comm) {
162 int retval = MPI_SUCCESS;
164 smpi_mpi_request_t *sendreq;
166 src = smpi_comm_rank(comm, SIMIX_host_self());
167 retval = smpi_create_request(buf, count, datatype, src, dst, tag, comm, &sendreq);
168 if (NULL != sendreq) {
170 smpi_wait(sendreq, MPI_STATUS_IGNORE);
176 int MPI_Bcast(void *buf, int count, MPI_Datatype datatype, int root, MPI_Comm comm) {
179 smpi_mpi_request_t *request;
182 rank = smpi_comm_rank(comm, SIMIX_host_self());
185 smpi_create_request(buf, count, datatype, root, (rank + 1) % comm->size, 0, comm, &request);
186 if (comm->size > 2) {
187 request->fwdthrough = (rank - 1 + comm->size) % comm->size;
190 smpi_wait(request, MPI_STATUS_IGNORE);
192 smpi_create_request(buf, count, datatype, MPI_ANY_SOURCE, rank, 0, comm, &request);
193 if (NULL != request) {
195 smpi_wait(request, MPI_STATUS_IGNORE);
203 int MPI_Barrier(MPI_Comm comm) {
210 // FIXME: instead of everyone sending in order, might be a good idea to send to next...
211 int MPI_Alltoall(void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, int recvcount, MPI_Datatype recvtype, MPI_Comm comm) {
214 smpi_mpi_request_t **sendreqs, **recvreqs;
217 rank = smpi_comm_rank(comm, SIMIX_host_self());
219 sendreqs = xbt_malloc(sizeof(smpi_mpi_request_t*) * comm->size);
220 recvreqs = xbt_malloc(sizeof(smpi_mpi_request_t*) * comm->size);
222 for (i = 0; i < comm->size; i++) {
226 memcpy(recvbuf + recvtype->size * recvcount * i, sendbuf + sendtype->size * sendcount * i, recvtype->size * recvcount);
228 smpi_create_request(sendbuf + sendtype->size * sendcount * i, sendcount, sendtype, rank, i, 0, comm, sendreqs + i);
229 smpi_isend(sendreqs[i]);
230 smpi_create_request(recvbuf + recvtype->size * recvcount * i, recvcount, recvtype, i, rank, 0, comm, recvreqs + i);
231 smpi_irecv(recvreqs[i]);
235 smpi_wait_all_nostatus(comm->size, sendreqs);
236 smpi_wait_all_nostatus(comm->size, recvreqs);
245 // FIXME: mpi routines shouldn't call mpi routines, complexity belongs at a lower level
246 // also, there's probably a really clever way to overlap everything for this one...
247 int MPI_Allreduce(void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm) {
248 MPI_Reduce(sendbuf, recvbuf, count, datatype, op, 0, comm);
249 MPI_Bcast(recvbuf, count, datatype, 0, comm);
253 // FIXME: check if behavior defined when send/recv bufs are same...
254 int MPI_Reduce(void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, int root, MPI_Comm comm) {
257 smpi_mpi_request_t **requests;
261 rank = smpi_comm_rank(comm, SIMIX_host_self());
264 requests = xbt_malloc(sizeof(smpi_mpi_request_t*) * comm->size);
265 scratchbuf = xbt_malloc(sizeof(void*) * comm->size);
266 memcpy(recvbuf, sendbuf, datatype->size * count);
267 for (i = 0; i < comm->size; i++) {
270 scratchbuf[i] = NULL;
272 scratchbuf[i] = xbt_malloc(datatype->size * count);
273 smpi_create_request(scratchbuf[i], count, datatype, MPI_ANY_SOURCE, rank, 0, comm, requests + i);
274 smpi_irecv(requests[i]);
277 smpi_wait_all_nostatus(comm->size, requests); // FIXME: use wait_any for slight performance gain
278 for (i = 0; i < comm->size; i++) {
280 for (j = 0; j < count; j++) {
281 op->func(scratchbuf[i] + datatype->size * j, recvbuf + datatype->size * j, recvbuf + datatype->size * j);
283 xbt_free(requests[i]);
284 xbt_free(scratchbuf[i]);
288 xbt_free(scratchbuf);
290 requests = xbt_malloc(sizeof(smpi_mpi_request_t*));
291 smpi_create_request(sendbuf, count, datatype, rank, root, 0, comm, requests);
292 smpi_isend(*requests);
293 smpi_wait(*requests, MPI_STATUS_IGNORE);