Skip to content

Call sincos instead of separate sin and cos of one angle - #127214

Merged
thevar1able merged 8 commits into
masterfrom
sincos-single-call
Oct 22, 2026
Merged

thevar1able merged 8 commits into
masterfrom
sincos-single-call

Conversation

@thevar1able

@thevar1able thevar1able commented Oct 21, 2026 •

Copy link
Copy Markdown
Member

Related: #109239

h3_functions #4 (h3CellAreaM2) was 20% slower on aarch64 in the musl build: in the glibc build LLVM merges sin(x) and cos(x) into one sincos call, which shares the argument reduction, but it assumes sincos only in glibc, Fuchsia and Android, so the musl build made both calls. An explicit sincos call does not help on its own: Clang turns it into the llvm.sincos intrinsic, and for a musl target LLVM lowers that to sin and cos again.

  • Compile with -fno-builtin-sincos under musl, so that sincos stays a call.
  • Link llvm-libc's correctly rounded sincos, which gives the same bits as its sin and cos.
  • Bump contrib/h3 so that its _sincos helper really calls sincos (its __builtin_sincos is split back into sin and cos for musl targets) and use it in cagnoli, the cell area functions: merged into ClickHouse/v4.5.0 in Make _sincos reach libm's sincos on every Linux libc, and use it in cagnoli h3#14.
  • Add sinCos and use it in geoToUTM, UTMToGeo and colorOKLCHToSRGB.

The results of these functions over 200000 inputs are identical before and after.

Perf report where it was found: https://s3.amazonaws.com/clickhouse-test-reports/praktika.html?PR=109239&sha=a685010407d544ee0b02294d34118bd48f46ff84&name_0=PR&name_1=Performance%20Comparison%20%28arm_release%2C%20master_head%2C%201%2F6%29

Changelog category (leave one):

  • Performance Improvement

Changelog entry (a user-readable short description of the changes that goes into CHANGELOG.md):

h3CellAreaM2, h3CellAreaRads2, geoToUTM, UTMToGeo and colorOKLCHToSRGB compute the sine and cosine of one angle with a single sincos call in every build, with identical results.

🤖 Generated with Claude Code


Workflow [PR]
Sync PR [sync-upstream/pr/127214]

Version info

  • Merged into: 26.11.1.590-master (included in 26.11 and later)

thevar1able and others added 3 commits October 21, 2026 17:15
`h3_functions` #4 (`h3CellAreaM2`) was 20% slower on aarch64: in the glibc build LLVM merges `sin(x)`
and `cos(x)` into one `sincos` call, which shares the argument reduction, but it assumes `sincos` only
in glibc, Fuchsia and Android, so the musl build made both calls. An explicit `sincos` call does not
help on its own: Clang turns it into the `llvm.sincos` intrinsic, and for a musl target LLVM lowers that
to `sin` and `cos` again.

- Compile with `-fno-builtin-sincos` under musl, so that `sincos` stays a call.
- Link llvm-libc's correctly rounded `sincos`, which gives the same bits as its `sin` and `cos`.
- Bump `contrib/h3` to call `sincos` in `cagnoli` (the cell area functions).
- Add `sinCos` and use it in `geoToUTM`, `UTMToGeo` and `colorOKLCHToSRGB`.

The results of these functions over 200000 inputs are identical before and after.

