Re: [proto] Transform result_of nightmare and preserving terminal identity

2012-11-03 Thread Mathias Gaunard

On 31/10/12 21:28, Agustín K-ballo Bergé wrote:


Quoting from my original mail, what I want is to replace the following
geometric vector expression:

 p = q + r;

by

 p[0] = q[0] + r[0],
 p[1] = q[1] + r[1],
 ...,
 p[N] = q[N] + r[N],
 p;

It **can** be done with a transform and that's what I did. The optimized
proto expression evaluates ~33% faster than the original proto expression.


You could also evaluate the expression directly instead of rebuilding a 
new expression to evaluate.


That would probably increase compilation performance.
___
proto mailing list
proto@lists.boost.org
http://lists.boost.org/mailman/listinfo.cgi/proto


Re: [proto] Transform result_of nightmare and preserving terminal identity

2012-10-31 Thread Agustín K-ballo Bergé

On 31/10/2012 05:28 p.m., Agustín K-ballo Bergé wrote:

On 31/10/2012 04:59 p.m., Eric Niebler wrote:

>I will
>continue my research by implementing a custom evaluation context that
>does this optimization 'on the fly', without actually modifying the
>expression.

 >

Evaluation contexts are weaker than transforms. If it can't be done with
a transform, it can't be done with a context. I can't tell from the code
fragment what exactly you're doing with the transforms you've written,
or whether they can be improved.


Quoting from my original mail, what I want is to replace the following
geometric vector expression:

 p = q + r;

by

 p[0] = q[0] + r[0],
 p[1] = q[1] + r[1],
 ...,
 p[N] = q[N] + r[N],
 p;

It **can** be done with a transform and that's what I did. The optimized
proto expression evaluates ~33% faster than the original proto expression.

I believe it can also be done with an evaluation context, that evaluates
an expression N times with a component-wise evaluation context. A
component-wise evaluation context would be a default context evaluation
except that vector terminals are evaluated to one of its scalar components.

Now that my transform finally works as intended, I will clean up the
code and upload it somewhere for you and anyone interested to see it.


I have uploaded my experiment to https://github.com/eggs-cpp/eggs-la . 
It only implements what is needed for my research, there are wholes 
pretty much everywhere.


Agustín K-ballo Bergé.-
http://fusionfenix.com

___
proto mailing list
proto@lists.boost.org
http://lists.boost.org/mailman/listinfo.cgi/proto


Re: [proto] Transform result_of nightmare and preserving terminal identity

2012-10-31 Thread Agustín K-ballo Bergé

On 31/10/2012 04:59 p.m., Eric Niebler wrote:

Proto expressions build and optimization times are not taken into
>account. There is a considerable number of expression copies made by the
>expression optimization that cannot be avoided by the compiler.

>

Expression copies ... during expression evaluation? I wonder why that's
necessary.


Not during expression evaluation, but during expression optimization. My 
optimization transform unrolls vector expressions into their 
component-wise expression equivalents; that generates a number of 
expressions that have to be held by value and hence copied.



>I will
>continue my research by implementing a custom evaluation context that
>does this optimization 'on the fly', without actually modifying the
>expression.

>

Evaluation contexts are weaker than transforms. If it can't be done with
a transform, it can't be done with a context. I can't tell from the code
fragment what exactly you're doing with the transforms you've written,
or whether they can be improved.


Quoting from my original mail, what I want is to replace the following 
geometric vector expression:


p = q + r;

by

p[0] = q[0] + r[0],
p[1] = q[1] + r[1],
...,
p[N] = q[N] + r[N],
p;

It **can** be done with a transform and that's what I did. The optimized 
proto expression evaluates ~33% faster than the original proto expression.


I believe it can also be done with an evaluation context, that evaluates 
an expression N times with a component-wise evaluation context. A 
component-wise evaluation context would be a default context evaluation 
except that vector terminals are evaluated to one of its scalar components.


Now that my transform finally works as intended, I will clean up the 
code and upload it somewhere for you and anyone interested to see it.


Agustín K-ballo Bergé.-
http://fusionfenix.com

___
proto mailing list
proto@lists.boost.org
http://lists.boost.org/mailman/listinfo.cgi/proto


