forked from headmyshoulder/odeint-v2
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Pascal Germroth
committed
Jul 21, 2013
1 parent
744e108
commit 7a709f7
Showing
4 changed files
with
291 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
/* | ||
[auto_generated] | ||
boost/numeric/odeint/external/mpi/mpi.hpp | ||
[begin_description] | ||
Wrappers for MPI. | ||
[end_description] | ||
Copyright 2009-2011 Karsten Ahnert | ||
Copyright 2009-2011 Mario Mulansky | ||
Distributed under the Boost Software License, Version 1.0. | ||
(See accompanying file LICENSE_1_0.txt or | ||
copy at http://www.boost.org/LICENSE_1_0.txt) | ||
*/ | ||
|
||
|
||
#ifndef BOOST_NUMERIC_ODEINT_EXTERNAL_MPI_MPI_HPP_INCLUDED | ||
#define BOOST_NUMERIC_ODEINT_EXTERNAL_MPI_MPI_HPP_INCLUDED | ||
|
||
#include "mpi_vector_state.hpp" | ||
#include "mpi_nested_algebra.hpp" | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
/* | ||
[auto_generated] | ||
boost/numeric/odeint/external/mpi/mpi_nested_algebra.hpp | ||
[begin_description] | ||
Nested parallelized algebra for MPI. | ||
[end_description] | ||
Copyright 2009-2011 Karsten Ahnert | ||
Copyright 2009-2011 Mario Mulansky | ||
Distributed under the Boost Software License, Version 1.0. | ||
(See accompanying file LICENSE_1_0.txt or | ||
copy at http://www.boost.org/LICENSE_1_0.txt) | ||
*/ | ||
|
||
|
||
#ifndef BOOST_NUMERIC_ODEINT_EXTERNAL_MPI_MPI_NESTED_ALGEBRA_HPP_INCLUDED | ||
#define BOOST_NUMERIC_ODEINT_EXTERNAL_MPI_MPI_NESTED_ALGEBRA_HPP_INCLUDED | ||
|
||
#include <boost/numeric/odeint/algebra/norm_result_type.hpp> | ||
#include <boost/numeric/odeint/util/n_ary_helper.hpp> | ||
|
||
namespace boost { | ||
namespace numeric { | ||
namespace odeint { | ||
|
||
/** \brief MPI-parallelized algebra, wrapping another algebra. | ||
*/ | ||
template< class InnerAlgebra > | ||
struct mpi_nested_algebra | ||
{ | ||
|
||
// execute the InnerAlgebra on each node's local data. | ||
#define BOOST_ODEINT_GEN_BODY(n) \ | ||
InnerAlgebra::for_each##n( \ | ||
BOOST_PP_ENUM_BINARY_PARAMS(n, s, .data BOOST_PP_INTERCEPT) , \ | ||
op \ | ||
); | ||
BOOST_ODEINT_GEN_FOR_EACH(BOOST_ODEINT_GEN_BODY) | ||
#undef BOOST_ODEINT_GEN_BODY | ||
|
||
|
||
template< class NestedState > | ||
static typename norm_result_type< typename NestedState::value_type >::type norm_inf( const NestedState &s ) | ||
{ | ||
typedef typename norm_result_type< typename NestedState::value_type >::type result_type; | ||
// local maximum | ||
result_type value = InnerAlgebra::norm_inf( s.data ); | ||
// global maximum | ||
return boost::mpi::all_reduce(s.world, value, boost::mpi::maximum<result_type>()); | ||
} | ||
|
||
}; | ||
|
||
|
||
} | ||
} | ||
} | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
/* | ||
[auto_generated] | ||
boost/numeric/odeint/external/mpi/mpi_state.hpp | ||
[begin_description] | ||
A generic split state, storing partial data on each node. | ||
[end_description] | ||
Copyright 2009-2011 Karsten Ahnert | ||
Copyright 2009-2011 Mario Mulansky | ||
Distributed under the Boost Software License, Version 1.0. | ||
(See accompanying file LICENSE_1_0.txt or | ||
copy at http://www.boost.org/LICENSE_1_0.txt) | ||
*/ | ||
|
||
|
||
#ifndef BOOST_NUMERIC_ODEINT_EXTERNAL_MPI_MPI_STATE_HPP_INCLUDED | ||
#define BOOST_NUMERIC_ODEINT_EXTERNAL_MPI_MPI_STATE_HPP_INCLUDED | ||
|
||
#include <vector> | ||
#include <algorithm> | ||
#include <boost/mpi.hpp> | ||
#include <boost/numeric/odeint/util/copy.hpp> | ||
#include <boost/numeric/odeint/util/resize.hpp> | ||
#include <boost/numeric/odeint/util/same_size.hpp> | ||
#include <boost/numeric/odeint/algebra/algebra_dispatcher.hpp> | ||
#include "mpi_nested_algebra.hpp" | ||
|
||
namespace boost { | ||
namespace numeric { | ||
namespace odeint { | ||
|
||
/** \brief A container which has its contents distributed among the nodes. | ||
*/ | ||
template< class InnerState > | ||
struct mpi_state | ||
{ | ||
typedef InnerState value_type; | ||
|
||
// the node's local data. | ||
InnerState data; | ||
|
||
boost::mpi::communicator world; | ||
|
||
mpi_state() {} | ||
mpi_state(boost::mpi::communicator comm) : world(comm) {} | ||
}; | ||
|
||
|
||
|
||
|
||
template< class InnerState > | ||
struct is_resizeable< mpi_state< InnerState > > | ||
: is_resizeable< InnerState > { }; | ||
|
||
|
||
template< class InnerState > | ||
struct same_size_impl< mpi_state< InnerState > , mpi_state< InnerState > > | ||
{ | ||
static bool same_size( const mpi_state< InnerState > &x , const mpi_state< InnerState > &y ) | ||
{ | ||
const bool local = boost::numeric::odeint::same_size(x.data, y.data); | ||
return boost::mpi::all_reduce(x.world, local, mpi::bitwise_and<bool>()); | ||
} | ||
}; | ||
|
||
|
||
template< class InnerState > | ||
struct resize_impl< mpi_state< InnerState > , mpi_state< InnerState > > | ||
{ | ||
static void resize( mpi_state< InnerState > &x , const mpi_state< InnerState > &y ) | ||
{ | ||
// resize local parts on each node. | ||
boost::numeric::odeint::resize(x.data, y.data); | ||
} | ||
}; | ||
|
||
|
||
/** \brief Copy data between mpi_states of same size. */ | ||
template< class InnerState > | ||
struct copy_impl< mpi_state< InnerState >, mpi_state< InnerState > > | ||
{ | ||
static void copy( const mpi_state< InnerState > &from, mpi_state< InnerState > &to ) | ||
{ | ||
// copy local parts on each node. | ||
boost::numeric::odeint::copy(from.data, to.data); | ||
} | ||
}; | ||
|
||
|
||
|
||
/** \brief Use `mpi_algebra` for `mpi_state`. */ | ||
template< class InnerState > | ||
struct algebra_dispatcher< mpi_state< InnerState > > | ||
{ | ||
typedef mpi_nested_algebra< | ||
typename algebra_dispatcher< InnerState >::algebra_type | ||
> algebra_type; | ||
}; | ||
|
||
|
||
} | ||
} | ||
} | ||
|
||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
/* | ||
[auto_generated] | ||
boost/numeric/odeint/external/mpi/mpi_vector_state.hpp | ||
[begin_description] | ||
Copying a container from/to an mpi_state splits/joins it. | ||
[end_description] | ||
Copyright 2009-2011 Karsten Ahnert | ||
Copyright 2009-2011 Mario Mulansky | ||
Distributed under the Boost Software License, Version 1.0. | ||
(See accompanying file LICENSE_1_0.txt or | ||
copy at http://www.boost.org/LICENSE_1_0.txt) | ||
*/ | ||
|
||
|
||
#ifndef BOOST_NUMERIC_ODEINT_EXTERNAL_MPI_MPI_VECTOR_STATE_HPP_INCLUDED | ||
#define BOOST_NUMERIC_ODEINT_EXTERNAL_MPI_MPI_VECTOR_STATE_HPP_INCLUDED | ||
|
||
#include <vector> | ||
#include <algorithm> | ||
#include <boost/mpi.hpp> | ||
#include <boost/numeric/odeint/util/copy.hpp> | ||
#include <boost/numeric/odeint/algebra/algebra_dispatcher.hpp> | ||
#include "mpi_state.hpp" | ||
|
||
namespace boost { | ||
namespace numeric { | ||
namespace odeint { | ||
|
||
|
||
/** \brief Copy data from some container on node 0 to the slaves. | ||
* SourceContainer must support `s::value_type`, `s::const_iterator`, `s.begin()`, `s.end()` and `s.size()`, | ||
* with Random Access Iterators; i.e. it must be a Random Access Container. */ | ||
template< class SourceContainer > | ||
struct copy_impl< SourceContainer, mpi_state< std::vector< typename SourceContainer::value_type > > > | ||
{ | ||
static void copy( const SourceContainer &from, mpi_state< std::vector< typename SourceContainer::value_type > > &to ) | ||
{ | ||
typedef typename SourceContainer::const_iterator it_t; | ||
typedef typename SourceContainer::value_type T; | ||
std::vector< std::vector<T> > pieces; | ||
if(to.world.rank() == 0) { | ||
// split as evenly as possible; length difference is at most 1. | ||
const size_t num = static_cast<size_t>(to.world.size()); | ||
const size_t part = from.size() / num; | ||
const size_t mod = from.size() % num; | ||
it_t begin = from.begin(), end = begin; | ||
pieces.resize(num); | ||
for(size_t i = 0 ; i < num ; i++) { | ||
const size_t offset = i < mod ? 1 : 0; | ||
end = begin + (part + offset); | ||
pieces[i].resize(end - begin); | ||
std::copy(begin, end, pieces[i].begin()); | ||
begin = end; | ||
} | ||
} | ||
// send to nodes | ||
boost::mpi::scatter(to.world, pieces, to.data, 0); | ||
} | ||
}; | ||
|
||
/** \brief Copy data from an mpi_state to some container on node 0. | ||
* TargetContainer must support `s::value_type`, `s::iterator`, `s.begin()` and `s.resize(n)`, | ||
* i.e. it must be a `std::vector`. */ | ||
template< class TargetContainer > | ||
struct copy_impl< mpi_state< std::vector< typename TargetContainer::value_type > >, TargetContainer > | ||
{ | ||
static void copy( const mpi_state< std::vector< typename TargetContainer::value_type > > &from , TargetContainer &to ) | ||
{ | ||
typedef typename TargetContainer::value_type T; | ||
std::vector< std::vector<T> > pieces; | ||
// send data to root | ||
boost::mpi::gather(from.world, from.data, pieces, 0); | ||
if(from.world.rank() == 0) { | ||
// resize target | ||
size_t total_size = 0; | ||
for(size_t i = 0 ; i < pieces.size() ; i++) | ||
total_size += pieces[i].size(); | ||
to.resize( total_size ); | ||
// copy parts | ||
typename TargetContainer::iterator out = to.begin(); | ||
for(size_t i = 0 ; i < pieces.size() ; i++) | ||
out = std::copy(pieces[i].begin(), pieces[i].end(), out); | ||
} | ||
} | ||
}; | ||
|
||
|
||
|
||
} | ||
} | ||
} | ||
|
||
|
||
#endif | ||
|