246 lines
6.2 KiB
C++
246 lines
6.2 KiB
C++
/*=============================================================================
|
|
Copyright (c) 2001-2007 Joel de Guzman
|
|
|
|
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
==============================================================================*/
|
|
|
|
#include <boost/phoenix.hpp>
|
|
|
|
struct omp_for_eval
|
|
{
|
|
typedef void result_type;
|
|
|
|
template <typename Init, typename Cond, typename Step, typename Do, typename Context>
|
|
result_type
|
|
operator()(
|
|
Init const& init
|
|
, Cond const& cond
|
|
, Step const& step
|
|
, Do const& do_
|
|
, Context & ctx
|
|
) const
|
|
{
|
|
#pragma omp parallel
|
|
for(
|
|
boost::phoenix::eval(init, ctx);
|
|
boost::phoenix::eval(cond, ctx);
|
|
boost::phoenix::eval(step, ctx)
|
|
)
|
|
{
|
|
boost::phoenix::eval(do_, ctx);
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// Define new custom expression
|
|
BOOST_PHOENIX_DEFINE_EXPRESSION(
|
|
(omp_for)
|
|
, (boost::phoenix::meta_grammar) // Cond
|
|
(boost::phoenix::meta_grammar) // Init
|
|
(boost::phoenix::meta_grammar) // Step
|
|
(boost::phoenix::meta_grammar) // Do
|
|
)
|
|
|
|
namespace boost { namespace phoenix
|
|
{
|
|
template <>
|
|
struct default_actions::when< ::rule::omp_for>
|
|
: boost::phoenix::call< ::omp_for_eval>
|
|
{};
|
|
}}
|
|
|
|
template <typename Init, typename Cond, typename Step>
|
|
struct omp_for_gen
|
|
{
|
|
omp_for_gen(Init const& init, Cond const& cond, Step const& step)
|
|
: init(init), cond(cond), step(step) {}
|
|
|
|
template <typename Do>
|
|
typename result_of::make_omp_for<Init, Cond, Step, Do>::type const
|
|
operator[](Do const& do_) const
|
|
{
|
|
return make_omp_for(init, cond, step, do_);
|
|
}
|
|
|
|
Init init;
|
|
Cond cond;
|
|
Step step;
|
|
};
|
|
|
|
template <typename Init, typename Cond, typename Step>
|
|
inline
|
|
omp_for_gen<Init, Cond, Step> const
|
|
omp_for(Init const& init, Cond const& cond, Step const& step)
|
|
{
|
|
return omp_for_gen<Init, Cond, Step>(init, cond, step);
|
|
}
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// Define new evaluation scheme
|
|
|
|
struct parallel_actions
|
|
{
|
|
template <typename Rule>
|
|
struct when
|
|
: boost::phoenix::default_actions::when<Rule>
|
|
{};
|
|
};
|
|
|
|
template <>
|
|
struct parallel_actions::when<boost::phoenix::rule::for_>
|
|
: boost::phoenix::call<omp_for_eval>
|
|
{};
|
|
|
|
// Doing the same as actor<Expr>::operator
|
|
template <typename Expr, typename A0, typename A1, typename A2>
|
|
typename boost::phoenix::result_of::eval<
|
|
Expr const &
|
|
, typename boost::phoenix::result_of::make_context<
|
|
typename boost::phoenix::result_of::make_env<
|
|
Expr const *
|
|
, A0 &
|
|
, A1 &
|
|
, A2 &
|
|
>::type
|
|
, parallel_actions
|
|
>::type
|
|
>::type
|
|
parallel_eval(Expr & expr, A0 & a0, A1 & a1, A2 & a2)
|
|
{
|
|
Expr const * this_ = boost::addressof(expr);
|
|
return
|
|
boost::phoenix::eval(
|
|
expr
|
|
, boost::phoenix::make_context(
|
|
boost::phoenix::make_env(this_, a0, a1, a2)
|
|
, parallel_actions()
|
|
)
|
|
);
|
|
}
|
|
|
|
// changing evaluation mechanism on the fly
|
|
BOOST_PHOENIX_DEFINE_EXPRESSION(
|
|
(parallel)
|
|
, (boost::phoenix::meta_grammar)
|
|
)
|
|
|
|
namespace boost { namespace phoenix
|
|
{
|
|
template <>
|
|
struct default_actions::when< ::rule::parallel>
|
|
: proto::call<
|
|
evaluator(
|
|
proto::_child0
|
|
, functional::make_context(
|
|
_env
|
|
, parallel_actions()
|
|
)
|
|
, unused()//mpl::void_()
|
|
)
|
|
>
|
|
{};
|
|
}}
|
|
|
|
template <typename Expr>
|
|
typename result_of::make_parallel<Expr>::type
|
|
parallel(Expr const & expr)
|
|
{
|
|
return make_parallel(expr);
|
|
}
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
#include <vector>
|
|
#include <iostream>
|
|
|
|
int main()
|
|
{
|
|
using boost::phoenix::arg_names::_1;
|
|
using boost::phoenix::arg_names::_2;
|
|
using boost::phoenix::arg_names::_3;
|
|
using boost::phoenix::local_names::_a;
|
|
using boost::phoenix::local_names::_b;
|
|
using boost::phoenix::local_names::_c;
|
|
using boost::phoenix::let;
|
|
using boost::phoenix::bind;
|
|
using boost::phoenix::lambda;
|
|
using boost::phoenix::nothing;
|
|
|
|
const int NUM = 1;
|
|
|
|
{
|
|
std::vector<int> a(NUM, 1);
|
|
std::vector<int> b(NUM, 2);
|
|
std::vector<int> c(NUM, 0);
|
|
|
|
(
|
|
let(_a = begin(_1), _b = begin(_2), _c = begin(_3))
|
|
[
|
|
for_(nothing, _a != end(_1), (++_a, ++_b, ++_c))
|
|
[
|
|
*_c = *_a + *_b
|
|
]
|
|
]
|
|
, std::cout << accumulate(_3, 0) << "\n"
|
|
)(a, b, c);
|
|
}
|
|
|
|
{
|
|
std::vector<int> a(NUM, 1);
|
|
std::vector<int> b(NUM, 2);
|
|
std::vector<int> c(NUM, 0);
|
|
|
|
(
|
|
let(_a = begin(_1), _b = begin(_2), _c = begin(_3))
|
|
[
|
|
omp_for(nothing, _a != end(_1), (++_a, ++_b, ++_c))
|
|
[
|
|
*_c = *_a + *_b
|
|
]
|
|
, std::cout << accumulate(_3, 0) << "\n"
|
|
]
|
|
)(a, b, c);
|
|
}
|
|
|
|
{
|
|
std::vector<int> a(NUM, 1);
|
|
std::vector<int> b(NUM, 2);
|
|
std::vector<int> c(NUM, 0);
|
|
|
|
parallel_eval(
|
|
let(_a = begin(_1), _b = begin(_2), _c = begin(_3))
|
|
[
|
|
for_(nothing, _a != end(_1), (++_a, ++_b, ++_c))
|
|
[
|
|
*_c = *_a + *_b
|
|
]
|
|
, std::cout << accumulate(_3, 0) << "\n"
|
|
]
|
|
, a, b, c);
|
|
}
|
|
|
|
{
|
|
std::vector<int> a(NUM, 1);
|
|
std::vector<int> b(NUM, 2);
|
|
std::vector<int> c(NUM, 0);
|
|
|
|
(
|
|
let(_a = begin(_1), _b = begin(_2), _c = begin(_3))
|
|
[
|
|
parallel(
|
|
for_(nothing, _a != end(_1), (++_a, ++_b, ++_c))
|
|
[
|
|
*_c = *_a + *_b
|
|
]
|
|
)
|
|
]
|
|
, std::cout << accumulate(_3, 0) << "\n"
|
|
)(a, b, c);
|
|
}
|
|
}
|