1 /* Copyright (c) 2013-2023. The SimGrid Team.
2 * All rights reserved. */
4 /* This program is free software; you can redistribute it and/or modify it
5 * under the terms of the license (GNU LGPL) which comes with this package. */
7 #include "../colls_private.hpp"
9 * Linear functions are copied from the basic coll module. For
10 * some small number of nodes and/or small data sizes they are just as
11 * fast as tuned/tree based segmenting operations and as such may be
12 * selected by the decision functions. These are copied into this module
13 * due to the way we select modules in V1. i.e. in V2 we will handle this
14 * differently and so will not have to duplicate code.
15 * GEF Oct05 after asking Jeff.
17 namespace simgrid::smpi {
18 int alltoallv__ompi_basic_linear(const void *sbuf, const int *scounts, const int *sdisps,
20 void *rbuf, const int *rcounts, const int *rdisps,
24 int size = comm->size();
25 int rank = comm->rank();
26 XBT_DEBUG("coll:tuned:alltoallv_intra_basic_linear rank %d", rank);
28 ptrdiff_t sext = sdtype->get_extent();
29 ptrdiff_t rext = rdtype->get_extent();
31 /* Simple optimization - handle send to self first */
32 char* psnd = ((char*)sbuf) + (sdisps[rank] * sext);
33 char* prcv = ((char*)rbuf) + (rdisps[rank] * rext);
34 if (0 != scounts[rank]) {
35 Datatype::copy(psnd, scounts[rank], sdtype, prcv, rcounts[rank], rdtype);
38 /* If only one process, we're done. */
43 /* Now, initiate all send/recv to/from others. */
44 auto* ireqs = new MPI_Request[size * 2];
46 MPI_Request* preq = ireqs;
48 /* Post all receives first */
49 for (int i = 0; i < size; ++i) {
54 prcv = ((char*)rbuf) + (rdisps[i] * rext);
56 *preq = Request::irecv_init(prcv, rcounts[i], rdtype, i, COLL_TAG_ALLTOALLV, comm);
61 /* Now post all sends */
62 for (int i = 0; i < size; ++i) {
67 psnd = ((char*)sbuf) + (sdisps[i] * sext);
68 *preq = Request::isend_init(psnd, scounts[i], sdtype, i, COLL_TAG_ALLTOALLV, comm);
73 /* Start your engines. This will never return an error. */
74 Request::startall(nreqs, ireqs);
76 /* Wait for them all. If there's an error, note that we don't care
77 * what the error was -- just that there *was* an error. The PML
78 * will finish all requests, even if one or more of them fail.
79 * i.e., by the end of this call, all the requests are free-able.
80 * So free them anyway -- even if there was an error, and return the
81 * error after we free everything. */
82 Request::waitall(nreqs, ireqs, MPI_STATUSES_IGNORE);
84 /* Free the requests. */
85 for (int i = 0; i < nreqs; ++i) {
86 if (ireqs[i] != MPI_REQUEST_NULL)
87 Request::unref(&ireqs[i]);
93 } // namespace simgrid::smpi