Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Avoid copying data if it comes from/to a shared buffer, even internally.
authorAugustin Degomme <adegomme@gmail.com>
Tue, 26 Nov 2019 11:39:51 +0000 (12:39 +0100)
committerAugustin Degomme <adegomme@gmail.com>
Tue, 26 Nov 2019 13:57:04 +0000 (14:57 +0100)
Mainly useful for MPI_IN_PLACE collectives.

include/smpi/smpi.h
src/smpi/bindings/smpi_pmpi_coll.cpp
src/smpi/internals/smpi_shared.cpp
src/smpi/mpi/smpi_datatype.cpp

index 282452f..bc9dcb7 100644 (file)
@@ -1061,7 +1061,7 @@ SG_END_DECL
 
 /* C++ declarations for shared_malloc */
 #ifdef __cplusplus
 
 /* C++ declarations for shared_malloc */
 #ifdef __cplusplus
-XBT_PUBLIC int smpi_is_shared(void* ptr, std::vector<std::pair<size_t, size_t>>& private_blocks, size_t* offset);
+XBT_PUBLIC int smpi_is_shared(const void* ptr, std::vector<std::pair<size_t, size_t>>& private_blocks, size_t* offset);
 
 std::vector<std::pair<size_t, size_t>> shift_and_frame_private_blocks(const std::vector<std::pair<size_t, size_t>>& vec,
                                                                       size_t offset, size_t buff_size);
 
 std::vector<std::pair<size_t, size_t>> shift_and_frame_private_blocks(const std::vector<std::pair<size_t, size_t>>& vec,
                                                                       size_t offset, size_t buff_size);
index 81535ee..e4a6076 100644 (file)
@@ -19,6 +19,15 @@ XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(smpi_pmpi);
     return (errcode);                                                                                                  \
   }
 
     return (errcode);                                                                                                  \
   }
 
+  static const void* smpi_get_in_place_buf(const void* inplacebuf, const void* otherbuf,std::unique_ptr<unsigned char[]>& tmp_sendbuf, int count, MPI_Datatype datatype){
+  if (inplacebuf == MPI_IN_PLACE) {
+      tmp_sendbuf.reset(new unsigned char[count * datatype->get_extent()]);
+      simgrid::smpi::Datatype::copy(otherbuf, count, datatype, tmp_sendbuf.get(), count, datatype);
+    return tmp_sendbuf.get();
+  }else{
+    return inplacebuf;
+  }
+}
 /* PMPI User level calls */
 
 int PMPI_Barrier(MPI_Comm comm)
 /* PMPI User level calls */
 
 int PMPI_Barrier(MPI_Comm comm)
@@ -373,7 +382,7 @@ int PMPI_Iscatterv(const void* sendbuf, const int* sendcounts, const int* displs
              "Iscatterv: the recvtype cannot be NULL when not receiving in place");
   CHECK_ARGS(request == nullptr, MPI_ERR_ARG, "Iscatterv: param 10 request cannot be NULL");
   CHECK_ARGS(recvbuf != MPI_IN_PLACE && recvcount < 0, MPI_ERR_COUNT,
              "Iscatterv: the recvtype cannot be NULL when not receiving in place");
   CHECK_ARGS(request == nullptr, MPI_ERR_ARG, "Iscatterv: param 10 request cannot be NULL");
   CHECK_ARGS(recvbuf != MPI_IN_PLACE && recvcount < 0, MPI_ERR_COUNT,
-             "Iscatterv: When not receiving in place, the recvcound cannot be negative");
+             "Iscatterv: When not receiving in place, the recvcount cannot be negative");
   CHECK_ARGS(root < 0, MPI_ERR_ROOT, "Iscatterv: root cannot be negative");
   CHECK_ARGS(root >= comm->size(), MPI_ERR_ROOT, "Iscatterv: root (=%d) is larger than communicator size (=%d)", root,
              comm->size());
   CHECK_ARGS(root < 0, MPI_ERR_ROOT, "Iscatterv: root cannot be negative");
   CHECK_ARGS(root >= comm->size(), MPI_ERR_ROOT, "Iscatterv: root (=%d) is larger than communicator size (=%d)", root,
              comm->size());
@@ -492,13 +501,9 @@ int PMPI_Iallreduce(const void *sendbuf, void *recvbuf, int count, MPI_Datatype
     return MPI_ERR_ARG;
 
   smpi_bench_end();
     return MPI_ERR_ARG;
 
   smpi_bench_end();
-  const void* real_sendbuf = sendbuf;
   std::unique_ptr<unsigned char[]> tmp_sendbuf;
   std::unique_ptr<unsigned char[]> tmp_sendbuf;
-  if (sendbuf == MPI_IN_PLACE) {
-    tmp_sendbuf.reset(new unsigned char[count * datatype->get_extent()]);
-    simgrid::smpi::Datatype::copy(recvbuf, count, datatype, tmp_sendbuf.get(), count, datatype);
-    real_sendbuf = tmp_sendbuf.get();
-  }
+  const void* real_sendbuf = smpi_get_in_place_buf(sendbuf, recvbuf, tmp_sendbuf, count, datatype);
+
   int rank = simgrid::s4u::this_actor::get_pid();
 
   TRACE_smpi_comm_in(rank, request == MPI_REQUEST_IGNORED ? "PMPI_Allreduce" : "PMPI_Iallreduce",
   int rank = simgrid::s4u::this_actor::get_pid();
 
   TRACE_smpi_comm_in(rank, request == MPI_REQUEST_IGNORED ? "PMPI_Allreduce" : "PMPI_Iallreduce",
@@ -538,12 +543,9 @@ int PMPI_Iscan(const void *sendbuf, void *recvbuf, int count, MPI_Datatype datat
 
   smpi_bench_end();
   int rank         = simgrid::s4u::this_actor::get_pid();
 
   smpi_bench_end();
   int rank         = simgrid::s4u::this_actor::get_pid();
-  const void* real_sendbuf = sendbuf;
   std::unique_ptr<unsigned char[]> tmp_sendbuf;
   std::unique_ptr<unsigned char[]> tmp_sendbuf;
-  if (sendbuf == MPI_IN_PLACE) {
-    tmp_sendbuf.reset(new unsigned char[count * datatype->size()]);
-    real_sendbuf = memcpy(tmp_sendbuf.get(), recvbuf, count * datatype->size());
-  }
+  const void* real_sendbuf = smpi_get_in_place_buf(sendbuf, recvbuf, tmp_sendbuf, count, datatype);;
+
   TRACE_smpi_comm_in(rank, request == MPI_REQUEST_IGNORED ? "PMPI_Scan" : "PMPI_Iscan",
                      new simgrid::instr::Pt2PtTIData(request == MPI_REQUEST_IGNORED ? "scan" : "iscan", -1,
                                                      datatype->is_replayable() ? count : count * datatype->size(),
   TRACE_smpi_comm_in(rank, request == MPI_REQUEST_IGNORED ? "PMPI_Scan" : "PMPI_Iscan",
                      new simgrid::instr::Pt2PtTIData(request == MPI_REQUEST_IGNORED ? "scan" : "iscan", -1,
                                                      datatype->is_replayable() ? count : count * datatype->size(),
@@ -581,12 +583,8 @@ int PMPI_Iexscan(const void *sendbuf, void *recvbuf, int count, MPI_Datatype dat
 
   smpi_bench_end();
   int rank         = simgrid::s4u::this_actor::get_pid();
 
   smpi_bench_end();
   int rank         = simgrid::s4u::this_actor::get_pid();
-  const void* real_sendbuf = sendbuf;
   std::unique_ptr<unsigned char[]> tmp_sendbuf;
   std::unique_ptr<unsigned char[]> tmp_sendbuf;
-  if (sendbuf == MPI_IN_PLACE) {
-    tmp_sendbuf.reset(new unsigned char[count * datatype->size()]);
-    real_sendbuf = memcpy(tmp_sendbuf.get(), recvbuf, count * datatype->size());
-  }
+  const void* real_sendbuf = smpi_get_in_place_buf(sendbuf, recvbuf, tmp_sendbuf, count, datatype);;
 
   TRACE_smpi_comm_in(rank, request == MPI_REQUEST_IGNORED ? "PMPI_Exscan" : "PMPI_Iexscan",
                      new simgrid::instr::Pt2PtTIData(request == MPI_REQUEST_IGNORED ? "exscan" : "iexscan", -1,
 
   TRACE_smpi_comm_in(rank, request == MPI_REQUEST_IGNORED ? "PMPI_Exscan" : "PMPI_Iexscan",
                      new simgrid::instr::Pt2PtTIData(request == MPI_REQUEST_IGNORED ? "exscan" : "iexscan", -1,
@@ -639,13 +637,8 @@ int PMPI_Ireduce_scatter(const void *sendbuf, void *recvbuf, const int *recvcoun
     trace_recvcounts->push_back(recvcounts[i] * dt_send_size);
     totalcount += recvcounts[i];
   }
     trace_recvcounts->push_back(recvcounts[i] * dt_send_size);
     totalcount += recvcounts[i];
   }
-
-  const void* real_sendbuf = sendbuf;
   std::unique_ptr<unsigned char[]> tmp_sendbuf;
   std::unique_ptr<unsigned char[]> tmp_sendbuf;
-  if (sendbuf == MPI_IN_PLACE) {
-    tmp_sendbuf.reset(new unsigned char[totalcount * datatype->size()]);
-    real_sendbuf = memcpy(tmp_sendbuf.get(), recvbuf, totalcount * datatype->size());
-  }
+  const void* real_sendbuf = smpi_get_in_place_buf(sendbuf, recvbuf, tmp_sendbuf, totalcount, datatype);;
 
   TRACE_smpi_comm_in(rank, request == MPI_REQUEST_IGNORED ? "PMPI_Reduce_scatter" : "PMPI_Ireduce_scatter",
                      new simgrid::instr::VarCollTIData(
 
   TRACE_smpi_comm_in(rank, request == MPI_REQUEST_IGNORED ? "PMPI_Reduce_scatter" : "PMPI_Ireduce_scatter",
                      new simgrid::instr::VarCollTIData(
@@ -688,13 +681,8 @@ int PMPI_Ireduce_scatter_block(const void* sendbuf, void* recvbuf, int recvcount
   int rank                           = simgrid::s4u::this_actor::get_pid();
   int dt_send_size                   = datatype->is_replayable() ? 1 : datatype->size();
   std::vector<int>* trace_recvcounts = new std::vector<int>(recvcount * dt_send_size); // copy data to avoid bad free
   int rank                           = simgrid::s4u::this_actor::get_pid();
   int dt_send_size                   = datatype->is_replayable() ? 1 : datatype->size();
   std::vector<int>* trace_recvcounts = new std::vector<int>(recvcount * dt_send_size); // copy data to avoid bad free
-
-  const void* real_sendbuf = sendbuf;
   std::unique_ptr<unsigned char[]> tmp_sendbuf;
   std::unique_ptr<unsigned char[]> tmp_sendbuf;
-  if (sendbuf == MPI_IN_PLACE) {
-    tmp_sendbuf.reset(new unsigned char[recvcount * count * datatype->size()]);
-    real_sendbuf = memcpy(tmp_sendbuf.get(), recvbuf, recvcount * count * datatype->size());
-  }
+  const void* real_sendbuf = smpi_get_in_place_buf(sendbuf, recvbuf, tmp_sendbuf, recvcount * count, datatype);
 
   TRACE_smpi_comm_in(
       rank, request == MPI_REQUEST_IGNORED ? "PMPI_Reduce_scatter_block" : "PMPI_Ireduce_scatter_block",
 
   TRACE_smpi_comm_in(
       rank, request == MPI_REQUEST_IGNORED ? "PMPI_Reduce_scatter_block" : "PMPI_Ireduce_scatter_block",
@@ -736,16 +724,13 @@ int PMPI_Ialltoall(const void* sendbuf, int sendcount, MPI_Datatype sendtype, vo
 
   smpi_bench_end();
   int rank                 = simgrid::s4u::this_actor::get_pid();
 
   smpi_bench_end();
   int rank                 = simgrid::s4u::this_actor::get_pid();
-  const void* real_sendbuf = sendbuf;
   int real_sendcount         = sendcount;
   MPI_Datatype real_sendtype = sendtype;
   int real_sendcount         = sendcount;
   MPI_Datatype real_sendtype = sendtype;
+  
   std::unique_ptr<unsigned char[]> tmp_sendbuf;
   std::unique_ptr<unsigned char[]> tmp_sendbuf;
+  const void* real_sendbuf = smpi_get_in_place_buf(sendbuf, recvbuf, tmp_sendbuf, recvcount * comm->size(), recvtype);
+
   if (sendbuf == MPI_IN_PLACE) {
   if (sendbuf == MPI_IN_PLACE) {
-    tmp_sendbuf.reset(new unsigned char[recvcount * comm->size() * recvtype->size()]);
-    // memcpy(??,nullptr,0) is actually undefined behavior, even if harmless.
-    if (recvbuf != nullptr)
-      memcpy(tmp_sendbuf.get(), recvbuf, recvcount * comm->size() * recvtype->size());
-    real_sendbuf = tmp_sendbuf.get();
     real_sendcount = recvcount;
     real_sendtype  = recvtype;
   }
     real_sendcount = recvcount;
     real_sendtype  = recvtype;
   }
@@ -804,7 +789,6 @@ int PMPI_Ialltoallv(const void* sendbuf, const int* sendcounts, const int* sendd
   std::vector<int>* trace_recvcounts = new std::vector<int>;
   int dt_size_recv                   = recvtype->size();
 
   std::vector<int>* trace_recvcounts = new std::vector<int>;
   int dt_size_recv                   = recvtype->size();
 
-  const void* real_sendbuf   = sendbuf;
   const int* real_sendcounts = sendcounts;
   const int* real_senddisps  = senddisps;
   MPI_Datatype real_sendtype = sendtype;
   const int* real_sendcounts = sendcounts;
   const int* real_senddisps  = senddisps;
   MPI_Datatype real_sendtype = sendtype;
@@ -819,9 +803,8 @@ int PMPI_Ialltoallv(const void* sendbuf, const int* sendcounts, const int* sendd
   std::unique_ptr<unsigned char[]> tmp_sendbuf;
   std::unique_ptr<int[]> tmp_sendcounts;
   std::unique_ptr<int[]> tmp_senddisps;
   std::unique_ptr<unsigned char[]> tmp_sendbuf;
   std::unique_ptr<int[]> tmp_sendcounts;
   std::unique_ptr<int[]> tmp_senddisps;
+  const void* real_sendbuf = smpi_get_in_place_buf(sendbuf, recvbuf, tmp_sendbuf, maxsize, MPI_CHAR);
   if (sendbuf == MPI_IN_PLACE) {
   if (sendbuf == MPI_IN_PLACE) {
-    tmp_sendbuf.reset(new unsigned char[maxsize]);
-    real_sendbuf = memcpy(tmp_sendbuf.get(), recvbuf, maxsize);
     tmp_sendcounts.reset(new int[size]);
     std::copy(recvcounts, recvcounts + size, tmp_sendcounts.get());
     real_sendcounts = tmp_sendcounts.get();
     tmp_sendcounts.reset(new int[size]);
     std::copy(recvcounts, recvcounts + size, tmp_sendcounts.get());
     real_sendcounts = tmp_sendcounts.get();
@@ -890,7 +873,6 @@ int PMPI_Ialltoallw(const void* sendbuf, const int* sendcounts, const int* sendd
   std::vector<int>* trace_sendcounts = new std::vector<int>;
   std::vector<int>* trace_recvcounts = new std::vector<int>;
 
   std::vector<int>* trace_sendcounts = new std::vector<int>;
   std::vector<int>* trace_recvcounts = new std::vector<int>;
 
-  const void* real_sendbuf           = sendbuf;
   const int* real_sendcounts         = sendcounts;
   const int* real_senddisps          = senddisps;
   const MPI_Datatype* real_sendtypes = sendtypes;
   const int* real_sendcounts         = sendcounts;
   const int* real_senddisps          = senddisps;
   const MPI_Datatype* real_sendtypes = sendtypes;
@@ -911,9 +893,8 @@ int PMPI_Ialltoallw(const void* sendbuf, const int* sendcounts, const int* sendd
   std::unique_ptr<int[]> tmp_sendcounts;
   std::unique_ptr<int[]> tmp_senddisps;
   std::unique_ptr<MPI_Datatype[]> tmp_sendtypes;
   std::unique_ptr<int[]> tmp_sendcounts;
   std::unique_ptr<int[]> tmp_senddisps;
   std::unique_ptr<MPI_Datatype[]> tmp_sendtypes;
+  const void* real_sendbuf = smpi_get_in_place_buf(sendbuf, recvbuf, tmp_sendbuf, maxsize, MPI_CHAR);
   if (sendbuf == MPI_IN_PLACE) {
   if (sendbuf == MPI_IN_PLACE) {
-    tmp_sendbuf.reset(new unsigned char[maxsize]);
-    real_sendbuf = memcpy(tmp_sendbuf.get(), recvbuf, maxsize);
     tmp_sendcounts.reset(new int[size]);
     std::copy(recvcounts, recvcounts + size, tmp_sendcounts.get());
     real_sendcounts = tmp_sendcounts.get();
     tmp_sendcounts.reset(new int[size]);
     std::copy(recvcounts, recvcounts + size, tmp_sendcounts.get());
     real_sendcounts = tmp_sendcounts.get();
index b549d72..29f3b27 100644 (file)
@@ -91,7 +91,7 @@ struct shared_metadata_t {
   shared_data_key_type* data;
 };
 
   shared_data_key_type* data;
 };
 
-std::map<void*, shared_metadata_t> allocs_metadata;
+std::map<const void*, shared_metadata_t> allocs_metadata;
 std::map<std::string, void*> calls;
 
 #ifndef WIN32
 std::map<std::string, void*> calls;
 
 #ifndef WIN32
@@ -372,7 +372,7 @@ void *smpi_shared_malloc(size_t size, const char *file, int line) {
   return ::operator new(size);
 }
 
   return ::operator new(size);
 }
 
-int smpi_is_shared(void* ptr, std::vector<std::pair<size_t, size_t>> &private_blocks, size_t *offset){
+int smpi_is_shared(const void* ptr, std::vector<std::pair<size_t, size_t>> &private_blocks, size_t *offset){
   private_blocks.clear(); // being paranoid
   if (allocs_metadata.empty())
     return 0;
   private_blocks.clear(); // being paranoid
   if (allocs_metadata.empty())
     return 0;
index 53ce75e..074c158 100644 (file)
@@ -279,6 +279,19 @@ int Datatype::copy(const void *sendbuf, int sendcount, MPI_Datatype sendtype,
     smpi_switch_data_segment(simgrid::s4u::Actor::self());
   }
   /* First check if we really have something to do */
     smpi_switch_data_segment(simgrid::s4u::Actor::self());
   }
   /* First check if we really have something to do */
+  size_t offset = 0;
+  std::vector<std::pair<size_t, size_t>> private_blocks;
+  if(smpi_is_shared(sendbuf,private_blocks,&offset)
+       && (private_blocks.size()==1
+       && (private_blocks[0].second - private_blocks[0].first)==(unsigned long)(sendcount * sendtype->get_extent()))){
+    return 0;
+  }
+  if(smpi_is_shared(recvbuf,private_blocks,&offset)
+       && (private_blocks.size()==1
+       && (private_blocks[0].second - private_blocks[0].first)==(unsigned long)(recvcount * recvtype->get_extent()))){
+    return 0;
+  }
+
   if (recvcount > 0 && recvbuf != sendbuf) {
     sendcount *= sendtype->size();
     recvcount *= recvtype->size();
   if (recvcount > 0 && recvbuf != sendbuf) {
     sendcount *= sendtype->size();
     recvcount *= recvtype->size();