]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /* |
2 | [auto_generated] | |
3 | boost/numeric/odeint/external/openmp/openmp_state.hpp | |
4 | ||
5 | [begin_description] | |
6 | Wrappers for OpenMP. | |
7 | [end_description] | |
8 | ||
9 | Copyright 2013 Karsten Ahnert | |
10 | Copyright 2013 Mario Mulansky | |
11 | Copyright 2013 Pascal Germroth | |
12 | ||
13 | Distributed under the Boost Software License, Version 1.0. | |
14 | (See accompanying file LICENSE_1_0.txt or | |
15 | copy at http://www.boost.org/LICENSE_1_0.txt) | |
16 | */ | |
17 | ||
18 | ||
19 | #ifndef BOOST_NUMERIC_ODEINT_EXTERNAL_OPENMP_OPENMP_STATE_HPP_INCLUDED | |
20 | #define BOOST_NUMERIC_ODEINT_EXTERNAL_OPENMP_OPENMP_STATE_HPP_INCLUDED | |
21 | ||
22 | #include <omp.h> | |
23 | #include <vector> | |
24 | #include <algorithm> | |
25 | #include <boost/range/adaptor/sliced.hpp> | |
26 | #include <boost/numeric/odeint/util/copy.hpp> | |
27 | #include <boost/numeric/odeint/util/split.hpp> | |
28 | #include <boost/numeric/odeint/util/resize.hpp> | |
29 | #include <boost/numeric/odeint/external/openmp/openmp_nested_algebra.hpp> | |
30 | ||
31 | namespace boost { | |
32 | namespace numeric { | |
33 | namespace odeint { | |
34 | ||
35 | /** \brief A container that is split into distinct parts, for threading. | |
36 | * Just a wrapper for vector<vector<T>>, use `copy` for splitting/joining. | |
37 | */ | |
38 | template< class T > | |
39 | struct openmp_state : public std::vector< std::vector< T > > | |
40 | { | |
41 | openmp_state() {} | |
42 | ||
43 | openmp_state(size_t n, const std::vector<T>& val = std::vector<T>()) | |
44 | : std::vector< std::vector< T > >(n, val) {} | |
45 | ||
46 | template<class InputIterator> | |
47 | openmp_state(InputIterator first, InputIterator last) | |
48 | : std::vector< std::vector< T > >(first, last) {} | |
49 | ||
50 | openmp_state(const std::vector< std::vector< T > > &orig) | |
51 | : std::vector< std::vector< T > >(orig) {} | |
52 | ||
53 | }; | |
54 | ||
55 | ||
56 | ||
57 | ||
58 | template< class T > | |
59 | struct is_resizeable< openmp_state< T > > : boost::true_type { }; | |
60 | ||
61 | ||
62 | template< class T > | |
63 | struct same_size_impl< openmp_state< T > , openmp_state< T > > | |
64 | { | |
65 | static bool same_size( const openmp_state< T > &x , const openmp_state< T > &y ) | |
66 | { | |
67 | if( x.size() != y.size() ) return false; | |
68 | for( size_t i = 0 ; i != x.size() ; i++ ) | |
69 | if( x[i].size() != y[i].size() ) return false; | |
70 | return true; | |
71 | } | |
72 | }; | |
73 | ||
74 | ||
75 | template< class T > | |
76 | struct resize_impl< openmp_state< T > , openmp_state< T > > | |
77 | { | |
78 | static void resize( openmp_state< T > &x , const openmp_state< T > &y ) | |
79 | { | |
80 | x.resize( y.size() ); | |
81 | # pragma omp parallel for schedule(dynamic) | |
82 | for(size_t i = 0 ; i < x.size() ; i++) | |
83 | x[i].resize( y[i].size() ); | |
84 | } | |
85 | }; | |
86 | ||
87 | ||
88 | /** \brief Copy data between openmp_states of same size. */ | |
89 | template< class T > | |
90 | struct copy_impl< openmp_state< T >, openmp_state< T > > | |
91 | { | |
92 | static void copy( const openmp_state< T > &from, openmp_state< T > &to ) | |
93 | { | |
94 | # pragma omp parallel for schedule(dynamic) | |
95 | for(size_t i = 0 ; i < from.size() ; i++) | |
96 | std::copy( from[i].begin() , from[i].end() , to.begin() ); | |
97 | } | |
98 | }; | |
99 | ||
100 | ||
101 | ||
102 | /** \brief Copy data from some container to an openmp_state and resize it. | |
103 | * Target container size will determine number of blocks to split into. | |
104 | * If it is empty, it will be resized to the maximum number of OpenMP threads. | |
105 | * SourceContainer must support `s::value_type`, `s::const_iterator`, `s.begin()`, `s.end()` and `s.size()`, | |
106 | * with Random Access Iterators; i.e. it must be a Random Access Container. */ | |
107 | template< class SourceContainer > | |
108 | struct split_impl< SourceContainer, openmp_state< typename SourceContainer::value_type > > | |
109 | { | |
110 | static void split( const SourceContainer &from, openmp_state< typename SourceContainer::value_type > &to ) | |
111 | { | |
112 | if(to.size() == 0) to.resize( omp_get_max_threads() ); | |
113 | const size_t part = from.size() / to.size(); | |
114 | # pragma omp parallel for schedule(dynamic) | |
115 | for(size_t i = 0 ; i < to.size() ; i++) { | |
116 | typedef typename SourceContainer::const_iterator it_t; | |
117 | const it_t begin = from.begin() + i * part; | |
118 | it_t end = begin + part; | |
119 | // for cases where from.size() % to.size() > 0 | |
120 | if(i + 1 == to.size() || end > from.end()) end = from.end(); | |
121 | to[i].resize(end - begin); | |
122 | std::copy(begin, end, to[i].begin()); | |
123 | } | |
124 | } | |
125 | }; | |
126 | ||
127 | /** \brief Copy data from an openmp_state to some container and resize it. | |
128 | * TargetContainer must support `s::value_type`, `s::iterator`, `s.begin()` and `s.resize(n)`, | |
129 | * i.e. it must be a `std::vector`. */ | |
130 | template< class TargetContainer > | |
131 | struct unsplit_impl< openmp_state< typename TargetContainer::value_type >, TargetContainer > | |
132 | { | |
133 | static void unsplit( const openmp_state< typename TargetContainer::value_type > &from , TargetContainer &to ) | |
134 | { | |
135 | // resize target | |
136 | size_t total_size = 0; | |
137 | for(size_t i = 0 ; i < from.size() ; i++) | |
138 | total_size += from[i].size(); | |
139 | to.resize( total_size ); | |
140 | // copy parts | |
141 | typename TargetContainer::iterator out = to.begin(); | |
142 | for(size_t i = 0 ; i < from.size() ; i++) | |
143 | out = std::copy(from[i].begin(), from[i].end(), out); | |
144 | } | |
145 | }; | |
146 | ||
147 | ||
148 | ||
149 | ||
150 | /** \brief OpenMP-parallelized algebra. | |
151 | * For use with openmp_state. | |
152 | */ | |
153 | typedef openmp_nested_algebra< range_algebra > openmp_algebra; | |
154 | ||
155 | ||
156 | ||
157 | /** \brief Use `openmp_algebra` for `openmp_state`. */ | |
158 | template< class T > | |
159 | struct algebra_dispatcher< openmp_state< T > > | |
160 | { | |
161 | typedef openmp_algebra algebra_type; | |
162 | }; | |
163 | ||
164 | ||
165 | } | |
166 | } | |
167 | } | |
168 | ||
169 | ||
170 | #endif | |
171 |