Skip to content

support pre-allocation in BigInt ctor #21983

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 4, 2019
Merged

support pre-allocation in BigInt ctor #21983

merged 2 commits into from
Jun 4, 2019

Conversation

rfourquet
Copy link
Member

The allows to initialize a BigInt with enough space to encode an n-bits integer (so this is an optimization compared to the function MPZ.realloc!, so as to avoid allocating twice).

This was initially implemented in #13815 and discussed there. It was suggested to make this functionality a method of sizehint!, but this has to be implemented in the inner constructor of BigInt, so I don't think it's possible. I don't mind the mecanism (I originally used a ::Val{:allocbits}, now ::typeof(sizehint!)), suggestions welcome!

@ararslan ararslan added the maths Mathematical functions label May 20, 2017
@rfourquet
Copy link
Member Author

What about creating a "BigInt" label? (or "bignum" to include BigFloat).

@rfourquet
Copy link
Member Author

I realized there are already "rationals" and "complex" labels, so sureley a "bignums" label seems deserved!

@rfourquet rfourquet added the bignums BigInt and BigFloat label May 23, 2017
@rfourquet
Copy link
Member Author

This is a tiny change, I think only the API can be controversial: I would choose BigInt(Val{:uninitialized}) or something similar, but am fine with any. Can someone make a call, e.g. @JeffBezanson or @vtjnash who had already commented on the API in #13815 ?

@tkelman
Copy link
Contributor

tkelman commented May 29, 2017

tests, docs?

@rfourquet
Copy link
Member Author

My last post was confusing: currently this PR defines a method to reserve at creation time a space big enough to store later a number with n bits. An alternative is to be able to create an unitialized number, on which to call mpz.init2!.
I can add tests/docs when the API is decided upon.

base/gmp.jl Outdated
end

# n is the number of bits to allocate
function BigInt(::typeof(sizehint!), n)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bit of a strange API, IMO. How about BigInt(; sizehint::Int=0) instead?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's strange and I would rather not use this API. I would prefer a Val{:unitit} or Val{:allocsize} argument, or a dedicated type, or even Type{Bool}. But I wanted to avoid a keyword argument because the goal of the PR is to make a small optimization, which becomes worse than the status quo with the overhead of keyword arguments. Currently b=BigInt() takes 50 ns on my machine and calling realloc(b, 200) from GMP on it costs 65ns; with a keyword arg, BigIng(sizehint=200) takes about 180ns, and BigInt() takes 120ns !; but BigInt(Val{:allocsize}, 200) takes about 50ns. Those numbers vary with the sizehint parameter (200 here), but always show that a keyword arg would be a no-go if optimization is sought after.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

keyword arguments are likely to get faster fairly soon, so we should avoid making too many ugly API choices as workarounds for them being slow now

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok then I can wait for no-overhead keywords.

@rfourquet
Copy link
Member Author

Now that keywords are fast, I reimplemented using the nbits keyword to control the bit length of the created BigInt (e.g. BigInt(nbits=128)). As an example, I updated the implementation of + for BigInt, which become 40% faster on my machine for 1-Limb bigints.
Please help bikesheding the nbits keyword name.

@rfourquet
Copy link
Member Author

I will merge in a few days if no objection. The name of the keyword is rather inconsequential and remains for now an implementation detail.

@KristofferC
Copy link
Member

If this is a performance change, should run Nanosoldier before merging.

@KristofferC KristofferC added the performance Must go faster label May 21, 2019
@KristofferC
Copy link
Member

@nanosoldier runbenchmarks(ALL, vs = ":master")

@nanosoldier
Copy link
Collaborator

Your benchmark job has completed - possible performance regressions were detected. A full report can be found here. cc @ararslan

@rfourquet
Copy link
Member Author

There seems to be some real performance regressions.

@jebej
Copy link
Contributor

jebej commented May 22, 2019

Not sure how much it would matter but should we wait after #32102 before testing performance?

edit: it see it has been merged

@KristofferC
Copy link
Member

Note, it's only been merged into the backport branch. But yes, it is true that the benchmarks might not be completely reliable if the bignum lib is built with bad optimizations.

@rfourquet
Copy link
Member Author

I can't reproduce locally the regressions, let's try again.

@nanosoldier runbenchmarks(ALL, vs = ":master")

@nanosoldier
Copy link
Collaborator

Your benchmark job has completed - possible performance regressions were detected. A full report can be found here. cc @ararslan

@rfourquet
Copy link
Member Author

In the two nanosoldier runs, I kept regressions wich are worse by more than 2% than what the tolerance allows, and the intersection contains 6 benchmarks, which are all unrelated to BigInt, so all shown regressions must be noise.

@rfourquet rfourquet merged commit c5d190e into master Jun 4, 2019
@rfourquet rfourquet deleted the rf/big-init2 branch June 4, 2019 09:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bignums BigInt and BigFloat maths Mathematical functions performance Must go faster
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants