Switch to log2 with table lookup and interpolation#31
Open
yushiuan9499 wants to merge 1 commit into
Open
Conversation
The original Taylor expansion-based fixed_log() is replaced with
fixed_log2(), which uses the identity log2(x * 2^n) = log2(x) + n. This
reduces the input range for log(x), allowing the use of a lookup table
and interpolation for efficient calculation.
To leverage binary properties—such as obtaining the integer part of
log2(x) via __builtin_clz()—the base is switched from Euler's number to
2. The change-of-base formula is then applied in uct_score() to obtain
the natural logarithm result.
Besides improving efficiency, the maximum error is significantly reduced
from >1 to <2^{-16}.
Change-Id: I043748fe1964bcdae77d840f426ef5b6825ad58a
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Previously,
fixed_log()was based on Taylor expansion, which is less accurate for inputs much larger than 1, as shown in the chart below. In addition, it uses a loop to calculate the result, which is inefficient.This PR replaces$\log_2(x * 2^n) = \log_2(x) + n$ . This reduces the input range for $\log_2(x)$ , allowing the use of a 4 KiB lookup table and interpolation for efficient and accurate calculation.
fixed_log()withfixed_log2(), which uses the identityThe base is changed to 2 because this allows the use of$\log_2(x)$ . The change-of-base formula is then applied in
__builtin_clz()to efficiently calculate the integer part ofuct_score()to obtain the natural logarithm result.Accuracy
The chart below is the curve of
fixed_log2(x)and glibclog2(x). It shows thatfixed_log2(x)is reasonably accurate.Thanks to the efficiency of$2^{-16}$ . The code
fixed_log2(), I was able to test all possible inputs offixed_log2(x)and compared it with glibc'slog2(x). The maximum absolute error isPerformance
I performed two benchmarks.$2^{15} - 1$ using both
The first benchmark tests integers from 1 to
fixed_log()andfixed_log2(), and measures their execution time.Without compiler optimizations:
With
-O2optimization:fixed_log2()is 20x~30x faster thanfixed_log().The second benchmark uses
ftraceto measure how many timesmcts()is called and how much total time is spent inmcts()over one minute.mcts()callsmcts()(ms)After the change,
mcts()is ~2x faster.Summary by cubic
Replace the Taylor-based fixed-point log with a fast
log2using a 4 KiB lookup table and interpolation. Accuracy improves to <2^-16 andmcts()runs about 2x faster (log evaluation is ~20–30x faster).fixed_log()withfixed_log2()usinglog2(x*2^n) = log2(x) + n; integer part via__builtin_clz.LOG2_TABLE_SIZE=10) with linear interpolation; initialized inmcts_init().uct_score()via change-of-base; adjustedEXPLORATION_FACTORby multiplying withsqrt(ln 2)to match the previous behavior.Written for commit 0000241. Summary will update on new commits.