Skip to content

Efficiency: use multiplication over std::pow for squaring (#3373) - #3375

Merged
WardBrian merged 3 commits into
stan-dev:developfrom
Purna-Chandra-4706:fix-issue-3373-square
Aug 28, 2026
Merged

Efficiency: use multiplication over std::pow for squaring (#3373)#3375
WardBrian merged 3 commits into
stan-dev:developfrom
Purna-Chandra-4706:fix-issue-3373-square

Conversation

@Purna-Chandra-4706

@Purna-Chandra-4706 Purna-Chandra-4706 commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Replaced std::pow(x, 2) with x * x after casting to double, preserving the prior rounding and overflow behavior. (Verified via grep that there are no other instances in the source code). Fixes #3373.

@WardBrian

Copy link
Copy Markdown
Member

Verified via grep that there are no other instances in the source code

It's a bit hard to spot with grep, but there is one more file that has this pattern:

return make_callback_vari(std::pow(a.val() - b.val(), 2),

return make_callback_vari(std::pow(a.val() - b, 2),

While these are in our autodiff systems, they're both only concerned with double values, so the same kind of patch can be applied

@WardBrian

Copy link
Copy Markdown
Member

And thank you for your patch!

@Purna-Chandra-4706

Copy link
Copy Markdown
Contributor Author

Thank you for pointing that out. It looks like my initial search missed it. I will take another look through the codebase for any remaining files with this pattern and push the updates shortly.

@Purna-Chandra-4706
Purna-Chandra-4706 marked this pull request as ready for review August 25, 2026 18:13
@stan-buildbot

Copy link
Copy Markdown
Contributor

Name Old Result New Result Ratio Performance change( 1 - new / old )
gp_regr/gp_regr.stan 0.1 0.1 0.98 -2.49% slower
gp_regr/gen_gp_data.stan 0.02 0.02 0.97 -2.64% slower
arK/arK.stan 1.55 1.63 0.95 -5.07% slower
eight_schools/eight_schools.stan 0.06 0.06 0.99 -1.19% slower
low_dim_gauss_mix_collapse/low_dim_gauss_mix_collapse.stan 8.62 8.65 1.0 -0.37% slower
pkpd/one_comp_mm_elim_abs.stan 19.79 19.69 1.01 0.52% faster
pkpd/sim_one_comp_mm_elim_abs.stan 0.26 0.25 1.04 4.15% faster
sir/sir.stan 70.96 70.27 1.01 0.98% faster
gp_pois_regr/gp_pois_regr.stan 2.38 2.38 1.0 0.2% faster
low_dim_gauss_mix/low_dim_gauss_mix.stan 2.79 2.81 0.99 -0.6% slower
irt_2pl/irt_2pl.stan 5.18 5.14 1.01 0.64% faster
arma/arma.stan 0.31 0.3 1.04 3.44% faster
garch/garch.stan 0.47 0.46 1.03 2.83% faster
low_dim_corr_gauss/low_dim_corr_gauss.stan 0.01 0.01 0.97 -3.04% slower
performance.compilation 271.74 279.88 0.97 -2.99% slower
Mean result: 0.9968879628536274

Jenkins Console Log
Blue Ocean
Commit hash: dbdc44b92c66574742629bf404057b3c7ba6f954


Machine information No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 20.04.3 LTS Release: 20.04 Codename: focal

CPU:
Architecture: x86_64
CPU op-mode(s): 32-bit, 64-bit
Byte Order: Little Endian
Address sizes: 46 bits physical, 48 bits virtual
CPU(s): 80
On-line CPU(s) list: 0-79
Thread(s) per core: 2
Core(s) per socket: 20
Socket(s): 2
NUMA node(s): 2
Vendor ID: GenuineIntel
CPU family: 6
Model: 85
Model name: Intel(R) Xeon(R) Gold 6148 CPU @ 2.40GHz
Stepping: 4
CPU MHz: 3371.532
CPU max MHz: 3700.0000
CPU min MHz: 1000.0000
BogoMIPS: 4800.00
Virtualization: VT-x
L1d cache: 1.3 MiB
L1i cache: 1.3 MiB
L2 cache: 40 MiB
L3 cache: 55 MiB
NUMA node0 CPU(s): 0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62,64,66,68,70,72,74,76,78
NUMA node1 CPU(s): 1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31,33,35,37,39,41,43,45,47,49,51,53,55,57,59,61,63,65,67,69,71,73,75,77,79
Vulnerability Gather data sampling: Mitigation; Microcode
Vulnerability Itlb multihit: KVM: Mitigation: Split huge pages
Vulnerability L1tf: Mitigation; PTE Inversion; VMX conditional cache flushes, SMT vulnerable
Vulnerability Mds: Mitigation; Clear CPU buffers; SMT vulnerable
Vulnerability Meltdown: Mitigation; PTI
Vulnerability Mmio stale data: Mitigation; Clear CPU buffers; SMT vulnerable
Vulnerability Reg file data sampling: Not affected
Vulnerability Retbleed: Mitigation; IBRS
Vulnerability Spec rstack overflow: Not affected
Vulnerability Spec store bypass: Mitigation; Speculative Store Bypass disabled via prctl
Vulnerability Spectre v1: Mitigation; usercopy/swapgs barriers and __user pointer sanitization
Vulnerability Spectre v2: Mitigation; IBRS; IBPB conditional; STIBP conditional; RSB filling; PBRSB-eIBRS Not affected; BHI Not affected
Vulnerability Srbds: Not affected
Vulnerability Tsx async abort: Mitigation; Clear CPU buffers; SMT vulnerable
Vulnerability Vmscape: Mitigation; IBPB before exit to userspace
Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb cat_l3 cdp_l3 invpcid_single pti intel_ppin ssbd mba ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm cqm mpx rdt_a avx512f avx512dq rdseed adx smap clflushopt clwb intel_pt avx512cd avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves cqm_llc cqm_occup_llc cqm_mbm_total cqm_mbm_local dtherm ida arat pln pts hwp hwp_act_window hwp_epp hwp_pkg_req pku ospke md_clear flush_l1d arch_capabilities

G++:
g++ (Ubuntu 9.4.0-1ubuntu1~20.04) 9.4.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Clang:
clang version 10.0.0-4ubuntu1
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin

@andrjohns

Copy link
Copy Markdown
Collaborator

Looking at the generated assembly, std::pow(x, 2) and x*x compile down to the same operation (mulsd) so I don't think this change is actually necessary

@andrjohns

Copy link
Copy Markdown
Collaborator

Looking at the generated assembly, std::pow(x, 2) and x*x compile down to the same operation (mulsd) so I don't think this change is actually necessary

Ahh looking at the linked issue I see the motivation, ignore me - sorry for the noise!

@WardBrian WardBrian left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

One minor thing but then I think we can merge this. Thank you!

Comment thread stan/math/rev/fun/squared_distance.hpp Outdated
check_finite("squared_distance", "a", a);
check_finite("squared_distance", "b", b);
return make_callback_vari(std::pow(a.val() - b, 2),
return make_callback_vari((a.val() - b) * (a.val() - b),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
return make_callback_vari((a.val() - b) * (a.val() - b),
double difference = a.val() - b;
return make_callback_vari(difference * difference,

And similarly above, to avoid the repetition

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I updated both functions to use a difference variable to avoid the repetition.

@Purna-Chandra-4706
Purna-Chandra-4706 marked this pull request as draft August 26, 2026 15:55
@Purna-Chandra-4706
Purna-Chandra-4706 marked this pull request as ready for review August 26, 2026 16:09
Comment thread stan/math/prim/fun/square.hpp
@SteveBronder SteveBronder self-assigned this Aug 26, 2026
@Purna-Chandra-4706

Copy link
Copy Markdown
Contributor Author

The downstream tests are failing, even though they passed successfully on the previous, identical change. My guess is this is a CI flake or timeout issue .could you help confirm whether something else is going on?

@WardBrian

Copy link
Copy Markdown
Member

It’s an unrelated issue that can be ignored

@stan-buildbot

Copy link
Copy Markdown
Contributor

Name Old Result New Result Ratio Performance change( 1 - new / old )
gp_regr/gp_regr.stan 0.13 0.11 1.17 14.21% faster
gp_regr/gen_gp_data.stan 0.03 0.03 1.02 2.22% faster
arK/arK.stan 1.74 1.68 1.04 3.51% faster
eight_schools/eight_schools.stan 0.06 0.06 1.03 3.38% faster
low_dim_gauss_mix_collapse/low_dim_gauss_mix_collapse.stan 9.18 8.94 1.03 2.58% faster
pkpd/one_comp_mm_elim_abs.stan 21.08 20.69 1.02 1.84% faster
pkpd/sim_one_comp_mm_elim_abs.stan 0.28 0.26 1.07 6.2% faster
sir/sir.stan 75.07 72.28 1.04 3.71% faster
gp_pois_regr/gp_pois_regr.stan 2.45 2.45 1.0 -0.01% slower
low_dim_gauss_mix/low_dim_gauss_mix.stan 2.98 2.92 1.02 2.21% faster
irt_2pl/irt_2pl.stan 6.17 5.43 1.13 11.89% faster
arma/arma.stan 0.38 0.33 1.15 13.35% faster
garch/garch.stan 0.57 0.49 1.17 14.71% faster
low_dim_corr_gauss/low_dim_corr_gauss.stan 0.01 0.01 1.08 7.46% faster
performance.compilation 266.86 272.49 0.98 -2.11% slower
Mean result: 1.063564322811493

Jenkins Console Log
Blue Ocean
Commit hash: b329e2697d67d8f4dceacb124013ad1193b4335c


Machine information No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 20.04.3 LTS Release: 20.04 Codename: focal

CPU:
Architecture: x86_64
CPU op-mode(s): 32-bit, 64-bit
Byte Order: Little Endian
Address sizes: 46 bits physical, 48 bits virtual
CPU(s): 80
On-line CPU(s) list: 0-79
Thread(s) per core: 2
Core(s) per socket: 20
Socket(s): 2
NUMA node(s): 2
Vendor ID: GenuineIntel
CPU family: 6
Model: 85
Model name: Intel(R) Xeon(R) Gold 6148 CPU @ 2.40GHz
Stepping: 4
CPU MHz: 2400.000
CPU max MHz: 3700.0000
CPU min MHz: 1000.0000
BogoMIPS: 4800.00
Virtualization: VT-x
L1d cache: 1.3 MiB
L1i cache: 1.3 MiB
L2 cache: 40 MiB
L3 cache: 55 MiB
NUMA node0 CPU(s): 0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62,64,66,68,70,72,74,76,78
NUMA node1 CPU(s): 1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31,33,35,37,39,41,43,45,47,49,51,53,55,57,59,61,63,65,67,69,71,73,75,77,79
Vulnerability Gather data sampling: Mitigation; Microcode
Vulnerability Itlb multihit: KVM: Mitigation: Split huge pages
Vulnerability L1tf: Mitigation; PTE Inversion; VMX conditional cache flushes, SMT vulnerable
Vulnerability Mds: Mitigation; Clear CPU buffers; SMT vulnerable
Vulnerability Meltdown: Mitigation; PTI
Vulnerability Mmio stale data: Mitigation; Clear CPU buffers; SMT vulnerable
Vulnerability Reg file data sampling: Not affected
Vulnerability Retbleed: Mitigation; IBRS
Vulnerability Spec rstack overflow: Not affected
Vulnerability Spec store bypass: Mitigation; Speculative Store Bypass disabled via prctl
Vulnerability Spectre v1: Mitigation; usercopy/swapgs barriers and __user pointer sanitization
Vulnerability Spectre v2: Mitigation; IBRS; IBPB conditional; STIBP conditional; RSB filling; PBRSB-eIBRS Not affected; BHI Not affected
Vulnerability Srbds: Not affected
Vulnerability Tsx async abort: Mitigation; Clear CPU buffers; SMT vulnerable
Vulnerability Vmscape: Mitigation; IBPB before exit to userspace
Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb cat_l3 cdp_l3 invpcid_single pti intel_ppin ssbd mba ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm cqm mpx rdt_a avx512f avx512dq rdseed adx smap clflushopt clwb intel_pt avx512cd avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves cqm_llc cqm_occup_llc cqm_mbm_total cqm_mbm_local dtherm ida arat pln pts hwp hwp_act_window hwp_epp hwp_pkg_req pku ospke md_clear flush_l1d arch_capabilities

G++:
g++ (Ubuntu 9.4.0-1ubuntu1~20.04) 9.4.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Clang:
clang version 10.0.0-4ubuntu1
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin

@WardBrian WardBrian left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thank you @Purna-Chandra-4706!

@WardBrian
WardBrian merged commit 7aafcdf into stan-dev:develop Aug 28, 2026
34 checks passed
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.

Efficiency: use multiplation over std::pow for squaring

5 participants