-
Notifications
You must be signed in to change notification settings - Fork 9
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
Add support for Float32 and Float16 #31
Conversation
Great idea, thanks! However, there's definitely a huge performance difference between using function cos1(x::Float32, r::RoundingMode)
return Float32(CRlibm.cos(Float64(x), r), r)
end
function cos2(x::Float32, r::RoundingMode)
y = setprecision(BigFloat, 24) do
setrounding(BigFloat, r) do
cos(BigFloat(x))
end
end
return Float32(y, r)
end
end
using BenchmarkTools
julia> @btime cos1($x, RoundDown)
20.465 ns (0 allocations: 0 bytes)
0.9950041f0
julia> @btime cos2($x, RoundDown)
648.976 ns (7 allocations: 176 bytes)
0.9950041f0 |
Ok, thanks for checking that. I found that a little odd, too. I'll change the code accordingly (i.e. only use standard FP types when possible). Any reason you use |
src/CRlibm.jl
Outdated
|
||
# Specialise for Float32 and Float16 to get the other IEEE FP types | ||
# working transparently as well | ||
@eval $f(x::Float16, r::RoundingMode) = Float16((Base.$f)(Float32(x)), r) |
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.
Maybe you should convert straight to Float64
here?
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 changed it for Float64
, but I doubt it really matters ... but I'm also not really an expert in FP arithmetic either. Do you have any reason why you think Float64
could be better?
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.
Because if you use Float32
, it will just convert it to Float64
in the following line ;) Although the compiler will probably compile that away, so feel free to leave it.
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 don't think this is what happens here (unless I'm wrong). At least I try to avoid that by calling e.g. Base.cos
and not just cos
. I quickly verified using a print-statement: So there is no dispatch to CRlibm.cos
in line 136 or 137.
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.
Ah, there's a subtlety here: CRlibm
doesn't import cos
from Base
, so "cos
" within the module refers to the internal cos
.
We may want to write it explicitly as CRlibm.cos
to make this clear.
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.
Yes, sure, but Base.cos
should not refer to CRlibm.cos
, right? That would be pretty counter-intuitive. So the @eval
in line 136 should generate calls to Base.cos
only and not back to CRlibm.cos
, no?
To clarify: If I am not mistaken, this means that a call to CRlibm.cos(Float16(1.0))
will, in the current version of the code, widen to Float64
and then dispatch to Base.cos(::Float64)
and never get passed on to the CRlib
C code.
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.
There is no use of Base.cos
within the package.
Any use of cos
within the CRlibm
package refers to the functions defined inside the package. Base.cos
never comes into the picture at all.
However, in IntervalArithmetic.jl
we define a new method Base.cos(x, r)
, with a RoundingMode
r
, to use CRlibm.cos
by default. (This is, strictly speaking, type piracy.)
You should be able to check this using the debugger in Juno or using Cthulhu.jl
to check that the correct methods are being called.
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.
Thanks for pointing out Cthulhu.jl
. That's quite a neat package for the @code_warntype
mess.
Ah I see, I think we might be misunderstanding each other here ... I am talking about the state of CRlibm after this PR is merged and this PR does introduce an explicit call to functions such as Base.cos
, Base.sin
and so on. If this is not what you want, please let me know, I'm happy to change this.
For example, one line where this happens is line 137. In the debugger a call to CRlibm.cos
with a Float32
type dispatches to Base.cos
(with the data widened to Float64
):
julia> using CRlibm; using Debugger; @breakpoint Base.cos(1.0)
cos(x::T) where T<:Union{Float32, Float64} in Base.Math at special/trig.jl:100
julia> @run CRlibm.cos(Float32(1.))
Hit breakpoint:
[ Info: tracking Base
In cos(x) at special/trig.jl:100
99 function cos(x::T) where T<:Union{Float32, Float64}
>100 absx = abs(x)
101 if absx < T(pi)/4
102 if absx < sqrt(eps(T)/T(2.0))
103 return T(1.0)
104 end
About to run: Core.NewvarNode(:(_4))
1|debug> bt
[1] cos(x) at special/trig.jl:100
| x::Float64 = 1.0
| T::DataType = Float64
[2] cos(x, r) at CRlibm.jl/src/CRlibm.jl:137
| x::Float32 = 1.0f0
| r::RoundingMode{:Nearest} = RoundingMode{:Nearest}()
[3] cos(x) at CRlibm.jl/src/CRlibm.jl:132
| x::Float32 = 1.0f0
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.
OK I had not noticed that change, sorry.
But Base.cos
does not do correct rounding, so can't be used here. You need to replace it with a rounded CRlibm.cos
call, as I did in my benchmark code.
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.
All right ... did that. All Base.cos
is gone again.
|
We/you should probably update the Travis and Appveyor files to test on Julia 1.0, 1.3 and nightly, and allow failures on nightly. |
Sorry about the confusion. I talked about |
At least part of the test failures seems to be due to the fact that |
Thanks, LGTM! Is this ready to merge? |
Yes, sorry. It is from my point of view 😄. |
Many thanks for this contribution! |
This PR adds transparent support for Float32 and Float16 datatypes. Closes #32.