// we make a copy here, as the size is modified by simix, and we may reuse the request in another receive later
request->real_size=request->size;
smpi_datatype_use(request->old_type);
+ smpi_comm_use(request->comm);
request->action = simcall_comm_irecv(mailbox, request->buf, &request->real_size, &match_recv, request);
//integrate pseudo-timing for buffering of small messages, do not bother to execute the simcall if 0
// we make a copy here, as the size is modified by simix, and we may reuse the request in another receive later
request->real_size=request->size;
smpi_datatype_use(request->old_type);
+ smpi_comm_use(request->comm);
//if we are giving back the control to the user without waiting for completion, we have to inject timings
double sleeptime =0.0;
}
if(req->detached == 0) free(req->buf);
}
+ smpi_comm_unuse(req->comm);
smpi_datatype_unuse(datatype);
}
*index = MPI_UNDEFINED;
flag = 0;
- if(count > 0) {
- comms = xbt_dynar_new(sizeof(smx_action_t), NULL);
- map = xbt_new(int, count);
- size = 0;
- for(i = 0; i < count; i++) {
- if((requests[i]!=MPI_REQUEST_NULL) && requests[i]->action) {
- xbt_dynar_push(comms, &requests[i]->action);
- map[size] = i;
- size++;
- }
+ comms = xbt_dynar_new(sizeof(smx_action_t), NULL);
+ map = xbt_new(int, count);
+ size = 0;
+ for(i = 0; i < count; i++) {
+ if((requests[i]!=MPI_REQUEST_NULL) && requests[i]->action) {
+ xbt_dynar_push(comms, &requests[i]->action);
+ map[size] = i;
+ size++;
}
- if(size > 0) {
- i = simcall_comm_testany(comms);
- // not MPI_UNDEFINED, as this is a simix return code
- if(i != -1) {
- *index = map[i];
- finish_wait(&requests[*index], status);
- flag = 1;
- }
- }else{
- //all requests are null or inactive, return true
- flag=1;
- smpi_empty_status(status);
+ }
+ if(size > 0) {
+ i = simcall_comm_testany(comms);
+ // not MPI_UNDEFINED, as this is a simix return code
+ if(i != -1) {
+ *index = map[i];
+ finish_wait(&requests[*index], status);
+ flag = 1;
}
- xbt_free(map);
- xbt_dynar_free(&comms);
+ }else{
+ //all requests are null or inactive, return true
+ flag=1;
+ smpi_empty_status(status);
}
+ xbt_free(map);
+ xbt_dynar_free(&comms);
return flag;
}
xbt_free(tmpbufs);
xbt_free(requests);
}
+
+void smpi_mpi_exscan(void *sendbuf, void *recvbuf, int count,
+ MPI_Datatype datatype, MPI_Op op, MPI_Comm comm)
+{
+ int system_tag = 888;
+ int rank, size, other, index;
+ MPI_Aint lb = 0, dataext = 0;
+ MPI_Request *requests;
+ void **tmpbufs;
+ int recvbuf_is_empty=1;
+ rank = smpi_comm_rank(comm);
+ size = smpi_comm_size(comm);
+
+ // FIXME: check for errors
+ smpi_datatype_extent(datatype, &lb, &dataext);
+
+ // Send/Recv buffers to/from others;
+ requests = xbt_new(MPI_Request, size - 1);
+ tmpbufs = xbt_new(void *, rank);
+ index = 0;
+ for(other = 0; other < rank; other++) {
+ // FIXME: possibly overkill we we have contiguous/noncontiguous data
+ // mapping...
+ tmpbufs[index] = xbt_malloc(count * dataext);
+ requests[index] =
+ smpi_irecv_init(tmpbufs[index], count, datatype, other, system_tag,
+ comm);
+ index++;
+ }
+ for(other = rank + 1; other < size; other++) {
+ requests[index] =
+ smpi_isend_init(sendbuf, count, datatype, other, system_tag, comm);
+ index++;
+ }
+ // Wait for completion of all comms.
+ smpi_mpi_startall(size - 1, requests);
+ for(other = 0; other < size - 1; other++) {
+ index = smpi_mpi_waitany(size - 1, requests, MPI_STATUS_IGNORE);
+ if(index == MPI_UNDEFINED) {
+ break;
+ }
+ if(index < rank) {
+ if(recvbuf_is_empty) smpi_datatype_copy(tmpbufs[index], count, datatype, recvbuf, count, datatype);
+ // #Request is below rank: it's a irecv
+ else smpi_op_apply(op, tmpbufs[index], recvbuf, &count, &datatype);
+ }
+ }
+ for(index = 0; index < rank; index++) {
+ xbt_free(tmpbufs[index]);
+ }
+ xbt_free(tmpbufs);
+ xbt_free(requests);
+}