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.

> 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_set_ui(g1, 2*b-1);
    mpz_mul_ui(g1, g1, 6*b-1);
    mpz_mul_ui(g1, g1, 6*b-5);

> 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.
  x = 2739218918L; // Conversion assignment operator.
  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.


More information about the gmp-discuss mailing list