C++11 classes
Hans Aberg
haberg-1 at telia.com
Wed Nov 16 12:51:19 CET 2011
On 16 Nov 2011, at 12:23, Marc Glisse wrote:
>> I drafted some C++11 classes integer etc., using move constructors and assignment operators,
>
> Something like that is likely to eventually get standardized in C++, but it may be a while yet.
It is in the new standard as of August.
https://en.wikipedia.org/wiki/C++11
> Note that without lazy initialization, gmp doesn't benefit from moves as much as it could.
I'm not sure what you have in mind here.
>> and then testing with a conversion of the pi program. In the most optimized version, the overhead is less than 10% relative C or C compile as C++,
>
> I believe you can get 0 overhead with gmpxx.
Possibly. The idea here, is to accept some overhead for a considerably simpler syntax. For example, write
gmp::integer g1;
g1 = 2*b-1;
g1 *= 6*b-1;
g1 *= 6*b-5;
...
instead of
mpz_init(g1)
mpz_set_ui(g1, 2*b-1);
mpz_mul_ui(g1, g1, 6*b-1);
mpz_mul_ui(g1, g1, 6*b-5);
...
mpz_clear(q1);
> Also, the overhead tends to play a comparatively larger role with small numbers (just a couple limbs, where even a mpz_swap is non-negligible) as opposed to huge numbers.
From my the tests with the pi program, it is important to eliminate the copying. But when there was a lot of move assignments, that causes 30 - 50% overhead.
>> and the funny thing is that it does not call any constructors or assignments at all. The reason is that either the compiler can optimize them away, or in a few cases, one can do some rewriting.
>
> I am not sure what you mean by that. When you write x=y*y, the compiler creates a temporary in which it puts the result of the multiplication and then it calls the move assignment. Or do you mean you rewrote the thing to never use * but only *= ?
It turns out that the pi program uses the latter. So the translation is of the form
gmp::integer g1 x = 2739218918L; // Conversion constructor.
or
x = 2739218918L; // Conversion assignment operator.
and
x *= y; // x mutates.
Part of the move elimination was done by adding conversion assignment operators. That is, along with
integer::integer(signed long int x) { mpz_init_set_si(value_, x); }
also have
integer& integer::operator=(unsigned long int x)
{ mpz_set_ui(value_, x); return *this; }
Further copying/moving can be done by using a reference count. I wrote a small calculator using Flex/Bison for testing, using that, and it turns out that it is neither invoking any of that.
Hans
More information about the gmp-discuss
mailing list