Re: [proto] Transform result_of nightmare and preserving terminal identity

2012-10-31 Thread Eric Niebler
10/31/2012 12:30 PM, Agustín K-ballo Bergé wrote:
> On 16/10/2012 03:50 p.m., Agustín K-ballo Bergé wrote:
>> On 16/10/2012 02:22 a.m., Eric Niebler wrote:
>>> Hi Agustín,
>>>
>>> This is just a quick note to let you know that I'm currently at the
>>> standard committee meeting in Portland, and that I'll be unable to look
>>> until this until I get back next week.
>>>
>>
>> Thank you for letting me know.
> 
> For future reference, my issue was resolved at StackOverflow. You can
> find it here
> http://stackoverflow.com/questions/13146537/boost-proto-and-complex-transform

Heh, answered by me! Funny, I thought Bart's solution on this list had
answered your question, so I didn't come back to it.

> Preliminar tests for 1 evaluations of a simple expression `p = q
> + r * 3.f` where p, q and r are geometric vectors of 3 ints give the
> following promising times:
> 
> Regular: 1.15s
> Proto: 1.2s
> Hand-Unrolled: 0.39s
> Proto-Unrolled: 0.8s
> 
> Proto expressions build and optimization times are not taken into
> account. There is a considerable number of expression copies made by the
> expression optimization that cannot be avoided by the compiler. 

Expression copies ... during expression evaluation? I wonder why that's
necessary.

> I will
> continue my research by implementing a custom evaluation context that
> does this optimization 'on the fly', without actually modifying the
> expression.

Evaluation contexts are weaker than transforms. If it can't be done with
a transform, it can't be done with a context. I can't tell from the code
fragment what exactly you're doing with the transforms you've written,
or whether they can be improved.

-- 
Eric Niebler
BoostPro Computing
http://www.boostpro.com
___
proto mailing list
proto@lists.boost.org
http://lists.boost.org/mailman/listinfo.cgi/proto


Re: [proto] Transform result_of nightmare and preserving terminal identity

2012-10-31 Thread Agustín K-ballo Bergé

On 16/10/2012 03:50 p.m., Agustín K-ballo Bergé wrote:

On 16/10/2012 02:22 a.m., Eric Niebler wrote:

Hi Agustín,

This is just a quick note to let you know that I'm currently at the
standard committee meeting in Portland, and that I'll be unable to look
until this until I get back next week.



Thank you for letting me know.

Agustín K-ballo Bergé.-
http://fusionfenix.com

___
proto mailing list
proto@lists.boost.org
http://lists.boost.org/mailman/listinfo.cgi/proto




For future reference, my issue was resolved at StackOverflow. You can 
find it here 
http://stackoverflow.com/questions/13146537/boost-proto-and-complex-transform


Preliminar tests for 1 evaluations of a simple expression `p = q 
+ r * 3.f` where p, q and r are geometric vectors of 3 ints give the 
following promising times:


Regular: 1.15s
Proto: 1.2s
Hand-Unrolled: 0.39s
Proto-Unrolled: 0.8s

Proto expressions build and optimization times are not taken into 
account. There is a considerable number of expression copies made by the 
expression optimization that cannot be avoided by the compiler. I will 
continue my research by implementing a custom evaluation context that 
does this optimization 'on the fly', without actually modifying the 
expression.


Agustín K-ballo Bergé.-
http://fusionfenix.com

___
proto mailing list
proto@lists.boost.org
http://lists.boost.org/mailman/listinfo.cgi/proto


Re: [proto] Transform result_of nightmare and preserving terminal identity

2012-10-16 Thread Agustín K-ballo Bergé

On 16/10/2012 07:24 a.m., Bart Janssens wrote:

On Sun, Oct 14, 2012 at 1:20 AM, Agustín K-ballo Bergé
 wrote:

When deep copying an expression the 'identity' of the terminals is lost, as
each reference to a terminal results in a new hold by value terminal.
Consequently, expressions with side effects (like assignment) no longer
evaluate correctly. Is it possible to customize the expression 'semantics'
so that when a deep copy is made terminals are copied only the first time
they are seen, and subsequent uses refer to that first copy?


