Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:42:51

0001 /*
0002  [auto_generated]
0003  boost/numeric/odeint/external/openmp/openmp_state.hpp
0004 
0005  [begin_description]
0006  Wrappers for OpenMP.
0007  [end_description]
0008 
0009  Copyright 2013 Karsten Ahnert
0010  Copyright 2013 Mario Mulansky
0011  Copyright 2013 Pascal Germroth
0012 
0013  Distributed under the Boost Software License, Version 1.0.
0014  (See accompanying file LICENSE_1_0.txt or
0015  copy at http://www.boost.org/LICENSE_1_0.txt)
0016  */
0017 
0018 
0019 #ifndef BOOST_NUMERIC_ODEINT_EXTERNAL_OPENMP_OPENMP_STATE_HPP_INCLUDED
0020 #define BOOST_NUMERIC_ODEINT_EXTERNAL_OPENMP_OPENMP_STATE_HPP_INCLUDED
0021 
0022 #include <omp.h>
0023 #include <vector>
0024 #include <algorithm>
0025 #include <boost/range/adaptor/sliced.hpp>
0026 #include <boost/numeric/odeint/util/copy.hpp>
0027 #include <boost/numeric/odeint/util/split.hpp>
0028 #include <boost/numeric/odeint/util/resize.hpp>
0029 #include <boost/numeric/odeint/external/openmp/openmp_nested_algebra.hpp>
0030 
0031 namespace boost {
0032 namespace numeric {
0033 namespace odeint {
0034 
0035 /** \brief A container that is split into distinct parts, for threading.
0036  * Just a wrapper for vector<vector<T>>, use `copy` for splitting/joining.
0037  */
0038 template< class T >
0039 struct openmp_state : public std::vector< std::vector< T > >
0040 {
0041     openmp_state() {}
0042 
0043     openmp_state(size_t n, const std::vector<T>& val = std::vector<T>())
0044     : std::vector< std::vector< T > >(n, val) {}
0045 
0046     template<class InputIterator>
0047     openmp_state(InputIterator first, InputIterator last)
0048     : std::vector< std::vector< T > >(first, last) {}
0049 
0050     openmp_state(const std::vector< std::vector< T > > &orig)
0051     : std::vector< std::vector< T > >(orig) {}
0052 
0053 };
0054 
0055 
0056 
0057 
0058 template< class T >
0059 struct is_resizeable< openmp_state< T > > : boost::true_type { };
0060 
0061 
0062 template< class T >
0063 struct same_size_impl< openmp_state< T > , openmp_state< T > >
0064 {
0065     static bool same_size( const openmp_state< T > &x , const openmp_state< T > &y )
0066     {
0067         if( x.size() != y.size() ) return false;
0068         for( size_t i = 0 ; i != x.size() ; i++ )
0069             if( x[i].size() != y[i].size() ) return false;
0070         return true;
0071     }
0072 };
0073 
0074 
0075 template< class T >
0076 struct resize_impl< openmp_state< T > , openmp_state< T > >
0077 {
0078     static void resize( openmp_state< T > &x , const openmp_state< T > &y )
0079     {
0080         x.resize( y.size() );
0081 #       pragma omp parallel for schedule(dynamic)
0082         for(size_t i = 0 ; i < x.size() ; i++)
0083             x[i].resize( y[i].size() );
0084     }
0085 };
0086 
0087 
0088 /** \brief Copy data between openmp_states of same size. */
0089 template< class T >
0090 struct copy_impl< openmp_state< T >, openmp_state< T > >
0091 {
0092     static void copy( const openmp_state< T > &from, openmp_state< T > &to )
0093     {
0094 #       pragma omp parallel for schedule(dynamic)
0095         for(size_t i = 0 ; i < from.size() ; i++)
0096             std::copy( from[i].begin() , from[i].end() , to.begin() );
0097     }
0098 };
0099 
0100 
0101 
0102 /** \brief Copy data from some container to an openmp_state and resize it.
0103  * Target container size will determine number of blocks to split into.
0104  * If it is empty, it will be resized to the maximum number of OpenMP threads.
0105  * SourceContainer must support `s::value_type`, `s::const_iterator`, `s.begin()`, `s.end()` and `s.size()`,
0106  * with Random Access Iterators; i.e. it must be a Random Access Container. */
0107 template< class SourceContainer >
0108 struct split_impl< SourceContainer, openmp_state< typename SourceContainer::value_type > >
0109 {
0110     static void split( const SourceContainer &from, openmp_state< typename SourceContainer::value_type > &to )
0111     {
0112         if(to.size() == 0) to.resize( omp_get_max_threads() );
0113         const size_t part = from.size() / to.size();
0114 #       pragma omp parallel for schedule(dynamic)
0115         for(size_t i = 0 ; i < to.size() ; i++) {
0116             typedef typename SourceContainer::const_iterator it_t;
0117             const it_t begin = from.begin() + i * part;
0118             it_t end = begin + part;
0119             // for cases where from.size() % to.size() > 0
0120             if(i + 1 == to.size() || end > from.end()) end = from.end();
0121             to[i].resize(end - begin);
0122             std::copy(begin, end, to[i].begin());
0123         }
0124     }
0125 };
0126 
0127 /** \brief Copy data from an openmp_state to some container and resize it.
0128  * TargetContainer must support `s::value_type`, `s::iterator`, `s.begin()` and `s.resize(n)`,
0129  * i.e. it must be a `std::vector`. */
0130 template< class TargetContainer >
0131 struct unsplit_impl< openmp_state< typename TargetContainer::value_type >, TargetContainer >
0132 {
0133     static void unsplit( const openmp_state< typename TargetContainer::value_type > &from , TargetContainer &to )
0134     {
0135         // resize target
0136         size_t total_size = 0;
0137         for(size_t i = 0 ; i < from.size() ; i++)
0138             total_size += from[i].size();
0139         to.resize( total_size );
0140         // copy parts
0141         typename TargetContainer::iterator out = to.begin();
0142         for(size_t i = 0 ; i < from.size() ; i++)
0143             out = std::copy(from[i].begin(), from[i].end(), out);
0144     }
0145 };
0146 
0147 
0148 
0149 
0150 /** \brief OpenMP-parallelized algebra.
0151  * For use with openmp_state.
0152  */
0153 typedef openmp_nested_algebra< range_algebra > openmp_algebra;
0154 
0155 
0156 
0157 /** \brief Use `openmp_algebra` for `openmp_state`. */
0158 template< class T >
0159 struct algebra_dispatcher< openmp_state< T > >
0160 {
0161     typedef openmp_algebra algebra_type;
0162 };
0163 
0164 
0165 }
0166 }
0167 }
0168 
0169 
0170 #endif
0171