-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
Better sizehint for primes #16333
Better sizehint for primes #16333
Conversation
@@ -2253,6 +2253,9 @@ for T in [Int,BigInt], n = [1:1000;1000000] | |||
@test s[k] == primesmask(k, k)[1] | |||
end | |||
end | |||
let i = rand(1:2^40) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
2^40
overflows on 32 bit
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, yes, and I swear I did not just try to make a point here - #5573
7f07a50
to
85904a1
Compare
@@ -83,7 +83,7 @@ function primes(lo::Int, hi::Int) | |||
lo ≤ 3 ≤ hi && push!(list, 3) | |||
lo ≤ 5 ≤ hi && push!(list, 5) | |||
hi < 7 && return list | |||
sizehint!(list, floor(Int, hi / log(hi))) | |||
sizehint!(list, floor(Int, max(hi,0) / log(max(hi,2)) - max(lo,0) / log(max(lo,2)))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you don't need max
here except for max(lo,0)
and max(lo,2)
as hi
will be greater or equal than 7 at this point.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess we can clean this up a bit by writing lo = max(2, lo)
after the lo ≤ hi
check. And then just write hi / log(hi) - lo / log(lo)
for the sizehint
8a5d887
to
4ec97a0
Compare
Thanks for the feedback. Not a big surprise, but for example now the batched infinite prime iterator julia-before> @time first(drop(primeiter, 10^9)) 93.870623 seconds (2.00 G allocations: 81.113 TB, 10.60% gc time) 22801763513 julia-after> @time first(drop(primeiter, 10^9)) 88.758689 seconds (2.00 G allocations: 87.218 GB, 3.50% gc time) 22801763513 For comparison, julia> @time primes(22801763513)[end]; 114.720337 seconds (10 allocations: 13.415 GB, 0.15% gc time) takes a bit longer. |
We could use better bound than |
It's only slightly too big (with relative error of 5% for n=10^9 for example), which is good. That is better than choosing something too small but much closer (Li(n) for example). |
A much better bound for |
But that will only work for |
Ok, as we have
then
so it would probably be better to have (though it would use more memory than you have now):
I guess is just a matter of experimenting a bit. |
Do we have |
See equation 10 from the reference a pasted above |
|
Just beware of |
I think we can take that one. That should work fine in practice, as sizehint!() rounds to the next multiple of a resizing factor and does not need much precision, but only good overall estimates which give enough space to accommodate the array. |
LGTM. |
@ararslan Do you want to have a look? I think this is good to go. |
@mschauer Funny you should ask me, I'm just some guy. 😜 Looks good to me (and it appears the AppVeyor failure was just a timeout). 👍 |
Want to try closing and reopening the PR to see if we can get AppVeyor to cooperate? |
Thanks to the unknown helping hand triggering AppVeyor. |
Better sizehint for
primes(lo,hi)
.Before it failed for 1 << lo < hi as the sizehint! actually consumed
hi / log(hi)
memory independent oflo
, but the needed size is better approximated byhi / log(hi) - lo/log(lo)
. Add a test which testprimes
and friends on short intervals with1 << lo
.