Hi Agustín,

Re-reading your question after Eric's nudge, I think this is similar
to a question I asked a while ago. Eric proposed replacing the
standard deep copy with a transform like this:

struct DeepCopy :
   boost::proto::or_
   <
 boost::proto::when // exceptions for terminals that need to be
stored by value
 <
   boost::proto::or_
   <
 boost::proto::terminal,
 boost::proto::terminal
   >,
   boost::proto::_make_terminal(boost::proto::_byval(boost::proto::_value))
 >,
 boost::proto::terminal,
 boost::proto::nary_expr > >
   >
{
};

This can then be called like DeepCopy()(your_expr). The when<>
template in here has some exceptions for terminals that I did want to
keep by value, so if you remove that all terminals should be stored by
reference in the copy. Concretely in the above example, const doubles
and ints are stored by value in the copy, all other types including
non-const doubles and ints are kept by reference. Hope this helps!

Cheers,



This is quite smart! If I can combine this with my domain's `as_child` 
then it is exactly what I need, I haven't even considered the 
possibility of using transforms there. Thank you for your help.


Agustín K-ballo Bergé.-
http://fusionfenix.com

___
proto mailing list
proto@lists.boost.org
http://lists.boost.org/mailman/listinfo.cgi/proto


Re: [proto] Transform result_of nightmare and preserving terminal identity

2012-10-16 Thread Agustín K-ballo Bergé

On 16/10/2012 02:22 a.m., Eric Niebler wrote:

Hi Agustín,

This is just a quick note to let you know that I'm currently at the
standard committee meeting in Portland, and that I'll be unable to look
until this until I get back next week.



Thank you for letting me know.

Agustín K-ballo Bergé.-
http://fusionfenix.com

___
proto mailing list
proto@lists.boost.org
http://lists.boost.org/mailman/listinfo.cgi/proto


Re: [proto] Transform result_of nightmare and preserving terminal identity

2012-10-16 Thread Bart Janssens
On Sun, Oct 14, 2012 at 1:20 AM, Agustín K-ballo Bergé
 wrote:
> When deep copying an expression the 'identity' of the terminals is lost, as
> each reference to a terminal results in a new hold by value terminal.
> Consequently, expressions with side effects (like assignment) no longer
> evaluate correctly. Is it possible to customize the expression 'semantics'
> so that when a deep copy is made terminals are copied only the first time
> they are seen, and subsequent uses refer to that first copy?

Hi Agustín,

Re-reading your question after Eric's nudge, I think this is similar
to a question I asked a while ago. Eric proposed replacing the
standard deep copy with a transform like this:

struct DeepCopy :
  boost::proto::or_
  <
boost::proto::when // exceptions for terminals that need to be
stored by value
<
  boost::proto::or_
  <
boost::proto::terminal,
boost::proto::terminal
  >,
  boost::proto::_make_terminal(boost::proto::_byval(boost::proto::_value))
>,
boost::proto::terminal,
boost::proto::nary_expr > >
  >
{
};

This can then be called like DeepCopy()(your_expr). The when<>
template in here has some exceptions for terminals that I did want to
keep by value, so if you remove that all terminals should be stored by
reference in the copy. Concretely in the above example, const doubles
and ints are stored by value in the copy, all other types including
non-const doubles and ints are kept by reference. Hope this helps!

Cheers,

-- 
Bart
___
proto mailing list
proto@lists.boost.org
http://lists.boost.org/mailman/listinfo.cgi/proto


Re: [proto] Transform result_of nightmare and preserving terminal identity

2012-10-15 Thread Eric Niebler
On 10/13/2012 4:20 PM, Agustín K-ballo Bergé wrote:
> Hi All,
> 
> I'm experimenting with Proto to build a DSEL that operates on geometric
> vectors. I'm trying to write a transform that would take an assign
> expression and unroll it component wise. For instance, I want to replace

Hi Agustín,

This is just a quick note to let you know that I'm currently at the
standard committee meeting in Portland, and that I'll be unable to look
until this until I get back next week. Sorry for the delay. Maybe
someone else on this list might be able to help (nudge!). You might also
pose this question on stackoverflow.com.

