On 27/08/2024 22:44, Kai Song wrote:
Thank you, David! That was very useful!
Glad to be of help!
I don't think expression templates are going to be able to cover
everything. I have only played with them a little myself, not used them
seriously, so I am no expert here. But I would expect you will hit
limitations with them long before you get to global transformations - I
think they will be a challenge as soon as there is more than one
reasonable way to transform an expression. Still, I think they could be
a cheap (in terms of your time as a developer) way to handle some common
transforms, such as combinations of constants.
In my head, I have a vague notion of having two classes -
Expression_Constant<Numeric n> and Expression_Variable, both inheriting
from an Expression<> template using CRTP to provide compile-time
polymorphism. Code can use an "if consteval" to determine whether a
given Numeric is known to be a constant (and thus put it in an
Expression_Constant<>) or not.
Combining Expression_Constant<> objects should be quite easy - just
provide operator overloads. The real "fun" comes when you mix them with
Expression_Variable's. You perhaps need some way to turn "x + y + z"
into a single function call "add(x, y, z)" - then you can provide
overloads for that function for different combinations of Constant and
Variable, letting you combine Constant's even if they are not adjacent.
Of course, that depends on Numeric's operations being commutative and
associative - you have to decide on that!
David
You said one thing very nicely:
>> you cannot expect to be able to lift floating-point specific parts
from deep within
the gcc optimiser and re-use them for your own code here.
I confirm that this was it that I was expecting (or rather hoping :) ).
Given my pessimism drawn from the apparent misunderstanding in the
communication prior, I have already started
to re-implement those expression templates that are probably hidden deep
within GCC.
Now as you and I discussed expression templates, my reluctance with
those at first is their limitation
on the complexity of DAG optimizations due to only permitting
transformations that are possible via
meta programming (i.e., no global DAG transformations).
But that is then just a practical 20-80 rule where one has to make
compromises.
Thank you for considering my question in detail and answering helpfully!
On Tue, Aug 27, 2024 at 10:26 AM David Brown <david.brown@xxxxxxxxxxxx
<mailto:david.brown@xxxxxxxxxxxx>> wrote:
I think expression templates are what you need here.
The "-ffast-math" optimisations are very specific to floating point
calculations, and are quite dependent on the underlying implementation
of floating point. Contrary to Segher's pessimism, "-ffast-math" is
extremely useful and gives significantly better end results in
situations where it is appropriate. But like any floating point work,
you need to understand the limitations and the suitability for the task
at hand.
I can't see how they could be of any use to you here, other than
perhaps
that the documentation for the flag might be an inspiration for the
kind
of re-arrangements you want to support. As I understand it, it is the
code you are writing that will do the re-arrangements - you cannot
expect to be able to lift floating-point specific parts from deep
within
the gcc optimiser and re-use them for your own code here.
You have to decide what re-arrangement rules you will accept for your
Number type, and build up appropriate expression templates. The rules
you accept will depend entirely on what "Number" is. If it represents
ideal mathematical integers, then you get lots of possibilities. If it
represents fixed-size floating point numbers, then now re-arranging "(x
+ y) - x" into "y" can give a very different result. Just like with
"-ffast-math", such a re-arrangement is fine if you are equally happy
with both results.
David
On 27/08/2024 00:04, Kai Song via Gcc-help wrote:
> I would like to add an example so as to clarify what it is that I
seek help
> on:
>
> I have a custom implementation of a class called Number. Number has
> overloaded operators that write down a program of all
computations that
> Number witnesses in an original program.
> For example, when the original program reads (original code):
> z=x-(-y);
>
> Then upon execution with type Number the following program will
be produced
> (generated code) as caused through stream buffers in Number:
> tmp1 = -y;
> z = x-tmp1;
>
> This generated code is inferior to as if the original code had been
> "z=x+y;".
> Using expression templates or hoping for excellent compiler
optimization on
> the "generated code", I could try to improve the performance of the
> generated code.
> But that means equal to re-inventing the wheel, because obviously the
> compilers have exactly these algebraic optimization capabilities
already
> built in.
> So I want to use these capabilities. This is what my request is
all about.
>
> Certainly the compiler has algebraic expression optimization
built in, so
> what I now seek to find out is whether and how this can be leveraged
> outside the rule-scope of native c++,
> so as to improve the algebra of my original code. Of course I am
aware that
> this alters the original programs result entirely (as per the above
> example) but this is precisely what I wish for.
>
> Kind regards
>
>
>
> In response to Segher:
>
> On Mon, Aug 26, 2024 at 7:19 PM Segher Boessenkool <
> segher@xxxxxxxxxxxxxxxxxxx <mailto:segher@xxxxxxxxxxxxxxxxxxx>>
wrote:
>
>> On Mon, Aug 26, 2024 at 06:00:21PM +0200, Kai Song via Gcc-help
wrote:
>>> I would like to learn more how GCC implements algebraic
optimization
>>> heuristic such as given in -ffast-math .
>>
>> Thank you for responding. Yet I cannot make sense of your
response or
> whether if how it relates to what I asked about.
>
>
>> Oh dear.
>>
>>> In particular, I have a type Number that is used in a code
>>
>> -ffast-math means you are not dealing with numbers at all, but
instead
>> with quantities somewhat akin to numbers, and you don't give two
hoots
>> about what happens with them.
>>
>
> Well if it was able to "deal" with anything akin to numbers, that
would
> imply I can tell it to treat a type as if it was a number.
> Clearly however, that is not the case. So you may have meant
something
> else, which is impossible to identify then due to ambiguity.
> This is unfortunate because I deeply care. So if you indeed mean that
> fastmath can be applied to anything akin to numbers,
> I am looking forward to how I can use the compilers abilities in that
> regard to transform algebraic expressions with custom types.
>
>
>>
>> It replaces floating point expressions by other expressions that are
>> at best vaguely related, and almost always compute a very different
>> result.
>>
>
> Yes, so here it is besides the question; because my custom type
Number,
> which is the single point of interest in the communication, is not a
> floating point type.
>
>
>>
>> If you do not care about your numbers at all, and (against better
>> judgement) prefer more speed over all quality, you can use
-ffast-math.
>>
>
> Well apparently I cannot, as per my question, since the algebraic
> expressions are involving my custom class Number.
>
>
>> Or, you can admit you think arithmetic is magic. It is fine to use
>> then, too.
>>
>
> I am a mathematician. I do not know nor wonder what you seek to say.
> I do care that arithmetic expressions are concise and equivalent.
> For instance, I like when "z=x-(-y);" is replaced by "z=x+y;"
where x and y
> may be of type Number.
>
>
>> Segher
>>
>