-
Notifications
You must be signed in to change notification settings - Fork 1k
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
Faster and cached square root #12191
Conversation
math/math_helper.go
Outdated
@@ -43,6 +50,25 @@ var squareRootTable = map[uint64]uint64{ | |||
4194304: 2048, | |||
} | |||
|
|||
// SquareRootEffectiveBalance implements Newton's algorithm to compute the square root of | |||
// the given uint64 starting from the last cached value | |||
func SquareRootEffectiveBalance(balance uint64) uint64 { |
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.
Qustion on general usages for this function. Is this only intended for EffectiveBalance
, if yes then we should move the function to a better location not general math helper
If it's not only intended for EffectiveBalance
such that it could be applied to other usages, we can rename this function to SquareRootCached
or something else
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.
Depending on the size of the cache it can be used for everything, I could move the cache to a map.
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.
Looking at this function again, given it's just a single value, it might be best to move (hide) it to core
pkg because we don't want to share it among others. Imagine Alice joins the team tomorrow and start using SquareRootEffectiveBalance
for something less relevant
Tested that the function returns the same value as our previous method for balances between 700K validators and 5 million validators. |
This PR adds a different method to compute the integer square root of a number. It first uses a simple mutex and a cache for the last computation done. If there is a cache miss, then it uses simple Newton approximation to find the new square root.
Rationale:
Square roots of total balances are computed when computing
In all cases we pass the total effective balance of validators that were active in the current epoch. This number stays constant throughout the epoch and changes slowly, by multiples of 10**9 Gwei, on epoch transitions.
This makes us believe that a single value cache is already good enough to avoid this computation on block processing, as the effective balance will not change intra-epoch. And In case of a cache miss, we can start a Newton approximation with the latest cached value that is guaranteed to be close to the actual value.
Possible improvemnents:
Some Benchmarks
Below there are some benchmarks on a AMD Ryzen 5 3600. On computing raw square roots for over 52 bits our method is about x2.3 faster, that is comparable with Golang's square root computation for numbers under 52 bits.