Skip to content

Switch to log2 with table lookup and interpolation#31

Open
yushiuan9499 wants to merge 1 commit into
sysprog21:mainfrom
yushiuan9499:precise_log
Open

Switch to log2 with table lookup and interpolation#31
yushiuan9499 wants to merge 1 commit into
sysprog21:mainfrom
yushiuan9499:precise_log

Conversation

@yushiuan9499
Copy link
Copy Markdown

@yushiuan9499 yushiuan9499 commented May 11, 2026

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.

fixed_log

This PR replaces fixed_log() with fixed_log2(), which uses the identity $\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.

The base is changed to 2 because this allows the use of __builtin_clz() to efficiently calculate the integer part of $\log_2(x)$. The change-of-base formula is then applied in uct_score() to obtain the natural logarithm result.

Accuracy

The chart below is the curve of fixed_log2(x) and glibc log2(x). It shows that fixed_log2(x) is reasonably accurate.

fixed_log2

Thanks to the efficiency of fixed_log2(), I was able to test all possible inputs of fixed_log2(x) and compared it with glibc's log2(x). The maximum absolute error is $2^{-16}$. The code

Performance

I performed two benchmarks.
The first benchmark tests integers from 1 to $2^{15} - 1$ using both fixed_log() and fixed_log2(), and measures their execution time.
Without compiler optimizations:

fixed_log: 0.004379 sec
fixed_log2: 0.000147 sec

With -O2 optimization:

fixed_log: 0.002201 sec
fixed_log2: 0.000094 sec

fixed_log2() is 20x~30x faster than fixed_log().

The second benchmark uses ftrace to measure how many times mcts() is called and how much total time is spent in mcts() over one minute.

mcts() calls Time spent on mcts() (ms) Time per call (ms)
Before 139 5.28e4 379.86
After 281 5.38e4 191.46

After the change, mcts() is ~2x faster.


Summary by cubic

Replace the Taylor-based fixed-point log with a fast log2 using a 4 KiB lookup table and interpolation. Accuracy improves to <2^-16 and mcts() runs about 2x faster (log evaluation is ~20–30x faster).

  • Refactors
    • Replaced fixed_log() with fixed_log2() using log2(x*2^n) = log2(x) + n; integer part via __builtin_clz.
    • Added 1024-entry lookup table (LOG2_TABLE_SIZE=10) with linear interpolation; initialized in mcts_init().
    • Kept natural log semantics in uct_score() via change-of-base; adjusted EXPLORATION_FACTOR by multiplying with sqrt(ln 2) to match the previous behavior.

Written for commit 0000241. Summary will update on new commits.

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
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

No issues found across 1 file

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.

1 participant