Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Fix a doc error about actors (Tutorial_algorithms)
[simgrid.git] / src / smpi / colls / allgather / allgather-mvapich-smp.cpp
1 /* Copyright (c) 2013-2019. The SimGrid Team.
2  * All rights reserved.                                                     */
3
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. */
6
7 /*
8  * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
9  *                         University Research and Technology
10  *                         Corporation.  All rights reserved.
11  * Copyright (c) 2004-2009 The University of Tennessee and The University
12  *                         of Tennessee Research Foundation.  All rights
13  *                         reserved.
14  * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
15  *                         University of Stuttgart.  All rights reserved.
16  * Copyright (c) 2004-2005 The Regents of the University of California.
17  *                         All rights reserved.
18  *
19  * Additional copyrights may follow
20  */
21  /* -*- Mode: C; c-basic-offset:4 ; -*- */
22 /* Copyright (c) 2001-2014, The Ohio State University. All rights
23  * reserved.
24  *
25  * This file is part of the MVAPICH2 software package developed by the
26  * team members of The Ohio State University's Network-Based Computing
27  * Laboratory (NBCL), headed by Professor Dhabaleswar K. (DK) Panda.
28  *
29  * For detailed copyright and licensing information, please refer to the
30  * copyright file COPYRIGHT in the top level MVAPICH2 directory.
31  */
32 /*
33  *
34  *  (C) 2001 by Argonne National Laboratory.
35  *      See COPYRIGHT in top-level directory.
36  */
37 #include "../colls_private.hpp"
38 namespace simgrid{
39 namespace smpi{
40
41 int Coll_allgather_mvapich2_smp::allgather(const void *sendbuf,int sendcnt, MPI_Datatype sendtype,
42                             void *recvbuf, int recvcnt,MPI_Datatype recvtype,
43                             MPI_Comm  comm)
44 {
45     int rank, size;
46     int local_rank, local_size;
47     int leader_comm_size = 0;
48     int mpi_errno = MPI_SUCCESS;
49     MPI_Aint recvtype_extent = 0;  /* Datatype extent */
50     MPI_Comm shmem_comm, leader_comm;
51
52   if(comm->get_leaders_comm()==MPI_COMM_NULL){
53     comm->init_smp();
54   }
55
56   if (not comm->is_uniform() || not comm->is_blocked())
57     throw std::invalid_argument("allgather MVAPICH2 smp algorithm can't be used with irregular deployment. Please "
58                                 "insure that processes deployed on the same node are contiguous and that each node has "
59                                 "the same number of processes");
60
61   if (recvcnt == 0) {
62     return MPI_SUCCESS;
63     }
64
65     rank = comm->rank();
66     size = comm->size();
67
68     /* extract the rank,size information for the intra-node communicator */
69     recvtype_extent=recvtype->get_extent();
70
71     shmem_comm = comm->get_intra_comm();
72     local_rank = shmem_comm->rank();
73     local_size = shmem_comm->size();
74
75     if (local_rank == 0) {
76         /* Node leader. Extract the rank, size information for the leader communicator */
77         leader_comm = comm->get_leaders_comm();
78         if(leader_comm==MPI_COMM_NULL){
79           leader_comm = MPI_COMM_WORLD;
80         }
81         leader_comm_size = leader_comm->size();
82     }
83
84     /*If there is just one node, after gather itself,
85      * root has all the data and it can do bcast*/
86     if(local_rank == 0) {
87         mpi_errno = Colls::gather(sendbuf, sendcnt,sendtype,
88                                     (void*)((char*)recvbuf + (rank * recvcnt * recvtype_extent)),
89                                      recvcnt, recvtype,
90                                      0, shmem_comm);
91     } else {
92         /*Since in allgather all the processes could have
93          * its own data in place*/
94         if(sendbuf == MPI_IN_PLACE) {
95             mpi_errno = Colls::gather((void*)((char*)recvbuf + (rank * recvcnt * recvtype_extent)),
96                                          recvcnt , recvtype,
97                                          recvbuf, recvcnt, recvtype,
98                                          0, shmem_comm);
99         } else {
100             mpi_errno = Colls::gather(sendbuf, sendcnt,sendtype,
101                                          recvbuf, recvcnt, recvtype,
102                                          0, shmem_comm);
103         }
104     }
105     /* Exchange the data between the node leaders*/
106     if (local_rank == 0 && (leader_comm_size > 1)) {
107         /*When data in each socket is different*/
108         if (comm->is_uniform() != 1) {
109
110             int *node_sizes = NULL;
111             int i = 0;
112
113             node_sizes = comm->get_non_uniform_map();
114
115             int* displs   = new int[leader_comm_size];
116             int* recvcnts = new int[leader_comm_size];
117             recvcnts[0] = node_sizes[0] * recvcnt;
118             displs[0] = 0;
119
120             for (i = 1; i < leader_comm_size; i++) {
121                 displs[i] = displs[i - 1] + node_sizes[i - 1] * recvcnt;
122                 recvcnts[i] = node_sizes[i] * recvcnt;
123             }
124
125
126             void* sendbuf=((char*)recvbuf)+recvtype->get_extent()*displs[leader_comm->rank()];
127
128             mpi_errno = Colls::allgatherv(sendbuf,
129                                        (recvcnt*local_size),
130                                        recvtype,
131                                        recvbuf, recvcnts,
132                                        displs, recvtype,
133                                        leader_comm);
134             delete[] displs;
135             delete[] recvcnts;
136         } else {
137         void* sendtmpbuf=((char*)recvbuf)+recvtype->get_extent()*(recvcnt*local_size)*leader_comm->rank();
138
139
140
141             mpi_errno = Coll_allgather_mpich::allgather(sendtmpbuf,
142                                                (recvcnt*local_size),
143                                                recvtype,
144                                                recvbuf, (recvcnt*local_size), recvtype,
145                                              leader_comm);
146
147         }
148     }
149
150     /*Bcast the entire data from node leaders to all other cores*/
151     mpi_errno = Colls::bcast (recvbuf, recvcnt * size, recvtype, 0, shmem_comm);
152     return mpi_errno;
153 }
154
155 }
156 }