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

fixed floating point error #713

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

dnabanita7
Copy link

related to issue #712

@nalimilan
Copy link
Member

Thanks for the PR! However, I'm not sure the docs should correspond exactly to the implementation. The docstring gives the mathematical formula, and the implementation is slightly different for performance reasons. Floating point approximations are generally not considered as significant. As was noted on Discourse, even 3/10 == 3*0.1 doesn't hold in floating point. As long as isapprox holds, everything is fine.

@dnabanita7
Copy link
Author

Alright! Should I just mention floating-point precision or anything in the docstrings? Or should I close the PR?

@andreasnoack
Copy link
Member

I think the existing version is fine. Separately from that, I also think this should be implemented with division instead of multiplication with the inverse.

@nalimilan
Copy link
Member

Separately from that, I also think this should be implemented with division instead of multiplication with the inverse.

I also wondered whether using the inverse was really a good idea. I imagine it can only be faster if the range of levels is very wide compared with the number of values, but even then it's not obvious that it would make a big difference.

@dnabanita7 Would you feel like checking whether using / for the implementation rather than inv would be acceptable for performance?

@dnabanita7
Copy link
Author

I think it is not making much difference with shorter collections.

julia> @btime counts(x1, s1) .* inv(length(x1))
  546.541 ns (5 allocations: 368 bytes)
7-element Vector{Float64}:
 0.1
 0.2
 0.1
 0.1
 0.30000000000000004
 0.0
 0.2

julia> @btime counts(x1, s1) / length(x1)
  133.574 ns (2 allocations: 288 bytes)
7-element Vector{Float64}:
 0.1
 0.2
 0.1
 0.1
 0.3
 0.0
 0.2

It gives better performance with larger collections.

julia> @btime counts(x1, s1) / length(x1)
25.491 s (5 allocations: 7.45 GiB)
500000000-element Vector{Float64}:

julia> @btime counts(x1, s1) .* inv(length(x1))
  28.704 s (8 allocations: 7.45 GiB)
500000000-element Vector{Float64}:

@nalimilan
Copy link
Member

What are x1 and s1 in these cases? I couldn't find cases where performance differs between inv and /.

@dnabanita7
Copy link
Author

dnabanita7 commented Sep 3, 2021

So, for the first case, x1, s1 are 7 element vector as in the output and for the second case x1, s1 is a random generated 5 * 10^8 element vector. As you can see in the second case, inv takes up more number of memory allocations as well as more time around 3 seconds than /.

@nalimilan
Copy link
Member

Hmm, I still don't get it. In general, posting code is more explicit.

Anyway, inv doesn't seem faster, so let's switch to /. Would you update the PR?

(BTW, be careful when looking at the number of allocations with @btime: it's safer to wrap the code in a function, in particular when it uses broadcasting. When doing that I see 4 allocations for both.)

@nalimilan
Copy link
Member

I meant that we should switch the implementation, not the docs.

@dnabanita7
Copy link
Author

oh sure, right!

@dnabanita7
Copy link
Author

cc @nalimilan

Copy link
Member

@nalimilan nalimilan left a comment

Choose a reason for hiding this comment

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

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants