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

Re-implementation of Tang (1990) log procedures in pure float32 #236

Closed
wants to merge 5 commits into from

Conversation

sotlampr
Copy link
Contributor

@sotlampr sotlampr commented Aug 12, 2023

Base.Math.log1p calculation relies on two procedures , log_proc1 and log_proc2 from the literature Tang (1990). The current implementation upscales to Float64 internally and as such is incompatible with Metal.

This PR attempts to convert the two procedures to pure-float32.

See also relevant discussion #234

jp = unsafe_trunc(Int,128.0f0*F)-127

## Steps 1 and 2
hi = t_log_Float32[jp]
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Julia Base uses Float64 tables

q = u*v*0.08333351f0

## Step 4
logb(base)*(l + (u + q))
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Similarly, logb in base returns a double

0.012512346f0)

## Step 3
@inline function truncate(x)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

From Tang (1990):

(1) Define M := 12 for single precision, and define M := 24 for double precision.
(2) u1 := u rounded (or truncated) to M significant bits.
(3) fi := f rounded (or truncated) to M significant bits.

I'm not sure if this is what is meant

reinterpret(Float32,
reinterpret(Int32, 0.012512346f0) & 0b11111111111100000000000000000000)
end
u₁ = truncate(u)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Non-upcasting alternative procedure from Tang (1990)

@maleadt
Copy link
Member

maleadt commented Aug 12, 2023

cc @oscardssmith

@oscardssmith
Copy link

What's the error like for these implementations?

@sotlampr
Copy link
Contributor Author

sotlampr commented Aug 13, 2023

EDIT: CPU, running on metal has too high error
This log1p(using the modified procedures) compared with Base.Math.log1p (Float32) (ULP):

max 4.0 at x = -0.099609345
mean 0.12487844518189703

This log_proc2 compared with Base.Math.log_proc2 (Float32) (ULP):

log_proc2{Float32}, base=2
max 2.0 at x = 0.043909933
mean 0.1784229523275927

log_proc2{Float32}, base=ℯ
max 1.0 at x = 0.064494334
mean 0.004462545515167737

log_proc2{Float32}, base=10
max 2.0 at x = 0.03663287
mean 0.287801184326243

@sotlampr
Copy link
Contributor Author

sotlampr commented Aug 13, 2023

NOTE Running on Metal has very high error - something is not right

@oscardssmith
Copy link

Can you compare against Base.Math.log1p (Float64)? your current comparison isn't great since Base.Math.log1p (Float32) also has rounding error.

@sotlampr
Copy link
Contributor Author

I assumed that we're interested in the difference between the upcasting float32 vs. the pure float32 implementation.

This log1p{Float32} v. Base.Math.log1p{Float64}

max 4.441346645355225 at x = -0.11138753
mean 0.17755624519091973

And for reference, Base.Math.log1p{Float32} v. Base.Math.log1p{Float64}

max 0.563554048538208 at x = 0.08200329
mean 0.11855523097385935

@sotlampr sotlampr marked this pull request as draft August 14, 2023 08:42
@sotlampr
Copy link
Contributor Author

@oscardssmith do you think the error is acceptable? And most critically, running on Metal does not work - the error is way too high. Can you see any possible culprit in the code?

@oscardssmith
Copy link

the error is probably acceptable, but it is higher than I was expecting. I don't know why it's giving wrong answers on gpu. possibly the truncate is misbehaving?

@sotlampr
Copy link
Contributor Author

The problems seems to be accessing t_log_Float32 - it returns 0

@oscardssmith
Copy link

now that you mention it, a table based method is probably not the best idea for a gpu.

@oscardssmith
Copy link

https://github.com/JuliaMath/openlibm/blob/master/src/s_log1pf.c might be a better approach.

@sotlampr
Copy link
Contributor Author

Replaced by #239

@sotlampr sotlampr closed this Aug 15, 2023
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.

3 participants