root/ompi/mca/coll/libnbc/nbc_ialltoallv.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. nbc_alltoallv_init
  2. ompi_coll_libnbc_ialltoallv
  3. nbc_alltoallv_inter_init
  4. ompi_coll_libnbc_ialltoallv_inter
  5. a2av_sched_linear
  6. a2av_sched_pairwise
  7. a2av_sched_inplace
  8. ompi_coll_libnbc_alltoallv_init
  9. ompi_coll_libnbc_alltoallv_inter_init

   1 /* -*- Mode: C; c-basic-offset:2 ; indent-tabs-mode:nil -*- */
   2 /*
   3  * Copyright (c) 2006      The Trustees of Indiana University and Indiana
   4  *                         University Research and Technology
   5  *                         Corporation.  All rights reserved.
   6  * Copyright (c) 2006      The Technical University of Chemnitz. All
   7  *                         rights reserved.
   8  * Copyright (c) 2014-2018 Research Organization for Information Science
   9  *                         and Technology (RIST).  All rights reserved.
  10  * Copyright (c) 2015-2017 Los Alamos National Security, LLC. All rights
  11  *                         reserved.
  12  * Copyright (c) 2017      IBM Corporation.  All rights reserved.
  13  * Copyright (c) 2018      FUJITSU LIMITED.  All rights reserved.
  14  * $COPYRIGHT$
  15  *
  16  * Additional copyrights may follow
  17  *
  18  * Author(s): Torsten Hoefler <htor@cs.indiana.edu>
  19  *
  20  */
  21 #include "nbc_internal.h"
  22 
  23 static inline int a2av_sched_linear(int rank, int p, NBC_Schedule *schedule,
  24                                     const void *sendbuf, const int *sendcounts,
  25                                     const int *sdispls, MPI_Aint sndext, MPI_Datatype sendtype,
  26                                     void *recvbuf, const int *recvcounts,
  27                                     const int *rdispls, MPI_Aint rcvext, MPI_Datatype recvtype);
  28 
  29 static inline int a2av_sched_pairwise(int rank, int p, NBC_Schedule *schedule,
  30                                       const void *sendbuf, const int *sendcounts, const int *sdispls,
  31                                       MPI_Aint sndext, MPI_Datatype sendtype,
  32                                       void *recvbuf, const int *recvcounts, const int *rdispls,
  33                                       MPI_Aint rcvext, MPI_Datatype recvtype);
  34 
  35 static inline int a2av_sched_inplace(int rank, int p, NBC_Schedule *schedule,
  36                                     void *buf, const int *counts, const int *displs,
  37                                     MPI_Aint ext, MPI_Datatype type, ptrdiff_t gap);
  38 
  39 /* an alltoallv schedule can not be cached easily because the contents
  40  * ot the recvcounts array may change, so a comparison of the address
  41  * would not be sufficient ... we simply do not cache it */
  42 
  43 /* simple linear Alltoallv */
  44 static int nbc_alltoallv_init(const void* sendbuf, const int *sendcounts, const int *sdispls,
  45                               MPI_Datatype sendtype, void* recvbuf, const int *recvcounts, const int *rdispls,
  46                               MPI_Datatype recvtype, struct ompi_communicator_t *comm, ompi_request_t ** request,
  47                               struct mca_coll_base_module_2_3_0_t *module, bool persistent)
  48 {
  49   int rank, p, res;
  50   MPI_Aint sndext, rcvext;
  51   NBC_Schedule *schedule;
  52   char *rbuf, *sbuf, inplace;
  53   ptrdiff_t gap = 0, span;
  54   void * tmpbuf = NULL;
  55   ompi_coll_libnbc_module_t *libnbc_module = (ompi_coll_libnbc_module_t*) module;
  56 
  57   NBC_IN_PLACE(sendbuf, recvbuf, inplace);
  58 
  59   rank = ompi_comm_rank (comm);
  60   p = ompi_comm_size (comm);
  61 
  62   res = ompi_datatype_type_extent (recvtype, &rcvext);
  63   if (MPI_SUCCESS != res) {
  64     NBC_Error("MPI Error in ompi_datatype_type_extent() (%i)", res);
  65     return res;
  66   }
  67 
  68   /* copy data to receivbuffer */
  69   if (inplace) {
  70     int count = 0;
  71     for (int i = 0; i < p; i++) {
  72       if (recvcounts[i] > count) {
  73         count = recvcounts[i];
  74       }
  75     }
  76     span = opal_datatype_span(&recvtype->super, count, &gap);
  77     if (OPAL_UNLIKELY(0 == span)) {
  78       return nbc_get_noop_request(persistent, request);
  79     }
  80     tmpbuf = malloc(span);
  81     if (OPAL_UNLIKELY(NULL == tmpbuf)) {
  82       return OMPI_ERR_OUT_OF_RESOURCE;
  83     }
  84     sendcounts = recvcounts;
  85     sdispls = rdispls;
  86   } else {
  87     res = ompi_datatype_type_extent (sendtype, &sndext);
  88     if (MPI_SUCCESS != res) {
  89       NBC_Error("MPI Error in ompi_datatype_type_extent() (%i)", res);
  90       return res;
  91     }
  92   }
  93 
  94   schedule = OBJ_NEW(NBC_Schedule);
  95   if (OPAL_UNLIKELY(NULL == schedule)) {
  96     free(tmpbuf);
  97     return OMPI_ERR_OUT_OF_RESOURCE;
  98   }
  99 
 100 
 101   if (!inplace && sendcounts[rank] != 0) {
 102     rbuf = (char *) recvbuf + rdispls[rank] * rcvext;
 103     sbuf = (char *) sendbuf + sdispls[rank] * sndext;
 104     res = NBC_Sched_copy (sbuf, false, sendcounts[rank], sendtype,
 105                           rbuf, false, recvcounts[rank], recvtype, schedule, false);
 106     if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
 107       OBJ_RELEASE(schedule);
 108       return res;
 109     }
 110   }
 111 
 112   if (inplace) {
 113     res = a2av_sched_inplace(rank, p, schedule, recvbuf, recvcounts,
 114                                  rdispls, rcvext, recvtype, gap);
 115   } else {
 116     res = a2av_sched_linear(rank, p, schedule,
 117                             sendbuf, sendcounts, sdispls, sndext, sendtype,
 118                             recvbuf, recvcounts, rdispls, rcvext, recvtype);
 119   }
 120   if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
 121     OBJ_RELEASE(schedule);
 122     free(tmpbuf);
 123     return res;
 124   }
 125 
 126   res = NBC_Sched_commit (schedule);
 127   if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
 128     OBJ_RELEASE(schedule);
 129     free(tmpbuf);
 130     return res;
 131   }
 132 
 133   res = NBC_Schedule_request(schedule, comm, libnbc_module, persistent, request, tmpbuf);
 134   if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
 135     OBJ_RELEASE(schedule);
 136     free(tmpbuf);
 137     return res;
 138   }
 139 
 140   return OMPI_SUCCESS;
 141 }
 142 
 143 int ompi_coll_libnbc_ialltoallv(const void* sendbuf, const int *sendcounts, const int *sdispls,
 144                                 MPI_Datatype sendtype, void* recvbuf, const int *recvcounts, const int *rdispls,
 145                                 MPI_Datatype recvtype, struct ompi_communicator_t *comm, ompi_request_t ** request,
 146                                 struct mca_coll_base_module_2_3_0_t *module) {
 147     int res = nbc_alltoallv_init(sendbuf, sendcounts, sdispls, sendtype,
 148                                  recvbuf, recvcounts, rdispls, recvtype,
 149                                  comm, request, module, false);
 150     if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
 151         return res;
 152     }
 153   
 154     res = NBC_Start(*(ompi_coll_libnbc_request_t **)request);
 155     if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
 156         NBC_Return_handle (*(ompi_coll_libnbc_request_t **)request);
 157         *request = &ompi_request_null.request;
 158         return res;
 159     }
 160 
 161     return OMPI_SUCCESS;
 162 }
 163 
 164 /* simple linear Alltoallv */
 165 static int nbc_alltoallv_inter_init (const void* sendbuf, const int *sendcounts, const int *sdispls,
 166                                      MPI_Datatype sendtype, void* recvbuf, const int *recvcounts, const int *rdispls,
 167                                      MPI_Datatype recvtype, struct ompi_communicator_t *comm, ompi_request_t ** request,
 168                                      struct mca_coll_base_module_2_3_0_t *module, bool persistent)
 169 {
 170   int res, rsize;
 171   MPI_Aint sndext, rcvext;
 172   NBC_Schedule *schedule;
 173   ompi_coll_libnbc_module_t *libnbc_module = (ompi_coll_libnbc_module_t*) module;
 174 
 175 
 176   res = ompi_datatype_type_extent(sendtype, &sndext);
 177   if (MPI_SUCCESS != res) {
 178     NBC_Error("MPI Error in ompi_datatype_type_extent() (%i)", res);
 179     return res;
 180   }
 181 
 182   res = ompi_datatype_type_extent(recvtype, &rcvext);
 183   if (MPI_SUCCESS != res) {
 184     NBC_Error("MPI Error in ompi_datatype_type_extent() (%i)", res);
 185     return res;
 186   }
 187 
 188   rsize = ompi_comm_remote_size (comm);
 189 
 190   schedule = OBJ_NEW(NBC_Schedule);
 191   if (OPAL_UNLIKELY(NULL == schedule)) {
 192     return OMPI_ERR_OUT_OF_RESOURCE;
 193   }
 194 
 195   for (int i = 0; i < rsize; i++) {
 196     /* post all sends */
 197     if (sendcounts[i] != 0) {
 198       char *sbuf = (char *) sendbuf + sdispls[i] * sndext;
 199       res = NBC_Sched_send (sbuf, false, sendcounts[i], sendtype, i, schedule, false);
 200       if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
 201         OBJ_RELEASE(schedule);
 202         return res;
 203       }
 204     }
 205     /* post all receives */
 206     if (recvcounts[i] != 0) {
 207       char *rbuf = (char *) recvbuf + rdispls[i] * rcvext;
 208       res = NBC_Sched_recv (rbuf, false, recvcounts[i], recvtype, i, schedule, false);
 209       if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
 210         OBJ_RELEASE(schedule);
 211         return res;
 212       }
 213     }
 214   }
 215 
 216   res = NBC_Sched_commit(schedule);
 217   if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
 218     OBJ_RELEASE(schedule);
 219     return res;
 220   }
 221 
 222   res = NBC_Schedule_request(schedule, comm, libnbc_module, persistent, request, NULL);
 223   if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
 224     OBJ_RELEASE(schedule);
 225     return res;
 226   }
 227 
 228   return OMPI_SUCCESS;
 229 }
 230 
 231 int ompi_coll_libnbc_ialltoallv_inter (const void* sendbuf, const int *sendcounts, const int *sdispls,
 232                                        MPI_Datatype sendtype, void* recvbuf, const int *recvcounts, const int *rdispls,
 233                                        MPI_Datatype recvtype, struct ompi_communicator_t *comm, ompi_request_t ** request,
 234                                        struct mca_coll_base_module_2_3_0_t *module) {
 235     int res = nbc_alltoallv_inter_init(sendbuf, sendcounts, sdispls, sendtype,
 236                                        recvbuf, recvcounts, rdispls, recvtype,
 237                                        comm, request, module, false);
 238     if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
 239         return res;
 240     }
 241   
 242     res = NBC_Start(*(ompi_coll_libnbc_request_t **)request);
 243     if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
 244         NBC_Return_handle (*(ompi_coll_libnbc_request_t **)request);
 245         *request = &ompi_request_null.request;
 246         return res;
 247     }
 248 
 249     return OMPI_SUCCESS;
 250 }
 251 
 252 __opal_attribute_unused__
 253 static inline int a2av_sched_linear(int rank, int p, NBC_Schedule *schedule,
 254                                     const void *sendbuf, const int *sendcounts, const int *sdispls,
 255                                     MPI_Aint sndext, MPI_Datatype sendtype,
 256                                     void *recvbuf, const int *recvcounts, const int *rdispls,
 257                                     MPI_Aint rcvext, MPI_Datatype recvtype) {
 258   int res;
 259 
 260   for (int i = 0 ; i < p ; ++i) {
 261     if (i == rank) {
 262       continue;
 263     }
 264 
 265     /* post send */
 266     if (sendcounts[i] != 0) {
 267       char *sbuf = ((char *) sendbuf) + (sdispls[i] * sndext);
 268       res = NBC_Sched_send(sbuf, false, sendcounts[i], sendtype, i, schedule, false);
 269       if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
 270         return res;
 271       }
 272     }
 273 
 274     /* post receive */
 275     if (recvcounts[i] != 0) {
 276       char *rbuf = ((char *) recvbuf) + (rdispls[i] * rcvext);
 277       res = NBC_Sched_recv(rbuf, false, recvcounts[i], recvtype, i, schedule, false);
 278       if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
 279         return res;
 280       }
 281     }
 282   }
 283 
 284   return OMPI_SUCCESS;
 285 }
 286 
 287 __opal_attribute_unused__
 288 static inline int a2av_sched_pairwise(int rank, int p, NBC_Schedule *schedule,
 289                                       const void *sendbuf, const int *sendcounts, const int *sdispls,
 290                                       MPI_Aint sndext, MPI_Datatype sendtype,
 291                                       void *recvbuf, const int *recvcounts, const int *rdispls,
 292                                       MPI_Aint rcvext, MPI_Datatype recvtype) {
 293   int res;
 294 
 295   for (int i = 1 ; i < p ; ++i) {
 296     int sndpeer = (rank + i) % p;
 297     int rcvpeer = (rank + p - i) %p;
 298 
 299     /* post send */
 300     if (sendcounts[sndpeer] != 0) {
 301       char *sbuf = ((char *) sendbuf) + (sdispls[sndpeer] * sndext);
 302       res = NBC_Sched_send(sbuf, false, sendcounts[sndpeer], sendtype, sndpeer, schedule, false);
 303       if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
 304         return res;
 305       }
 306     }
 307 
 308     /* post receive */
 309     if (recvcounts[rcvpeer] != 0) {
 310       char *rbuf = ((char *) recvbuf) + (rdispls[rcvpeer] * rcvext);
 311       res = NBC_Sched_recv(rbuf, false, recvcounts[rcvpeer], recvtype, rcvpeer, schedule, true);
 312       if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
 313         return res;
 314       }
 315     }
 316   }
 317 
 318   return OMPI_SUCCESS;
 319 }
 320 
 321 static inline int a2av_sched_inplace(int rank, int p, NBC_Schedule *schedule,
 322                                     void *buf, const int *counts, const int *displs,
 323                                     MPI_Aint ext, MPI_Datatype type, ptrdiff_t gap) {
 324   int res;
 325 
 326   for (int i = 1; i < (p+1)/2; i++) {
 327     int speer = (rank + i) % p;
 328     int rpeer = (rank + p - i) % p;
 329     char *sbuf = (char *) buf + displs[speer] * ext;
 330     char *rbuf = (char *) buf + displs[rpeer] * ext;
 331 
 332     if (0 != counts[rpeer]) {
 333       res = NBC_Sched_copy (rbuf, false, counts[rpeer], type,
 334                             (void *)(-gap), true, counts[rpeer], type,
 335                             schedule, true);
 336       if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
 337         return res;
 338       }
 339     }
 340     if (0 != counts[speer]) {
 341       res = NBC_Sched_send (sbuf, false , counts[speer], type, speer, schedule, false);
 342       if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
 343         return res;
 344       }
 345     }
 346     if (0 != counts[rpeer]) {
 347       res = NBC_Sched_recv (rbuf, false , counts[rpeer], type, rpeer, schedule, true);
 348       if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
 349         return res;
 350       }
 351     }
 352 
 353     if (0 != counts[rpeer]) {
 354       res = NBC_Sched_send ((void *)(-gap), true, counts[rpeer], type, rpeer, schedule, false);
 355       if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
 356         return res;
 357       }
 358     }
 359     if (0 != counts[speer]) {
 360       res = NBC_Sched_recv (sbuf, false, counts[speer], type, speer, schedule, true);
 361       if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
 362         return res;
 363       }
 364     }
 365   }
 366   if (0 == (p%2)) {
 367     int peer = (rank + p/2) % p;
 368 
 369     char *tbuf = (char *) buf + displs[peer] * ext;
 370     res = NBC_Sched_copy (tbuf, false, counts[peer], type,
 371                           (void *)(-gap), true, counts[peer], type,
 372                           schedule, true);
 373     if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
 374       return res;
 375     }
 376     if (0 != counts[peer]) {
 377       res = NBC_Sched_send ((void *)(-gap), true , counts[peer], type, peer, schedule, false);
 378       if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
 379         return res;
 380       }
 381       res = NBC_Sched_recv (tbuf, false , counts[peer], type, peer, schedule, true);
 382       if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
 383         return res;
 384       }
 385     }
 386   }
 387 
 388   return OMPI_SUCCESS;
 389 }
 390 
 391 int ompi_coll_libnbc_alltoallv_init(const void* sendbuf, const int *sendcounts, const int *sdispls,
 392                                     MPI_Datatype sendtype, void* recvbuf, const int *recvcounts, const int *rdispls,
 393                                     MPI_Datatype recvtype, struct ompi_communicator_t *comm, MPI_Info info, ompi_request_t ** request,
 394                                     struct mca_coll_base_module_2_3_0_t *module) {
 395     int res = nbc_alltoallv_init(sendbuf, sendcounts, sdispls, sendtype, recvbuf, recvcounts, rdispls, recvtype,
 396                                  comm, request, module, true);
 397     if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
 398         return res;
 399     }
 400 
 401     return OMPI_SUCCESS;
 402 }
 403 
 404 int ompi_coll_libnbc_alltoallv_inter_init(const void* sendbuf, const int *sendcounts, const int *sdispls,
 405                                           MPI_Datatype sendtype, void* recvbuf, const int *recvcounts, const int *rdispls,
 406                                           MPI_Datatype recvtype, struct ompi_communicator_t *comm, MPI_Info info, ompi_request_t ** request,
 407                                           struct mca_coll_base_module_2_3_0_t *module) {
 408     int res = nbc_alltoallv_inter_init(sendbuf, sendcounts, sdispls, sendtype, recvbuf, recvcounts, rdispls, recvtype,
 409                                        comm, request, module, true);
 410     if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
 411         return res;
 412     }
 413 
 414     return OMPI_SUCCESS;
 415 }

/* [<][>][^][v][top][bottom][index][help] */