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

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

DEFINITIONS

This source file includes following definitions.
  1. nbc_alltoallw_init
  2. ompi_coll_libnbc_ialltoallw
  3. nbc_alltoallw_inter_init
  4. ompi_coll_libnbc_ialltoallw_inter
  5. a2aw_sched_linear
  6. a2aw_sched_pairwise
  7. a2aw_sched_inplace
  8. ompi_coll_libnbc_alltoallw_init
  9. ompi_coll_libnbc_alltoallw_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 a2aw_sched_linear(int rank, int p, NBC_Schedule *schedule,
  24                                     const void *sendbuf, const int *sendcounts, const int *sdispls,
  25                                     struct ompi_datatype_t * const * sendtypes,
  26                                     void *recvbuf, const int *recvcounts, const int *rdispls,
  27                                     struct ompi_datatype_t * const * recvtypes);
  28 
  29 static inline int a2aw_sched_pairwise(int rank, int p, NBC_Schedule *schedule,
  30                                       const void *sendbuf, const int *sendcounts, const int *sdispls,
  31                                       struct ompi_datatype_t * const * sendtypes,
  32                                       void *recvbuf, const int *recvcounts, const int *rdispls,
  33                                       struct ompi_datatype_t * const * recvtypes);
  34 
  35 static inline int a2aw_sched_inplace(int rank, int p, NBC_Schedule *schedule,
  36                                     void *buf, const int *counts, const int *displs,
  37                                     struct ompi_datatype_t * const * types);
  38 
  39 /* an alltoallw 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 Alltoallw */
  44 static int nbc_alltoallw_init(const void* sendbuf, const int *sendcounts, const int *sdispls,
  45                               struct ompi_datatype_t * const *sendtypes, void* recvbuf, const int *recvcounts, const int *rdispls,
  46                               struct ompi_datatype_t * const *recvtypes, 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   NBC_Schedule *schedule;
  51   char *rbuf, *sbuf, inplace;
  52   ptrdiff_t span=0;
  53   void *tmpbuf = NULL;
  54   ompi_coll_libnbc_module_t *libnbc_module = (ompi_coll_libnbc_module_t*) module;
  55 
  56   NBC_IN_PLACE(sendbuf, recvbuf, inplace);
  57 
  58   rank = ompi_comm_rank (comm);
  59   p = ompi_comm_size (comm);
  60 
  61   /* copy data to receivbuffer */
  62   if (inplace) {
  63     ptrdiff_t lgap, lspan;
  64     for (int i = 0; i < p; i++) {
  65       lspan = opal_datatype_span(&recvtypes[i]->super, recvcounts[i], &lgap);
  66       if (lspan > span) {
  67         span = lspan;
  68       }
  69     }
  70     if (OPAL_UNLIKELY(0 == span)) {
  71       return nbc_get_noop_request(persistent, request);
  72     }
  73     tmpbuf = malloc(span);
  74     if (OPAL_UNLIKELY(NULL == tmpbuf)) {
  75       return OMPI_ERR_OUT_OF_RESOURCE;
  76     }
  77     sendcounts = recvcounts;
  78     sdispls = rdispls;
  79     sendtypes = recvtypes;
  80   }
  81 
  82   schedule = OBJ_NEW(NBC_Schedule);
  83   if (OPAL_UNLIKELY(NULL == schedule)) {
  84     free(tmpbuf);
  85     return OMPI_ERR_OUT_OF_RESOURCE;
  86   }
  87 
  88   if (!inplace && sendcounts[rank] != 0) {
  89     rbuf = (char *) recvbuf + rdispls[rank];
  90     sbuf = (char *) sendbuf + sdispls[rank];
  91     res = NBC_Sched_copy(sbuf, false, sendcounts[rank], sendtypes[rank],
  92                          rbuf, false, recvcounts[rank], recvtypes[rank], schedule, false);
  93     if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
  94       return res;
  95     }
  96   }
  97 
  98   if (inplace) {
  99     res = a2aw_sched_inplace(rank, p, schedule, recvbuf,
 100                                  recvcounts, rdispls, recvtypes);
 101   } else {
 102     res = a2aw_sched_linear(rank, p, schedule,
 103                             sendbuf, sendcounts, sdispls, sendtypes,
 104                             recvbuf, recvcounts, rdispls, recvtypes);
 105   }
 106   if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
 107     OBJ_RELEASE(schedule);
 108     free(tmpbuf);
 109     return res;
 110   }
 111 
 112   res = NBC_Sched_commit (schedule);
 113   if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
 114     OBJ_RELEASE(schedule);
 115     free(tmpbuf);
 116     return res;
 117   }
 118 
 119   res = NBC_Schedule_request(schedule, comm, libnbc_module, persistent, request, tmpbuf);
 120   if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
 121     OBJ_RELEASE(schedule);
 122     free(tmpbuf);
 123     return res;
 124   }
 125 
 126   return OMPI_SUCCESS;
 127 } 
 128 
 129 int ompi_coll_libnbc_ialltoallw(const void* sendbuf, const int *sendcounts, const int *sdispls,
 130                                 struct ompi_datatype_t * const *sendtypes, void* recvbuf, const int *recvcounts, const int *rdispls,
 131                                 struct ompi_datatype_t * const *recvtypes, struct ompi_communicator_t *comm, ompi_request_t ** request,
 132                                 struct mca_coll_base_module_2_3_0_t *module) {
 133     int res = nbc_alltoallw_init(sendbuf, sendcounts, sdispls, sendtypes,
 134                                  recvbuf, recvcounts, rdispls, recvtypes,
 135                                  comm, request, module, false);
 136     if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
 137         return res;
 138     }
 139   
 140     res = NBC_Start(*(ompi_coll_libnbc_request_t **)request);
 141     if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
 142         NBC_Return_handle (*(ompi_coll_libnbc_request_t **)request);
 143         *request = &ompi_request_null.request;
 144         return res;
 145     }
 146 
 147     return OMPI_SUCCESS;
 148 }
 149 
 150 /* simple linear Alltoallw */
 151 static int nbc_alltoallw_inter_init (const void* sendbuf, const int *sendcounts, const int *sdispls,
 152                                      struct ompi_datatype_t * const *sendtypes, void* recvbuf, const int *recvcounts, const int *rdispls,
 153                                      struct ompi_datatype_t * const *recvtypes, struct ompi_communicator_t *comm, ompi_request_t ** request,
 154                                      struct mca_coll_base_module_2_3_0_t *module, bool persistent)
 155 {
 156   int res, rsize;
 157   NBC_Schedule *schedule;
 158   char *rbuf, *sbuf;
 159   ompi_coll_libnbc_module_t *libnbc_module = (ompi_coll_libnbc_module_t*) module;
 160 
 161   rsize = ompi_comm_remote_size (comm);
 162 
 163   schedule = OBJ_NEW(NBC_Schedule);
 164   if (OPAL_UNLIKELY(NULL == schedule)) {
 165     return OMPI_ERR_OUT_OF_RESOURCE;
 166   }
 167 
 168   for (int i = 0 ; i < rsize ; ++i) {
 169     /* post all sends */
 170     if (sendcounts[i] != 0) {
 171       sbuf = (char *) sendbuf + sdispls[i];
 172       res = NBC_Sched_send (sbuf, false, sendcounts[i], sendtypes[i], i, schedule, false);
 173       if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
 174         OBJ_RELEASE(schedule);
 175         return res;
 176       }
 177     }
 178     /* post all receives */
 179     if (recvcounts[i] != 0) {
 180       rbuf = (char *) recvbuf + rdispls[i];
 181       res = NBC_Sched_recv (rbuf, false, recvcounts[i], recvtypes[i], i, schedule, false);
 182       if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
 183         OBJ_RELEASE(schedule);
 184         return res;
 185       }
 186     }
 187   }
 188 
 189   res = NBC_Sched_commit (schedule);
 190   if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
 191     OBJ_RELEASE(schedule);
 192     return res;
 193   }
 194 
 195   res = NBC_Schedule_request(schedule, comm, libnbc_module, persistent, request, NULL);
 196   if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
 197     OBJ_RELEASE(schedule);
 198     return res;
 199   }
 200 
 201   return OMPI_SUCCESS;
 202 }
 203 
 204 int ompi_coll_libnbc_ialltoallw_inter(const void* sendbuf, const int *sendcounts, const int *sdispls,
 205                                       struct ompi_datatype_t * const *sendtypes, void* recvbuf, const int *recvcounts, const int *rdispls,
 206                                       struct ompi_datatype_t * const *recvtypes, struct ompi_communicator_t *comm, ompi_request_t ** request,
 207                                       struct mca_coll_base_module_2_3_0_t *module) {
 208     int res = nbc_alltoallw_inter_init(sendbuf, sendcounts, sdispls, sendtypes,
 209                                        recvbuf, recvcounts, rdispls, recvtypes,
 210                                        comm, request, module, false);
 211     if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
 212         return res;
 213     }
 214   
 215     res = NBC_Start(*(ompi_coll_libnbc_request_t **)request);
 216     if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
 217         NBC_Return_handle (*(ompi_coll_libnbc_request_t **)request);
 218         *request = &ompi_request_null.request;
 219         return res;
 220     }
 221 
 222     return OMPI_SUCCESS;
 223 }
 224 
 225 static inline int a2aw_sched_linear(int rank, int p, NBC_Schedule *schedule,
 226                                     const void *sendbuf, const int *sendcounts, const int *sdispls,
 227                                     struct ompi_datatype_t * const * sendtypes,
 228                                     void *recvbuf, const int *recvcounts, const int *rdispls,
 229                                     struct ompi_datatype_t * const * recvtypes) {
 230   int res;
 231 
 232   for (int i = 0; i < p; i++) {
 233     ptrdiff_t gap, span;
 234     if (i == rank) {
 235       continue;
 236     }
 237 
 238     /* post send */
 239     span = opal_datatype_span(&sendtypes[i]->super, sendcounts[i], &gap);
 240     if (OPAL_LIKELY(0 < span)) {
 241       char *sbuf = (char *) sendbuf + sdispls[i];
 242       res = NBC_Sched_send (sbuf, false, sendcounts[i], sendtypes[i], i, schedule, false);
 243       if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
 244         return res;
 245       }
 246     }
 247     /* post receive */
 248     span = opal_datatype_span(&recvtypes[i]->super, recvcounts[i], &gap);
 249     if (OPAL_LIKELY(0 < span)) {
 250       char *rbuf = (char *) recvbuf + rdispls[i];
 251       res = NBC_Sched_recv (rbuf, false, recvcounts[i], recvtypes[i], i, schedule, false);
 252       if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
 253         return res;
 254       }
 255     }
 256   }
 257 
 258   return OMPI_SUCCESS;
 259 }
 260 
 261 __opal_attribute_unused__
 262 static inline int a2aw_sched_pairwise(int rank, int p, NBC_Schedule *schedule,
 263                                       const void *sendbuf, const int *sendcounts, const int *sdispls,
 264                                       struct ompi_datatype_t * const * sendtypes,
 265                                       void *recvbuf, const int *recvcounts, const int *rdispls,
 266                                       struct ompi_datatype_t * const * recvtypes) {
 267   int res;
 268 
 269   for (int i = 1; i < p; i++) {
 270     int sndpeer = (rank + i) % p;
 271     int rcvpeer = (rank + p - i) % p;
 272 
 273     /* post send */
 274     if (sendcounts[sndpeer] != 0) {
 275       char *sbuf = (char *) sendbuf + sdispls[sndpeer];
 276       res = NBC_Sched_send (sbuf, false, sendcounts[sndpeer], sendtypes[sndpeer], sndpeer, schedule, false);
 277       if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
 278         return res;
 279       }
 280     }
 281     /* post receive */
 282     if (recvcounts[rcvpeer] != 0) {
 283       char *rbuf = (char *) recvbuf + rdispls[rcvpeer];
 284       res = NBC_Sched_recv (rbuf, false, recvcounts[rcvpeer], recvtypes[rcvpeer], rcvpeer, schedule, true);
 285       if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
 286         return res;
 287       }
 288     }
 289   }
 290 
 291   return OMPI_SUCCESS;
 292 }
 293 
 294 static inline int a2aw_sched_inplace(int rank, int p, NBC_Schedule *schedule,
 295                                      void *buf, const int *counts, const int *displs,
 296                                      struct ompi_datatype_t * const * types) {
 297   ptrdiff_t gap = 0;
 298   int res;
 299 
 300   for (int i = 1; i < (p+1)/2; i++) {
 301     int speer = (rank + i) % p;
 302     int rpeer = (rank + p - i) % p;
 303     char *sbuf = (char *) buf + displs[speer];
 304     char *rbuf = (char *) buf + displs[rpeer];
 305 
 306     if (0 != counts[rpeer]) {
 307       (void)opal_datatype_span(&types[rpeer]->super, counts[rpeer], &gap);
 308       res = NBC_Sched_copy (rbuf, false, counts[rpeer], types[rpeer],
 309                             (void *)(-gap), true, counts[rpeer], types[rpeer],
 310                             schedule, true);
 311       if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
 312         return res;
 313       }
 314     }
 315     if (0 != counts[speer]) {
 316       res = NBC_Sched_send (sbuf, false , counts[speer], types[speer], speer, schedule, false);
 317       if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
 318         return res;
 319       }
 320     }
 321     if (0 != counts[rpeer]) {
 322       res = NBC_Sched_recv (rbuf, false , counts[rpeer], types[rpeer], rpeer, schedule, true);
 323       if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
 324         return res;
 325       }
 326     }
 327 
 328     if (0 != counts[rpeer]) {
 329       res = NBC_Sched_send ((void *)(-gap), true, counts[rpeer], types[rpeer], rpeer, schedule, false);
 330       if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
 331         return res;
 332       }
 333     }
 334     if (0 != counts[speer]) {
 335       res = NBC_Sched_recv (sbuf, false, counts[speer], types[speer], speer, schedule, true);
 336       if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
 337         return res;
 338       }
 339     }
 340   }
 341   if (0 == (p%2)) {
 342     int peer = (rank + p/2) % p;
 343 
 344     char *tbuf = (char *) buf + displs[peer];
 345     (void)opal_datatype_span(&types[peer]->super, counts[peer], &gap);
 346     res = NBC_Sched_copy (tbuf, false, counts[peer], types[peer],
 347                           (void *)(-gap), true, counts[peer], types[peer],
 348                           schedule, true);
 349     if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
 350       return res;
 351     }
 352     res = NBC_Sched_send ((void *)(-gap), true , counts[peer], types[peer], peer, schedule, false);
 353     if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
 354       return res;
 355     }
 356     res = NBC_Sched_recv (tbuf, false , counts[peer], types[peer], peer, schedule, true);
 357     if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
 358       return res;
 359     }
 360   }
 361 
 362   return OMPI_SUCCESS;
 363 }
 364 
 365 int ompi_coll_libnbc_alltoallw_init(const void* sendbuf, const int *sendcounts, const int *sdispls,
 366                                     struct ompi_datatype_t * const *sendtypes, void* recvbuf, const int *recvcounts, const int *rdispls,
 367                                     struct ompi_datatype_t * const *recvtypes, struct ompi_communicator_t *comm, MPI_Info info, ompi_request_t ** request,
 368                                     struct mca_coll_base_module_2_3_0_t *module) {
 369     int res = nbc_alltoallw_init(sendbuf, sendcounts, sdispls, sendtypes, recvbuf, recvcounts, rdispls, recvtypes,
 370                                  comm, request, module, true);
 371     if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
 372         return res;
 373     }
 374 
 375     return OMPI_SUCCESS;
 376 }
 377 
 378 int ompi_coll_libnbc_alltoallw_inter_init(const void* sendbuf, const int *sendcounts, const int *sdispls,
 379                                           struct ompi_datatype_t * const *sendtypes, void* recvbuf, const int *recvcounts, const int *rdispls,
 380                                           struct ompi_datatype_t * const *recvtypes, struct ompi_communicator_t *comm, MPI_Info info, ompi_request_t ** request,
 381                                           struct mca_coll_base_module_2_3_0_t *module) {
 382     int res = nbc_alltoallw_inter_init(sendbuf, sendcounts, sdispls, sendtypes, recvbuf, recvcounts, rdispls, recvtypes,
 383                                        comm, request, module, true);
 384     if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
 385         return res;
 386     }
 387 
 388     return OMPI_SUCCESS;
 389 }

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