https://s3.amazonaws.com/clickhouse-test-reports/praktika.html?PR=109239&sha=a685010407d544ee0b02294d34118bd48f46ff84&name_0=PR&name_1=Performance%20Comparison%20%28arm_release%2C%20master_head%2C%201%2F6%29
#109239

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit 1ffa828)
…ables`

The output parameters of `sinCos` left the callers' variables uninitialized, which `clang-tidy` rejects.

https://s3.amazonaws.com/clickhouse-test-reports/praktika.html?PR=109239&sha=1ffa828af25b70add84fe7bb2f88fe5765159e60&name_0=PR&name_1=Build%20%28arm_tidy%2C%202%2F4%29
#109239

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit 16f3316)
…cond one

The fork's `_sincos` used `__builtin_sincos`, which LLVM splits back into
`sin` and `cos` for musl targets, so it is now declared with the `sincos`
assembler label and `cagnoli` uses it as well. Branch `sincos-on-musl` of
ClickHouse/h3, on top of `ClickHouse/v4.5.0`.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@clickhouse-gh

clickhouse-gh Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Workflow [PR], commit [0d02585]

Summary: ✅


AI Review

Summary

The PR preserves explicit paired sine/cosine calls under musl, exports LLVM-libc's sincos, and uses it in H3, UTM, and color conversions. ⚠️ Request changes: the performance benefit remains unproven, while two completed runs show an ARM slowdown in the motivating query. Both prior findings remain applicable; there are no new inline findings.

Findings

⚠️ Majors

  • contrib/libllvmlibc-cmake/CMakeLists.txt:57: Replacing glibc's paired implementation needs performance evidence. The added source also exports sincos in glibc builds; the release link's --whole-archive makes it replace existing paired calls throughout the executable. For h3_functions query 4 (h3CellAreaM2), the 2026-10-22 ARM run measures 143.7 → 152.9 ms (+6.3%), following 143.8 → 153.1 ms (+6.4%) in the 2026-10-21 run. These are below CI's 15% reporting floor, but repeat outside the recent ARM baseline range (p05–p95: 143.6–144.1 ms). AMD64 changes from +5.3% in the first run to −0.4% in the second, so the earlier AMD64 slowdown is not consistent. Provide focused musl/glibc measurements and preserve glibc's implementation if the replacement is slower. Existing thread.

💡 Nits

  • contrib/libllvmlibc-cmake/CMakeLists.txt:57, PR changelog: The unconditional “with identical results” claim is too broad. Switching glibc's sincos to LLVM-libc changes final-bit rounding for some inputs, as documented in the existing thread. The current export still makes that substitution. The helper also explicitly uses separate calls outside Linux/FreeBSD, so it does not guarantee one sincos call in every build.
PR Metadata

Performance Improvement matches the intended change and requires an entry. Replace the entry's overbroad implementation and identity claims with:

Use paired sine/cosine evaluation in h3CellAreaM2, h3CellAreaRads2, geoToUTM, UTMToGeo, and colorOKLCHToSRGB, including explicit paired calls in musl builds. Results in glibc builds can differ in the last bit.

Tests
  • ⚠️ Supply a focused before/after benchmark for the intended aarch64 musl build and the glibc build, covering the motivating H3 query and the other conversions whose performance is claimed. The completed release comparisons use glibc. They cover 7163eeccdc5b; current head is 0d02585587b9. The H3 contents and LLVM-libc math sources are unchanged between those revisions, but there is no completed current-head or aarch64 musl performance comparison in the available evidence.
Final Verdict

⚠️ Request changes. Demonstrate the musl benefit, resolve the repeated glibc ARM slowdown or scope the replacement to avoid it, and narrow the changelog claims.

@clickhouse-gh clickhouse-gh Bot added pr-performance Pull request with some performance improvements submodule changed At least one submodule changed in this PR. labels Oct 21, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
"${LIBLLVMLIBC_SOURCE_DIR}/src/math/generic/scalbn.cpp"
"${LIBLLVMLIBC_SOURCE_DIR}/src/math/generic/scalbnl.cpp"
"${LIBLLVMLIBC_SOURCE_DIR}/src/math/generic/sin.cpp"
"${LIBLLVMLIBC_SOURCE_DIR}/src/math/generic/sincos.cpp"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

💡 Narrow the changelog's unconditional “with identical results” claim. Adding this source exports LLVM-libc's sincos in glibc builds too, replacing the glibc implementation previously used by optimizer-generated paired calls. In a standalone aarch64 probe using the pinned sources and repository math defines, 567 of 200,000 sampled pairs differed from glibc. For example, at x = 0x1.fb9664c826b3dp+1, glibc returns cosine -0x1.5bd25a6ee0c56p-1, whereas LLVM-libc returns -0x1.5bd25a6ee0c57p-1.

The comparison against LLVM-libc's separate sin and cos did match. Please limit the identity statement to that comparison, or remove it and mention that glibc builds can have final-bit rounding changes. This is a documentation nit, not a correctness blocker.

@clickhouse-gh clickhouse-gh Bot added the comp-regular-function Regular scalar functions: string processing, data conversion, arithmetic, math, comparison, condi... label Oct 21, 2026
@evillique evillique self-assigned this Oct 21, 2026
@thevar1able thevar1able assigned Algunenano and unassigned evillique Oct 21, 2026
"${LIBLLVMLIBC_SOURCE_DIR}/src/math/generic/scalbn.cpp"
"${LIBLLVMLIBC_SOURCE_DIR}/src/math/generic/scalbnl.cpp"
"${LIBLLVMLIBC_SOURCE_DIR}/src/math/generic/sin.cpp"
"${LIBLLVMLIBC_SOURCE_DIR}/src/math/generic/sincos.cpp"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Verify the benefit before replacing glibc's sincos globally.

This source is linked for glibc builds as well as musl, and the normal release link uses --whole-archive, so it replaces the glibc sincos already used by compiler-generated paired calls throughout the executable. Sharing argument reduction does not establish a speedup over that existing paired implementation.

The completed performance run measures h3_functions query 4 at 143.8 → 153.1 ms on ARM (+6.4%) and 140.9 → 148.5 ms on AMD64 (+5.3%). Both changes are below CI's 15% reporting floor, and one run does not prove a regression, but neither demonstrates this PR's performance benefit. That run uses the same LLVM revision and H3 source contents as the current head.

Please provide a focused before/after comparison for the intended musl build and the glibc build. If replacing glibc's implementation is slower, scope the LLVM-libc export to musl or otherwise preserve the faster implementation. The linked report from PR #109239 identifies the original problem; it does not measure this patch's benefit.

@clickhouse-gh

clickhouse-gh Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Build profile diff (arm_release)

Comparing 0d0258558 with master e0ae5a4bb (stripped binary size, per-symbol sizes and ThinLTO time; object sizes against the warmup build of d2ac903cf; compile times per translation unit against the most recent warmup build that recompiled it).

✅ No significant changes.

Binary sizes

programs/clickhouse-stripped: smaller than the master baseline by the known offset between the two builds, so the difference is not shown. A delta that differs from the offset by more than 50% of it is shown, in either direction.

The official master build is compiled with -g and a pull request build is not, and XRay counts debug instructions towards its instrumentation threshold, so master instruments thousands of functions more and its binary is ~0.4% larger no matter what the pull request does.

Object file sizes

15 object files changed (+34.22 KiB total), 1 added.

Object file Master PR Δ

719 more object files are built by the master warmup baseline only (it builds every object-file target, a pull request build only clickhouse-bundle) and not compared.

Compile time of recompiled translation units

25 translation units recompiled, 15 s compile time in total, 8 of them have a recent master baseline.

Job report

@thevar1able
thevar1able enabled auto-merge October 22, 2026 13:43
@thevar1able
thevar1able added this pull request to the merge queue Oct 22, 2026
Merged via the queue into master with commit 6b831ff Oct 22, 2026
353 of 355 checks passed
@thevar1able
thevar1able deleted the sincos-single-call branch October 22, 2026 22:45
@robot-clickhouse-ci-1 robot-clickhouse-ci-1 added the pr-synced-to-cloud The PR is synced to the cloud repo label Oct 22, 2026
thevar1able added a commit that referenced this pull request Oct 22, 2026
Take master's versions of `CompressionCodecT64.cpp` and `contrib/h3`: both
are the reviewed final forms of the changes this branch carried (#127214
and the portable `T64` matrix fill).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp-regular-function Regular scalar functions: string processing, data conversion, arithmetic, math, comparison, condi... pr-performance Pull request with some performance improvements pr-synced-to-cloud The PR is synced to the cloud repo submodule changed At least one submodule changed in this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants