Skip to content
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

merge 2 versions (for GMP 5 & 6) of rand(::UnitRange{BigInt}) #13815

Merged
merged 2 commits into from
Jun 3, 2017

Conversation

rfourquet
Copy link
Member

I saw the error caused by incompatible GMP versions (run time vs compile time) reported few times on the lists, but technically the versions need to agree only for rand(::UnitRange{BigInt}), so this PR proposes to remove this constraint.
That said I'm not sure if different versions of GMP could reveal other installation problems, so I kept a warning, please comment on this point.
The second commit optimizes slightly the pre-allocation of the random BigInt in some cases (the speed gains are very modest). This is not related to GMP versions, and I could as well make another PR for that.

base/gmp.jl Outdated
ccall((:__gmpz_init,:libgmp), Void, (Ptr{BigInt},), &b)
finalizer(b, _gmp_clear_func)
return b
function BigInt(::Val{:allocbits}, nbits)
Copy link
Member

Choose a reason for hiding this comment

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

allocbits should be a keyword argument

Copy link
Member Author

Choose a reason for hiding this comment

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

I feared that a keyword would slow things down... the only point of this feature is to improve efficiency by avoiding allocating unnecessarily one Limb (the default of mpz_init) and then re-allocating what is needed from within mpz_* functions. For the same reason, I think sizehint! would not work. Also this is really not meant to be a user API (where a BigInt is immutable), meant only for the wrapping layer of mpz, so the ugliness was kind of "on purpose". Would you accept a solution like BigInt(::Type{Bool}, nbits), or maybe using an ad-hoc type tag BigInt(::Type{SizeHint}, nbits) ? Otherwise, I will update to use a keyword argument.

Copy link
Member

Choose a reason for hiding this comment

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

If it's just going to be internal, we can use a name like BigInt_withsize and switch to a keyword arg later when they are fast.

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 i'll update using BigInt_withsize. Other methods in gmp.jl may benefit from this constructor.

@JeffBezanson
Copy link
Member

Instead of allocbits, could this be a method of sizehint!? Val is really ugly.

@rfourquet
Copy link
Member Author

So I finally changed Val{:allocbits} to _withsize (which I could change to BigInt_withsize...) but I'm not sure: besides the name, was that the suggested implementation?

@rfourquet rfourquet force-pushed the rand-bigrange-mergeversions branch 2 times, most recently from 52e3144 to 04d780f Compare May 22, 2016 15:13
@rfourquet
Copy link
Member Author

Is _withsize an OK name? Once the name is decided, I can squash the last commit.

base/gmp.jl Outdated
function BigInt(::_withsize, nbits)
z = new(Cint(0), Cint(0), C_NULL)
# WARNING: nbits == 0 is unsafe, some mpz_* functions expect an abs size >= 1
nbits > 0 && ccall((:__gmpz_init2,:libgmp), Void, (Ptr{BigInt}, Culong), &z, nbits)
Copy link
Contributor

Choose a reason for hiding this comment

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

should there be an error when nbits <= 0 instead of just doing nothing?

Copy link
Member Author

@rfourquet rfourquet May 23, 2016

Choose a reason for hiding this comment

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

I left this as an option for the programmer to manually initialize the BigIng object at a later stage. Note that as long as the object (equal to big(0)) is not used in a mutative GMP function, this should not be unsafe.

@tkelman
Copy link
Contributor

tkelman commented May 22, 2016

Isn't _withsize just a gmp-specific name for Val? I think Jeff was suggesting using sizehint! for this.

edit: whoops, hadn't read the collapsed conversation

edit2: So rereading it, I think Jeff's suggestion is actually to use a different function name for the _withsize signature.

@rfourquet
Copy link
Member Author

Whoops, sorry @tkelman I have missed your last comment. I don't understand how to use a different function name, as there has to be an inner constructor which allows to tune the allocation; otherwise, sizehint! will be fine (1 allocation would be wasted). I agree that _withsize is no more than a gmp-specific name for Val. I could also change the signature to BigInt(_withsize(n)).

@tkelman
Copy link
Contributor

tkelman commented May 27, 2016

Is there currently a meaning to calling BigInt with 3 arguments? Could use the default inner constructor as an unchecked shortcut, make the existing 0 arg method an outer constructor, then use different names for preallocated versions?

@rfourquet rfourquet force-pushed the rand-bigrange-mergeversions branch from 04d780f to 28286fb Compare May 29, 2016 06:52
@rfourquet
Copy link
Member Author

Ah I get it now, thanks. It's not my preference to introduce a new name for what is actually a constructor but I updated accordingly. The 3-argument constructor is left unchecked (in particular with no finalizer attached). Another option: using a dummy Bool value in a 2-argument inner constructor, eg BigInt(withsize::Bool, size::Int, ) where withsize is not used.

@rfourquet
Copy link
Member Author

Would it help pushing this forward if I entirely remove the BigInt_withsize business? I somehow need to control the allocated size, but I guess this could be accomplished by something like z = big(2)^bits_to_allocate.

@rfourquet rfourquet force-pushed the rand-bigrange-mergeversions branch from 28286fb to 47aee88 Compare June 15, 2016 14:00
@rfourquet
Copy link
Member Author

I rebased because of merge conflicts. I decided to remove the BigInt_withsize constructor, it is not essential here, and I instead ccall'ed to libgmp to allocate when needed. If I can defend the introduction of a BigInt constructor which controls allocation with performance numbers, it will be in another PR.
There was an apparently not related error on travis with the previous version, which I don't understand (test blas, "AssertionError: frame.inferred"), here is the link.

@rfourquet rfourquet added the randomness Random number generation and the Random stdlib label Jun 15, 2016
@rfourquet rfourquet force-pushed the rand-bigrange-mergeversions branch from 47aee88 to f8223cd Compare June 19, 2016 07:29
@rfourquet rfourquet force-pushed the rand-bigrange-mergeversions branch from f8223cd to 765febf Compare May 20, 2017 14:58
@rfourquet
Copy link
Member Author

Rebased. I would like to merge soon, if no-one objects...

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

Good to go?

@rfourquet rfourquet force-pushed the rand-bigrange-mergeversions branch from 765febf to 2ca7166 Compare May 26, 2017 14:00
@tkelman
Copy link
Contributor

tkelman commented May 26, 2017

you've tested this against older libgmp?

@tkelman
Copy link
Contributor

tkelman commented May 27, 2017

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

@rfourquet
Copy link
Member Author

I didn't think to test against older gmp versions, good idea, I'm running the whole tests locally now with gmp-5.1.3 (you must have seen I had rebased, I was about to merge!)

@tkelman
Copy link
Contributor

tkelman commented May 27, 2017

cc @nalimilan as well who I believe maintains some configurations of his copr against older libgmp, main user of the older branch code

@rfourquet
Copy link
Member Author

There is only one failure with gmp-5.1.3, on numbers, which seems unrelated: powermod(1, -1, big(1)) == 0 throws an integer division error (in this branch as well as on master).

@nanosoldier
Copy link
Collaborator

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

@ViralBShah
Copy link
Member

I think we can drop gmp-5 support, if it simplifies things.

@rfourquet
Copy link
Member Author

This PR doesn't change the compatibility with gmp-5, it bypasses the different APIs by working directly with the low-level representation. On the other hand, the error with powermod I mentioned above seems to imply that gmp-5 is not 100% supported.
So I will finally merge tomorrow if no objection.

rfourquet added 2 commits June 3, 2017 12:25
As a consequence, using dynamically a version of GMP which
does not match the compile time version is no longer an error
(this patch makes this a warming).
The code is shorter, but we break the MPZ API boundary; this also
allows to put allocating pointer_to_array out of the loop, and get
slightly better performances.
@rfourquet rfourquet force-pushed the rand-bigrange-mergeversions branch from 2ca7166 to 141a8f4 Compare June 3, 2017 10:25
@rfourquet rfourquet merged commit 063e8f1 into JuliaLang:master Jun 3, 2017
@rfourquet rfourquet deleted the rand-bigrange-mergeversions branch June 3, 2017 11:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bignums BigInt and BigFloat randomness Random number generation and the Random stdlib
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants