PageRenderTime 39ms CodeModel.GetById 17ms app.highlight 18ms RepoModel.GetById 1ms app.codeStats 0ms

/Src/Dependencies/Boost/libs/phoenix/example/parallel_for.cpp

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