Discontinuous Galerkin Library
#include "dg/algorithm.h"
Loading...
Searching...
No Matches
mpi_permutation.h
Go to the documentation of this file.
1#pragma once
2#include <map>
3#include <thrust/host_vector.h>
4#include "index.h"
5#include "mpi_datatype.h"
6#include "tensor_traits.h"
9#include "tensor_traits_std.h"
10
11
12namespace dg{
14
23template<class MessageType>
24bool is_communicating(
25 const std::map<int,MessageType>& messages,
26 MPI_Comm comm)
27{
28 int comm_size;
29 MPI_Comm_size( comm, &comm_size);
30 thrust::host_vector<int> sendTo( comm_size, 0 );
31 thrust::host_vector<int> global( comm_size*comm_size);
32 for( auto& send : messages)
33 sendTo[send.first] = 1; // just indicate that a message is being sent
34 // everyone knows howmany messages everyone is sending
35 MPI_Allgather( sendTo.data(), comm_size, MPI_INT,
36 global.data(), comm_size, MPI_INT,
37 comm);
38 bool isCommunicating = false;
39 for( int i=0; i<comm_size; i++)
40 for( int k=0; k<comm_size; k++)
41 if( k != i and global[i*comm_size+k] != 0)
42 isCommunicating = true;
43 return isCommunicating;
44}
46
49
89template<class MessageType>
90std::map<int,MessageType> mpi_permute(
91 const std::map<int,MessageType>& messages,
92 MPI_Comm comm)
93{
94 // I think this function is fairly intuitive to understand which is good
95 int rank, comm_size;
96 MPI_Comm_rank( comm, &rank);
97 MPI_Comm_size( comm, &comm_size);
98 thrust::host_vector<int> sendTo( comm_size, 0 ), recvFrom( comm_size, 0);
99 thrust::host_vector<int> global( comm_size*comm_size);
100 auto flat_vals = detail::flatten_values( messages);
101 for( auto& send : flat_vals)
102 {
103 sendTo[send.first] = send.second.size();
104 }
105 // everyone knows howmany messages everyone is sending
106 MPI_Allgather( sendTo.data(), comm_size, MPI_INT,
107 global.data(), comm_size, MPI_INT,
108 comm);
109 for( int i=0; i<comm_size; i++)
110 recvFrom[i] = global[i*comm_size+rank];
111 // Now we can use Alltoallv to send
112 thrust::host_vector<int> accS( comm_size), accR(comm_size);
113 thrust::exclusive_scan( sendTo.begin(), sendTo.end(), accS.begin());
114 thrust::exclusive_scan( recvFrom.begin(), recvFrom.end(), accR.begin());
115
116 auto send = detail::flatten_map( flat_vals);
117 using value_type = dg::get_value_type<decltype(send)>;
118 thrust::host_vector<value_type> recv(
119 thrust::reduce( recvFrom.begin(), recvFrom.end()));
120 void * send_ptr = thrust::raw_pointer_cast( send.data());
121 const int * sendTo_ptr = thrust::raw_pointer_cast( sendTo.data());
122 const int * accS_ptr = thrust::raw_pointer_cast( accS.data());
123 void * recv_ptr = thrust::raw_pointer_cast( recv.data());
124 const int * recvFrom_ptr = thrust::raw_pointer_cast( recvFrom.data());
125 const int * accR_ptr = thrust::raw_pointer_cast( accR.data());
126 MPI_Datatype type = dg::getMPIDataType<value_type>();
127 MPI_Alltoallv( send_ptr, sendTo_ptr, accS_ptr, type,
128 recv_ptr, recvFrom_ptr, accR_ptr, type,
129 comm);
130 return detail::make_map_t<MessageType>( recv, detail::make_size_map( recvFrom) );
131}
132
147template<class ContainerType>
148void mpi_gather( const thrust::host_vector<std::array<int,2>>& gather_map,
149 const ContainerType& gatherFrom, ContainerType& result, MPI_Comm comm)
150{
151 thrust::host_vector<int> bufferIdx;
152 auto gather_m = gIdx2unique_idx( gather_map, bufferIdx);
153 auto send_map = mpi_permute(gather_m, comm);
154 auto gather = detail::flatten_map( send_map);
155 auto size_map = detail::get_size_map( send_map);
156 ContainerType res( gather.size());
157 thrust::gather( gather.begin(), gather.end(), gatherFrom.begin(), res.begin());
158 std::map<int,ContainerType> result_map = detail::make_map_t<ContainerType>( res, size_map);
159 std::map<int,ContainerType> recv = mpi_permute( result_map, comm);
160 ContainerType flat = detail::flatten_map( recv);
161 result.resize( bufferIdx.size());
162 thrust::gather( bufferIdx.begin(), bufferIdx.end(), flat.begin(), result.begin());
163}
183template<class ContainerType>
184void mpi_scatter( const thrust::host_vector<std::array<int,2>>& scatter_map,
185 const ContainerType& toScatter, ContainerType& result,
186 MPI_Comm comm,
187 bool resize_result = false
188 )
189{
190 thrust::host_vector<int> bufferIdx;
191 // must be injective
192 auto scatter_m = gIdx2unique_idx( scatter_map, bufferIdx);
193 auto recv_map = mpi_permute(scatter_m, comm);
194 auto scatter = detail::flatten_map( recv_map);
195
196 auto size_map = detail::get_size_map( scatter_m);
197
198 ContainerType to_send( toScatter);
199 thrust::scatter( toScatter.begin(), toScatter.end(), bufferIdx.begin(), to_send.begin());
200
201 auto send = detail::make_map_t<ContainerType>( to_send, size_map);
202 auto result_map = mpi_permute( send, comm);
203 auto res = detail::flatten_map( result_map);
204 if( resize_result)
205 result.resize( res.size());
206 thrust::scatter( res.begin(), res.end(), scatter.begin(), result.begin());
207}
208
221template<class Integer>
222thrust::host_vector<std::array<Integer,2>>
223 mpi_invert_permutation( const thrust::host_vector<std::array<Integer,2>>& p,
224 MPI_Comm comm)
225{
226 thrust::host_vector<Integer> seq( p.size());
227 thrust::host_vector<std::array<Integer,2>> seq_arr( p.size());
228 thrust::sequence( seq.begin(), seq.end());
229 Integer rank;
230 MPI_Comm_rank( comm, &rank);
231 // package sequence
232 for( unsigned u=0; u<seq.size(); u++)
233 seq_arr[u] = {rank, seq[u]};
234 thrust::host_vector<std::array<Integer,2>> sort_map;
235 mpi_scatter( p, seq_arr, sort_map, comm, true);
236 return sort_map;
237
238}
240
241
242} // namespace dg
typename TensorTraits< std::decay_t< Vector > >::value_type get_value_type
Definition tensor_traits.h:45
void mpi_gather(const thrust::host_vector< std::array< int, 2 > > &gather_map, const ContainerType &gatherFrom, ContainerType &result, MPI_Comm comm)
Un-optimized distributed gather operation.
Definition mpi_permutation.h:148
thrust::host_vector< std::array< Integer, 2 > > mpi_invert_permutation(const thrust::host_vector< std::array< Integer, 2 > > &p, MPI_Comm comm)
Invert a globally bijective index map.
Definition mpi_permutation.h:223
void mpi_scatter(const thrust::host_vector< std::array< int, 2 > > &scatter_map, const ContainerType &toScatter, ContainerType &result, MPI_Comm comm, bool resize_result=false)
Un-optimized distributed scatter operation.
Definition mpi_permutation.h:184
std::map< int, MessageType > mpi_permute(const std::map< int, MessageType > &messages, MPI_Comm comm)
Exchange messages between processes in a communicator.
Definition mpi_permutation.h:90
This is the namespace for all functions and classes defined and used by the discontinuous Galerkin li...
double value_type