parallel_for.cpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. /*=============================================================================
  2. Copyright (c) 2001-2007 Joel de Guzman
  3. Distributed under the Boost Software License, Version 1.0. (See accompanying
  4. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. ==============================================================================*/
  6. #include <boost/phoenix.hpp>
  7. struct omp_for_eval
  8. {
  9. typedef void result_type;
  10. template <typename Init, typename Cond, typename Step, typename Do, typename Context>
  11. result_type
  12. operator()(
  13. Init const& init
  14. , Cond const& cond
  15. , Step const& step
  16. , Do const& do_
  17. , Context & ctx
  18. ) const
  19. {
  20. #pragma omp parallel
  21. for(
  22. boost::phoenix::eval(init, ctx);
  23. boost::phoenix::eval(cond, ctx);
  24. boost::phoenix::eval(step, ctx)
  25. )
  26. {
  27. boost::phoenix::eval(do_, ctx);
  28. }
  29. }
  30. };
  31. ////////////////////////////////////////////////////////////////////////////////
  32. // Define new custom expression
  33. BOOST_PHOENIX_DEFINE_EXPRESSION(
  34. (omp_for)
  35. , (boost::phoenix::meta_grammar) // Cond
  36. (boost::phoenix::meta_grammar) // Init
  37. (boost::phoenix::meta_grammar) // Step
  38. (boost::phoenix::meta_grammar) // Do
  39. )
  40. namespace boost { namespace phoenix
  41. {
  42. template <>
  43. struct default_actions::when< ::rule::omp_for>
  44. : boost::phoenix::call< ::omp_for_eval>
  45. {};
  46. }}
  47. template <typename Init, typename Cond, typename Step>
  48. struct omp_for_gen
  49. {
  50. omp_for_gen(Init const& init, Cond const& cond, Step const& step)
  51. : init(init), cond(cond), step(step) {}
  52. template <typename Do>
  53. typename result_of::make_omp_for<Init, Cond, Step, Do>::type const
  54. operator[](Do const& do_) const
  55. {
  56. return make_omp_for(init, cond, step, do_);
  57. }
  58. Init init;
  59. Cond cond;
  60. Step step;
  61. };
  62. template <typename Init, typename Cond, typename Step>
  63. inline
  64. omp_for_gen<Init, Cond, Step> const
  65. omp_for(Init const& init, Cond const& cond, Step const& step)
  66. {
  67. return omp_for_gen<Init, Cond, Step>(init, cond, step);
  68. }
  69. ////////////////////////////////////////////////////////////////////////////////
  70. ////////////////////////////////////////////////////////////////////////////////
  71. // Define new evaluation scheme
  72. struct parallel_actions
  73. {
  74. template <typename Rule>
  75. struct when
  76. : boost::phoenix::default_actions::when<Rule>
  77. {};
  78. };
  79. template <>
  80. struct parallel_actions::when<boost::phoenix::rule::for_>
  81. : boost::phoenix::call<omp_for_eval>
  82. {};
  83. // Doing the same as actor<Expr>::operator
  84. template <typename Expr, typename A0, typename A1, typename A2>
  85. typename boost::phoenix::result_of::eval<
  86. Expr const &
  87. , typename boost::phoenix::result_of::make_context<
  88. typename boost::phoenix::result_of::make_env<
  89. Expr const *
  90. , A0 &
  91. , A1 &
  92. , A2 &
  93. >::type
  94. , parallel_actions
  95. >::type
  96. >::type
  97. parallel_eval(Expr & expr, A0 & a0, A1 & a1, A2 & a2)
  98. {
  99. Expr const * this_ = boost::addressof(expr);
  100. return
  101. boost::phoenix::eval(
  102. expr
  103. , boost::phoenix::make_context(
  104. boost::phoenix::make_env(this_, a0, a1, a2)
  105. , parallel_actions()
  106. )
  107. );
  108. }
  109. // changing evaluation mechanism on the fly
  110. BOOST_PHOENIX_DEFINE_EXPRESSION(
  111. (parallel)
  112. , (boost::phoenix::meta_grammar)
  113. )
  114. namespace boost { namespace phoenix
  115. {
  116. template <>
  117. struct default_actions::when< ::rule::parallel>
  118. : proto::call<
  119. evaluator(
  120. proto::_child0
  121. , functional::make_context(
  122. _env
  123. , parallel_actions()
  124. )
  125. , unused()//mpl::void_()
  126. )
  127. >
  128. {};
  129. }}
  130. template <typename Expr>
  131. typename result_of::make_parallel<Expr>::type
  132. parallel(Expr const & expr)
  133. {
  134. return make_parallel(expr);
  135. }
  136. ////////////////////////////////////////////////////////////////////////////////
  137. #include <vector>
  138. #include <iostream>
  139. int main()
  140. {
  141. using boost::phoenix::arg_names::_1;
  142. using boost::phoenix::arg_names::_2;
  143. using boost::phoenix::arg_names::_3;
  144. using boost::phoenix::local_names::_a;
  145. using boost::phoenix::local_names::_b;
  146. using boost::phoenix::local_names::_c;
  147. using boost::phoenix::let;
  148. using boost::phoenix::bind;
  149. using boost::phoenix::lambda;
  150. using boost::phoenix::nothing;
  151. const int NUM = 1;
  152. {
  153. std::vector<int> a(NUM, 1);
  154. std::vector<int> b(NUM, 2);
  155. std::vector<int> c(NUM, 0);
  156. (
  157. let(_a = begin(_1), _b = begin(_2), _c = begin(_3))
  158. [
  159. for_(nothing, _a != end(_1), (++_a, ++_b, ++_c))
  160. [
  161. *_c = *_a + *_b
  162. ]
  163. ]
  164. , std::cout << accumulate(_3, 0) << "\n"
  165. )(a, b, c);
  166. }
  167. {
  168. std::vector<int> a(NUM, 1);
  169. std::vector<int> b(NUM, 2);
  170. std::vector<int> c(NUM, 0);
  171. (
  172. let(_a = begin(_1), _b = begin(_2), _c = begin(_3))
  173. [
  174. omp_for(nothing, _a != end(_1), (++_a, ++_b, ++_c))
  175. [
  176. *_c = *_a + *_b
  177. ]
  178. , std::cout << accumulate(_3, 0) << "\n"
  179. ]
  180. )(a, b, c);
  181. }
  182. {
  183. std::vector<int> a(NUM, 1);
  184. std::vector<int> b(NUM, 2);
  185. std::vector<int> c(NUM, 0);
  186. parallel_eval(
  187. let(_a = begin(_1), _b = begin(_2), _c = begin(_3))
  188. [
  189. for_(nothing, _a != end(_1), (++_a, ++_b, ++_c))
  190. [
  191. *_c = *_a + *_b
  192. ]
  193. , std::cout << accumulate(_3, 0) << "\n"
  194. ]
  195. , a, b, c);
  196. }
  197. {
  198. std::vector<int> a(NUM, 1);
  199. std::vector<int> b(NUM, 2);
  200. std::vector<int> c(NUM, 0);
  201. (
  202. let(_a = begin(_1), _b = begin(_2), _c = begin(_3))
  203. [
  204. parallel(
  205. for_(nothing, _a != end(_1), (++_a, ++_b, ++_c))
  206. [
  207. *_c = *_a + *_b
  208. ]
  209. )
  210. ]
  211. , std::cout << accumulate(_3, 0) << "\n"
  212. )(a, b, c);
  213. }
  214. }