openmp_nested_algebra.hpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. /*
  2. [auto_generated]
  3. boost/numeric/odeint/external/openmp/openmp_nested_algebra.hpp
  4. [begin_description]
  5. Nested parallelized algebra for OpenMP.
  6. [end_description]
  7. Copyright 2013 Karsten Ahnert
  8. Copyright 2013 Mario Mulansky
  9. Copyright 2013 Pascal Germroth
  10. Distributed under the Boost Software License, Version 1.0.
  11. (See accompanying file LICENSE_1_0.txt or
  12. copy at http://www.boost.org/LICENSE_1_0.txt)
  13. */
  14. #ifndef BOOST_NUMERIC_ODEINT_EXTERNAL_OPENMP_OPENMP_NESTED_ALGEBRA_HPP_INCLUDED
  15. #define BOOST_NUMERIC_ODEINT_EXTERNAL_OPENMP_OPENMP_NESTED_ALGEBRA_HPP_INCLUDED
  16. #include <boost/assert.hpp>
  17. #include <boost/range.hpp>
  18. #include <boost/numeric/odeint/algebra/norm_result_type.hpp>
  19. #include <boost/numeric/odeint/util/n_ary_helper.hpp>
  20. namespace boost {
  21. namespace numeric {
  22. namespace odeint {
  23. /** \brief OpenMP-parallelized algebra, wrapping another, non-parallelized algebra.
  24. *
  25. * NestedState must be a model of Random Access Range, where the elements are sub-states
  26. * which will be processed in parallel.
  27. */
  28. template< class InnerAlgebra >
  29. struct openmp_nested_algebra
  30. {
  31. #if __cplusplus >= 201103L // C++11 supports _Pragma
  32. #define BOOST_ODEINT_GEN_LOCAL(z, n, unused) \
  33. BOOST_ASSERT_MSG( len == boost::size(s ## n), "All nested state ranges must have the same size." ); \
  34. typename boost::range_iterator<S ## n>::type beg ## n = boost::begin(s ## n);
  35. #define BOOST_ODEINT_GEN_BODY(n) \
  36. const size_t len = boost::size(s0); \
  37. BOOST_PP_REPEAT(n, BOOST_ODEINT_GEN_LOCAL, ~) \
  38. _Pragma("omp parallel for schedule(runtime)") \
  39. for( size_t i = 0 ; i < len ; i++ ) \
  40. InnerAlgebra::for_each##n( \
  41. BOOST_PP_ENUM_BINARY_PARAMS(n, beg, [i] BOOST_PP_INTERCEPT) , \
  42. op \
  43. );
  44. BOOST_ODEINT_GEN_FOR_EACH(BOOST_ODEINT_GEN_BODY)
  45. #undef BOOST_ODEINT_GEN_BODY
  46. #undef BOOST_ODEINT_GEN_LOCAL
  47. #else
  48. template< class S0 , class Op > static void for_each1 ( S0 &s0 , Op op ) {
  49. const size_t len = boost::size(s0);
  50. typename boost::range_iterator<S0>::type beg0 = boost::begin(s0);
  51. #pragma omp parallel for schedule(runtime)
  52. for( size_t i = 0 ; i < len ; i++ ) InnerAlgebra::for_each1( beg0 [i] , op );
  53. }
  54. template< class S0 , class S1 , class Op > static void for_each2 ( S0 &s0 , S1 &s1 , Op op ) {
  55. const size_t len = boost::size(s0);
  56. typename boost::range_iterator<S0>::type beg0 = boost::begin(s0);
  57. typename boost::range_iterator<S1>::type beg1 = boost::begin(s1);
  58. #pragma omp parallel for schedule(runtime)
  59. for( size_t i = 0 ; i < len ; i++ ) InnerAlgebra::for_each2( beg0 [i] , beg1 [i] , op );
  60. }
  61. template< class S0 , class S1 , class S2 , class Op > static void for_each3 ( S0 &s0 , S1 &s1 , S2 &s2 , Op op ) {
  62. const size_t len = boost::size(s0);
  63. typename boost::range_iterator<S0>::type beg0 = boost::begin(s0);
  64. typename boost::range_iterator<S1>::type beg1 = boost::begin(s1);
  65. typename boost::range_iterator<S2>::type beg2 = boost::begin(s2);
  66. #pragma omp parallel for schedule(runtime)
  67. for( size_t i = 0 ; i < len ; i++ ) InnerAlgebra::for_each3( beg0 [i] , beg1 [i] , beg2 [i] , op );
  68. }
  69. template< class S0 , class S1 , class S2 , class S3 , class Op > static void for_each4 ( S0 &s0 , S1 &s1 , S2 &s2 , S3 &s3 , Op op ) {
  70. const size_t len = boost::size(s0);
  71. typename boost::range_iterator<S0>::type beg0 = boost::begin(s0);
  72. typename boost::range_iterator<S1>::type beg1 = boost::begin(s1);
  73. typename boost::range_iterator<S2>::type beg2 = boost::begin(s2);
  74. typename boost::range_iterator<S3>::type beg3 = boost::begin(s3);
  75. #pragma omp parallel for schedule(runtime)
  76. for( size_t i = 0 ; i < len ; i++ ) InnerAlgebra::for_each4( beg0 [i] , beg1 [i] , beg2 [i] , beg3 [i] , op );
  77. }
  78. template< class S0 , class S1 , class S2 , class S3 , class S4 , class Op > static void for_each5 ( S0 &s0 , S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , Op op ) {
  79. const size_t len = boost::size(s0);
  80. typename boost::range_iterator<S0>::type beg0 = boost::begin(s0);
  81. typename boost::range_iterator<S1>::type beg1 = boost::begin(s1);
  82. typename boost::range_iterator<S2>::type beg2 = boost::begin(s2);
  83. typename boost::range_iterator<S3>::type beg3 = boost::begin(s3);
  84. typename boost::range_iterator<S4>::type beg4 = boost::begin(s4);
  85. #pragma omp parallel for schedule(runtime)
  86. for( size_t i = 0 ; i < len ; i++ ) InnerAlgebra::for_each5( beg0 [i] , beg1 [i] , beg2 [i] , beg3 [i] , beg4 [i] , op );
  87. }
  88. template< class S0 , class S1 , class S2 , class S3 , class S4 , class S5 , class Op > static void for_each6 ( S0 &s0 , S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , Op op ) {
  89. const size_t len = boost::size(s0);
  90. typename boost::range_iterator<S0>::type beg0 = boost::begin(s0);
  91. typename boost::range_iterator<S1>::type beg1 = boost::begin(s1);
  92. typename boost::range_iterator<S2>::type beg2 = boost::begin(s2);
  93. typename boost::range_iterator<S3>::type beg3 = boost::begin(s3);
  94. typename boost::range_iterator<S4>::type beg4 = boost::begin(s4);
  95. typename boost::range_iterator<S5>::type beg5 = boost::begin(s5);
  96. #pragma omp parallel for schedule(runtime)
  97. for( size_t i = 0 ; i < len ; i++ ) InnerAlgebra::for_each6( beg0 [i] , beg1 [i] , beg2 [i] , beg3 [i] , beg4 [i] , beg5 [i] , op );
  98. }
  99. template< class S0 , class S1 , class S2 , class S3 , class S4 , class S5 , class S6 , class Op > static void for_each7 ( S0 &s0 , S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , Op op ) {
  100. const size_t len = boost::size(s0);
  101. typename boost::range_iterator<S0>::type beg0 = boost::begin(s0);
  102. typename boost::range_iterator<S1>::type beg1 = boost::begin(s1);
  103. typename boost::range_iterator<S2>::type beg2 = boost::begin(s2);
  104. typename boost::range_iterator<S3>::type beg3 = boost::begin(s3);
  105. typename boost::range_iterator<S4>::type beg4 = boost::begin(s4);
  106. typename boost::range_iterator<S5>::type beg5 = boost::begin(s5);
  107. typename boost::range_iterator<S6>::type beg6 = boost::begin(s6);
  108. #pragma omp parallel for schedule(runtime)
  109. for( size_t i = 0 ; i < len ; i++ ) InnerAlgebra::for_each7( beg0 [i] , beg1 [i] , beg2 [i] , beg3 [i] , beg4 [i] , beg5 [i] , beg6 [i] , op );
  110. }
  111. template< class S0 , class S1 , class S2 , class S3 , class S4 , class S5 , class S6 , class S7 , class Op > static void for_each8 ( S0 &s0 , S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , Op op ) {
  112. const size_t len = boost::size(s0);
  113. typename boost::range_iterator<S0>::type beg0 = boost::begin(s0);
  114. typename boost::range_iterator<S1>::type beg1 = boost::begin(s1);
  115. typename boost::range_iterator<S2>::type beg2 = boost::begin(s2);
  116. typename boost::range_iterator<S3>::type beg3 = boost::begin(s3);
  117. typename boost::range_iterator<S4>::type beg4 = boost::begin(s4);
  118. typename boost::range_iterator<S5>::type beg5 = boost::begin(s5);
  119. typename boost::range_iterator<S6>::type beg6 = boost::begin(s6);
  120. typename boost::range_iterator<S7>::type beg7 = boost::begin(s7);
  121. #pragma omp parallel for schedule(runtime)
  122. for( size_t i = 0 ; i < len ; i++ ) InnerAlgebra::for_each8( beg0 [i] , beg1 [i] , beg2 [i] , beg3 [i] , beg4 [i] , beg5 [i] , beg6 [i] , beg7 [i] , op );
  123. }
  124. template< class S0 , class S1 , class S2 , class S3 , class S4 , class S5 , class S6 , class S7 , class S8 , class Op > static void for_each9 ( S0 &s0 , S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , S8 &s8 , Op op ) {
  125. const size_t len = boost::size(s0);
  126. typename boost::range_iterator<S0>::type beg0 = boost::begin(s0);
  127. typename boost::range_iterator<S1>::type beg1 = boost::begin(s1);
  128. typename boost::range_iterator<S2>::type beg2 = boost::begin(s2);
  129. typename boost::range_iterator<S3>::type beg3 = boost::begin(s3);
  130. typename boost::range_iterator<S4>::type beg4 = boost::begin(s4);
  131. typename boost::range_iterator<S5>::type beg5 = boost::begin(s5);
  132. typename boost::range_iterator<S6>::type beg6 = boost::begin(s6);
  133. typename boost::range_iterator<S7>::type beg7 = boost::begin(s7);
  134. typename boost::range_iterator<S8>::type beg8 = boost::begin(s8);
  135. #pragma omp parallel for schedule(runtime)
  136. for( size_t i = 0 ; i < len ; i++ ) InnerAlgebra::for_each9( beg0 [i] , beg1 [i] , beg2 [i] , beg3 [i] , beg4 [i] , beg5 [i] , beg6 [i] , beg7 [i] , beg8 [i] , op );
  137. }
  138. template< class S0 , class S1 , class S2 , class S3 , class S4 , class S5 , class S6 , class S7 , class S8 , class S9 , class Op > static void for_each10 ( S0 &s0 , S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , S8 &s8 , S9 &s9 , Op op ) {
  139. const size_t len = boost::size(s0);
  140. typename boost::range_iterator<S0>::type beg0 = boost::begin(s0);
  141. typename boost::range_iterator<S1>::type beg1 = boost::begin(s1);
  142. typename boost::range_iterator<S2>::type beg2 = boost::begin(s2);
  143. typename boost::range_iterator<S3>::type beg3 = boost::begin(s3);
  144. typename boost::range_iterator<S4>::type beg4 = boost::begin(s4);
  145. typename boost::range_iterator<S5>::type beg5 = boost::begin(s5);
  146. typename boost::range_iterator<S6>::type beg6 = boost::begin(s6);
  147. typename boost::range_iterator<S7>::type beg7 = boost::begin(s7);
  148. typename boost::range_iterator<S8>::type beg8 = boost::begin(s8);
  149. typename boost::range_iterator<S9>::type beg9 = boost::begin(s9);
  150. #pragma omp parallel for schedule(runtime)
  151. for( size_t i = 0 ; i < len ; i++ ) InnerAlgebra::for_each10( beg0 [i] , beg1 [i] , beg2 [i] , beg3 [i] , beg4 [i] , beg5 [i] , beg6 [i] , beg7 [i] , beg8 [i] , beg9 [i] , op );
  152. }
  153. template< class S0 , class S1 , class S2 , class S3 , class S4 , class S5 , class S6 , class S7 , class S8 , class S9 , class S10 , class Op > static void for_each11 ( S0 &s0 , S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , S8 &s8 , S9 &s9 , S10 &s10 , Op op ) {
  154. const size_t len = boost::size(s0);
  155. typename boost::range_iterator<S0>::type beg0 = boost::begin(s0);
  156. typename boost::range_iterator<S1>::type beg1 = boost::begin(s1);
  157. typename boost::range_iterator<S2>::type beg2 = boost::begin(s2);
  158. typename boost::range_iterator<S3>::type beg3 = boost::begin(s3);
  159. typename boost::range_iterator<S4>::type beg4 = boost::begin(s4);
  160. typename boost::range_iterator<S5>::type beg5 = boost::begin(s5);
  161. typename boost::range_iterator<S6>::type beg6 = boost::begin(s6);
  162. typename boost::range_iterator<S7>::type beg7 = boost::begin(s7);
  163. typename boost::range_iterator<S8>::type beg8 = boost::begin(s8);
  164. typename boost::range_iterator<S9>::type beg9 = boost::begin(s9);
  165. typename boost::range_iterator<S10>::type beg10 = boost::begin(s10);
  166. #pragma omp parallel for schedule(runtime)
  167. for( size_t i = 0 ; i < len ; i++ ) InnerAlgebra::for_each11( beg0 [i] , beg1 [i] , beg2 [i] , beg3 [i] , beg4 [i] , beg5 [i] , beg6 [i] , beg7 [i] , beg8 [i] , beg9 [i] , beg10 [i] , op );
  168. }
  169. template< class S0 , class S1 , class S2 , class S3 , class S4 , class S5 , class S6 , class S7 , class S8 , class S9 , class S10 , class S11 , class Op > static void for_each12 ( S0 &s0 , S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , S8 &s8 , S9 &s9 , S10 &s10 , S11 &s11 , Op op ) {
  170. const size_t len = boost::size(s0);
  171. typename boost::range_iterator<S0>::type beg0 = boost::begin(s0);
  172. typename boost::range_iterator<S1>::type beg1 = boost::begin(s1);
  173. typename boost::range_iterator<S2>::type beg2 = boost::begin(s2);
  174. typename boost::range_iterator<S3>::type beg3 = boost::begin(s3);
  175. typename boost::range_iterator<S4>::type beg4 = boost::begin(s4);
  176. typename boost::range_iterator<S5>::type beg5 = boost::begin(s5);
  177. typename boost::range_iterator<S6>::type beg6 = boost::begin(s6);
  178. typename boost::range_iterator<S7>::type beg7 = boost::begin(s7);
  179. typename boost::range_iterator<S8>::type beg8 = boost::begin(s8);
  180. typename boost::range_iterator<S9>::type beg9 = boost::begin(s9);
  181. typename boost::range_iterator<S10>::type beg10 = boost::begin(s10);
  182. typename boost::range_iterator<S11>::type beg11 = boost::begin(s11);
  183. #pragma omp parallel for schedule(runtime)
  184. for( size_t i = 0 ; i < len ; i++ ) InnerAlgebra::for_each12( beg0 [i] , beg1 [i] , beg2 [i] , beg3 [i] , beg4 [i] , beg5 [i] , beg6 [i] , beg7 [i] , beg8 [i] , beg9 [i] , beg10 [i] , beg11 [i] , op );
  185. }
  186. template< class S0 , class S1 , class S2 , class S3 , class S4 , class S5 , class S6 , class S7 , class S8 , class S9 , class S10 , class S11 , class S12 , class Op > static void for_each13 ( S0 &s0 , S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , S8 &s8 , S9 &s9 , S10 &s10 , S11 &s11 , S12 &s12 , Op op ) {
  187. const size_t len = boost::size(s0);
  188. typename boost::range_iterator<S0>::type beg0 = boost::begin(s0);
  189. typename boost::range_iterator<S1>::type beg1 = boost::begin(s1);
  190. typename boost::range_iterator<S2>::type beg2 = boost::begin(s2);
  191. typename boost::range_iterator<S3>::type beg3 = boost::begin(s3);
  192. typename boost::range_iterator<S4>::type beg4 = boost::begin(s4);
  193. typename boost::range_iterator<S5>::type beg5 = boost::begin(s5);
  194. typename boost::range_iterator<S6>::type beg6 = boost::begin(s6);
  195. typename boost::range_iterator<S7>::type beg7 = boost::begin(s7);
  196. typename boost::range_iterator<S8>::type beg8 = boost::begin(s8);
  197. typename boost::range_iterator<S9>::type beg9 = boost::begin(s9);
  198. typename boost::range_iterator<S10>::type beg10 = boost::begin(s10);
  199. typename boost::range_iterator<S11>::type beg11 = boost::begin(s11);
  200. typename boost::range_iterator<S12>::type beg12 = boost::begin(s12);
  201. #pragma omp parallel for schedule(runtime)
  202. for( size_t i = 0 ; i < len ; i++ ) InnerAlgebra::for_each13( beg0 [i] , beg1 [i] , beg2 [i] , beg3 [i] , beg4 [i] , beg5 [i] , beg6 [i] , beg7 [i] , beg8 [i] , beg9 [i] , beg10 [i] , beg11 [i] , beg12 [i] , op );
  203. }
  204. template< class S0 , class S1 , class S2 , class S3 , class S4 , class S5 , class S6 , class S7 , class S8 , class S9 , class S10 , class S11 , class S12 , class S13 , class Op > static void for_each14 ( S0 &s0 , S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , S8 &s8 , S9 &s9 , S10 &s10 , S11 &s11 , S12 &s12 , S13 &s13 , Op op ) {
  205. const size_t len = boost::size(s0);
  206. typename boost::range_iterator<S0>::type beg0 = boost::begin(s0);
  207. typename boost::range_iterator<S1>::type beg1 = boost::begin(s1);
  208. typename boost::range_iterator<S2>::type beg2 = boost::begin(s2);
  209. typename boost::range_iterator<S3>::type beg3 = boost::begin(s3);
  210. typename boost::range_iterator<S4>::type beg4 = boost::begin(s4);
  211. typename boost::range_iterator<S5>::type beg5 = boost::begin(s5);
  212. typename boost::range_iterator<S6>::type beg6 = boost::begin(s6);
  213. typename boost::range_iterator<S7>::type beg7 = boost::begin(s7);
  214. typename boost::range_iterator<S8>::type beg8 = boost::begin(s8);
  215. typename boost::range_iterator<S9>::type beg9 = boost::begin(s9);
  216. typename boost::range_iterator<S10>::type beg10 = boost::begin(s10);
  217. typename boost::range_iterator<S11>::type beg11 = boost::begin(s11);
  218. typename boost::range_iterator<S12>::type beg12 = boost::begin(s12);
  219. typename boost::range_iterator<S13>::type beg13 = boost::begin(s13);
  220. #pragma omp parallel for schedule(runtime)
  221. for( size_t i = 0 ; i < len ; i++ ) InnerAlgebra::for_each14( beg0 [i] , beg1 [i] , beg2 [i] , beg3 [i] , beg4 [i] , beg5 [i] , beg6 [i] , beg7 [i] , beg8 [i] , beg9 [i] , beg10 [i] , beg11 [i] , beg12 [i] , beg13 [i] , op );
  222. }
  223. template< class S0 , class S1 , class S2 , class S3 , class S4 , class S5 , class S6 , class S7 , class S8 , class S9 , class S10 , class S11 , class S12 , class S13 , class S14 , class Op > static void for_each15 ( S0 &s0 , S1 &s1 , S2 &s2 , S3 &s3 , S4 &s4 , S5 &s5 , S6 &s6 , S7 &s7 , S8 &s8 , S9 &s9 , S10 &s10 , S11 &s11 , S12 &s12 , S13 &s13 , S14 &s14 , Op op ) {
  224. const size_t len = boost::size(s0);
  225. typename boost::range_iterator<S0>::type beg0 = boost::begin(s0);
  226. typename boost::range_iterator<S1>::type beg1 = boost::begin(s1);
  227. typename boost::range_iterator<S2>::type beg2 = boost::begin(s2);
  228. typename boost::range_iterator<S3>::type beg3 = boost::begin(s3);
  229. typename boost::range_iterator<S4>::type beg4 = boost::begin(s4);
  230. typename boost::range_iterator<S5>::type beg5 = boost::begin(s5);
  231. typename boost::range_iterator<S6>::type beg6 = boost::begin(s6);
  232. typename boost::range_iterator<S7>::type beg7 = boost::begin(s7);
  233. typename boost::range_iterator<S8>::type beg8 = boost::begin(s8);
  234. typename boost::range_iterator<S9>::type beg9 = boost::begin(s9);
  235. typename boost::range_iterator<S10>::type beg10 = boost::begin(s10);
  236. typename boost::range_iterator<S11>::type beg11 = boost::begin(s11);
  237. typename boost::range_iterator<S12>::type beg12 = boost::begin(s12);
  238. typename boost::range_iterator<S13>::type beg13 = boost::begin(s13);
  239. typename boost::range_iterator<S14>::type beg14 = boost::begin(s14);
  240. #pragma omp parallel for schedule(runtime)
  241. for( size_t i = 0 ; i < len ; i++ ) InnerAlgebra::for_each15( beg0 [i] , beg1 [i] , beg2 [i] , beg3 [i] , beg4 [i] , beg5 [i] , beg6 [i] , beg7 [i] , beg8 [i] , beg9 [i] , beg10 [i] , beg11 [i] , beg12 [i] , beg13 [i] , beg14 [i] , op );
  242. }
  243. #endif
  244. template< class NestedState >
  245. static typename norm_result_type< typename NestedState::value_type >::type norm_inf( const NestedState &s )
  246. {
  247. typedef typename boost::range_iterator<const NestedState>::type iterator;
  248. typedef typename std::iterator_traits<iterator>::value_type value_type;
  249. typedef typename norm_result_type<value_type>::type result_type;
  250. result_type init = static_cast< result_type >( 0 );
  251. const size_t len = boost::size(s);
  252. iterator beg = boost::begin(s);
  253. # pragma omp parallel for reduction(max: init) schedule(dynamic)
  254. for( size_t i = 0 ; i < len ; i++ )
  255. init = (std::max)( init , InnerAlgebra::norm_inf( beg[i] ) );
  256. return init;
  257. }
  258. };
  259. }
  260. }
  261. }
  262. #endif