ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
gather_buffer.hpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2017-2022 The ESPResSo project
3 * Max-Planck-Institute for Polymer Research, Theory Group
4 *
5 * This file is part of ESPResSo.
6 *
7 * ESPResSo is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * ESPResSo is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#ifndef UTILS_MPI_GATHER_BUFFER_HPP
22#define UTILS_MPI_GATHER_BUFFER_HPP
23
25#include "gatherv.hpp"
26
27#include <boost/mpi/collectives.hpp>
28#include <boost/mpi/communicator.hpp>
29
30#include <algorithm>
31#include <type_traits>
32#include <vector>
33
34namespace Utils {
35namespace Mpi {
36
37/**
38 * @brief Gather buffer with different size on each node.
39 *
40 * Gathers buffers with different lengths from all nodes to root.
41 * The buffer is resized to the total size. On the @p root node,
42 * the first @p n_elem elements of @p buffer are moved, if need
43 * be. On the other nodes, @p buffer is not touched.
44 *
45 * This encapsulates a common combination of <tt>MPI_Gather()</tt>
46 * and <tt>MPI_{Send,Recv}()</tt>.
47 *
48 * @param buffer On the head node: the target buffer that has the local
49 * part in the beginning. On worker nodes: the local buffer.
50 * @param comm The MPI communicator.
51 * @param root The rank where the data should be gathered.
52 */
53template <typename T, class Allocator>
54void gather_buffer(std::vector<T, Allocator> &buffer,
55 boost::mpi::communicator const &comm, int root = 0) {
56 auto const n_elem = static_cast<int>(buffer.size());
57
58 if (comm.rank() == root) {
59 static std::vector<int> sizes;
60 static std::vector<int> displ;
61
62 auto const tot_size =
63 detail::size_and_offset<T>(sizes, displ, n_elem, comm, root);
64
65 /* Resize the buffer */
66 buffer.resize(static_cast<unsigned int>(tot_size));
67
68 /* Move the original data to its new location */
69 if (sizes[root] && displ[root]) {
70 for (int i = sizes[root] - 1; i >= 0; --i) {
71 buffer[i + displ[root]] = buffer[i];
72 }
73 }
74
75 /* Gather data */
76 gatherv(comm, buffer.data(), tot_size, buffer.data(), sizes.data(),
77 displ.data(), root);
78 } else {
79 /* Send local size */
80 detail::size_and_offset(n_elem, comm, root);
81 /* Send data */
82 gatherv(comm, buffer.data(), n_elem, static_cast<T *>(nullptr), nullptr,
83 nullptr, root);
84 }
85}
86} // namespace Mpi
87} // namespace Utils
88
89#endif
void gather_buffer(std::vector< T, Allocator > &buffer, boost::mpi::communicator const &comm, int root=0)
Gather buffer with different size on each node.
void gatherv(const boost::mpi::communicator &comm, const T *in_values, int in_size, T *out_values, const int *sizes, const int *displs, int root)
Definition gatherv.hpp:87