-- 
Eric Niebler
BoostPro Computing
http://www.boostpro.com
___
proto mailing list
proto@lists.boost.org
http://lists.boost.org/mailman/listinfo.cgi/proto


[proto] Transform result_of nightmare and preserving terminal identity

2012-10-13 Thread Agustín K-ballo Bergé

Hi All,

I'm experimenting with Proto to build a DSEL that operates on geometric 
vectors. I'm trying to write a transform that would take an assign 
expression and unroll it component wise. For instance, I want to replace


p = q + r;

by

p[0] = q[0] + r[0],
p[1] = q[1] + r[1],
...,
p[N] = q[N] + r[N],
p;

So far I have been able to *mostly* make it work by making a transform 
template unroll_vector_expr that recursively unrolls the expression for 
each vector component, in conjunction with a distribute_subscript 
transform (which I shamelessly took from Eric's article on C++Next).


I don't seem to understand whats the rationale for the 'parameters' used 
with `boost::result_of` and `result_of::make_expr`. The documentation, 
examples and internal code seem to mix `Expr`, `impl::expr` and 
`impl::expr_param`. I'm not sure what should I be using and when so that 
the `result_type` matches the actual result type. Currently I made it 
work by trial an error, by examining the error messages and fixing the 
`const` and `&` discrepancies (code for the transform attached). 
However, as soon as I deep copy the expression the terminals are no 
longer hold by reference and my code fails. Which incidentally brings me 
to my second question...


When deep copying an expression the 'identity' of the terminals is lost, 
as each reference to a terminal results in a new hold by value terminal. 
Consequently, expressions with side effects (like assignment) no longer 
evaluate correctly. Is it possible to customize the expression 
'semantics' so that when a deep copy is made terminals are copied only 
the first time they are seen, and subsequent uses refer to that first 
copy? Or should I be taking a completely different approach, perhaps by 
leaving operations with side effects outside of the grammar?


Thanks in advance for any help, and sorry if any of my questions is 
trivial or erroneous.


Agustín K-ballo Bergé.-
http://fusionfenix.com
struct distribute_subscript
: or_<
scalar_grammar
, when<
vector_literal
, _make_subscript( _, _state )
>
, plus< distribute_subscript, distribute_subscript >
, minus< distribute_subscript, distribute_subscript >
, multiplies< distribute_subscript, distribute_subscript >
, divides< distribute_subscript, distribute_subscript >
, assign< distribute_subscript, distribute_subscript >
>
{};

template< std::size_t I, std::size_t N >
struct unroll_vector_expr_c;

template< std::size_t N >
struct unroll_vector_expr_c< 0, N >
: transform< unroll_vector_expr_c< 0, N > >
{
template< typename Expr, typename State, typename Data >
struct impl
: transform_impl< Expr, State, Data >
{
typedef
typename result_of::make_expr<
tag::comma
, typename boost::result_of<
unroll_vector_expr_c< 1, N >(
typename impl::expr
)
>::type
, typename impl::state
>::type
result_type;

result_type operator ()(
typename impl::expr_param expr
, typename impl::state_param state
, typename impl::data_param data
) const
{
return
make_expr< tag::comma >(
unroll_vector_expr_c< 1, N >()(
expr
)
, state
);
}
};
};

template< std::size_t I, std::size_t N >
struct unroll_vector_expr_c
: transform< unroll_vector_expr_c< I, N > >
{
template< typename Expr, typename State, typename Data >
struct impl
: transform_impl< Expr, State, Data >
{
typedef
typename result_of::make_expr<
tag::comma
, typename boost::result_of<
distribute_subscript(
typename impl::expr_param
, typename result_of::make_expr<
tag::terminal
, boost::mpl::size_t< I - 1 >
>::type const&
)
>::type
, typename boost::result_of<
unroll_vector_expr_c< I + 1, N >(
typename impl::expr_param
)
>::type
>::type
result_type;

result_type operator ()(
typename impl::expr_param expr
, typename impl::state_param state
, typename impl::data_param data
) const
{
return
make_expr< tag::comma >(
distribute_subscript()(
expr
, make_expr< tag::terminal >( 
boost::mpl::size_t< I - 1 >()