Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
make sure refcount of a comm is really 1 when initialized
[simgrid.git] / src / smpi / smpi_base.c
index ee947cc2efee06d2633b16b35228830991a90b8c..8afbcae3cb6593cdb991e89dacecb0e0940695b6 100644 (file)
@@ -327,6 +327,7 @@ void smpi_mpi_start(MPI_Request request)
     // 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
@@ -375,6 +376,7 @@ void smpi_mpi_start(MPI_Request request)
     // 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;
@@ -582,6 +584,7 @@ static void finish_wait(MPI_Request * request, MPI_Status * status)
       }
       if(req->detached == 0) free(req->buf);
     }
+    smpi_comm_unuse(req->comm);
     smpi_datatype_unuse(datatype);
 
   }
@@ -633,33 +636,31 @@ int smpi_mpi_testany(int count, MPI_Request requests[], int *index,
 
   *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;
 }
@@ -1297,3 +1298,56 @@ void smpi_mpi_scan(void *sendbuf, void *recvbuf, int count,
   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);
+}