Skip to content

More stable logistic_lpdf/lcdf/lccdf computation - #3398

Open
avehtari wants to merge 13 commits into
fix-fwd-tanh-corr-jacobianfrom
improve-logistic_lpdf-derivative-stability
Open

avehtari wants to merge 13 commits into
fix-fwd-tanh-corr-jacobianfrom
improve-logistic_lpdf-derivative-stability

Conversation

@avehtari

@avehtari avehtari commented Sep 13, 2026 •

Copy link
Copy Markdown
Member

Fixes #2827

This PR is based on #3452 and must be merged after it: the second derivative of logistic_lpdf in nested forward mode needs the forward-mode tanh fix of #3452.

The PR was assisted with Sol and Claude.

Summary

logistic_lpdf

The logistic_lpdf location derivative separately exponentiated mu / sigma and y / sigma.
When mu / sigma > log(DBL_MAX / 2), this could produce an infinite or NaN gradient even though
the log density and true gradient remained finite. For example, y = 711, mu = 710, and
sigma = 1 returned a NaN location gradient instead of tanh(0.5).

The denominator can overflow before 2 * exp(m) does leading to big errors. For example: m = log(DBL_MAX / 2) - 1e-6 and d = 0.1 old gradient is 1.0 while exact gradient is tanh(0.05) = 0.04995837495788

  • Before any intermediate overflow, error is often small.
  • Denominator overflow can produce a large but finite error first.
  • Numerator overflow then produces -Inf or NaN.
  • The transition is abrupt, which is particularly problematic for HMC trajectories.

The new tanh(d / 2) / sigma form depends only on the standardized difference and remains bounded by
1 / sigma.

logistic_lccdf

For logistic_lccdf(z | 0, 1):

z Current value Stable value Current gradient Stable gradient
30 -30.0010 -30 -1.00102 -1
34 -33.9642 -34 -0.96484 -1
35 -34.9450 -35 -0.94652 -1
36 -36.0437 -36 -1.04462 -1
36.5 -36.0437 -36.5 -0.63359 -1
36.736 -36.0437 -36.736 -0.50040 -1
36.74 -Inf -36.74 -Inf -1

The error is already substantial before saturation, and happens with values of z that are not completely unfeasible.

After fix

  • Value uses log1m_inv_logit(z).
  • Gradients inv_logit(z) / sigma.

logistic_lcdf

For logistic_lcdf(z | 0, 1):

z Current value Stable value
-730 -729.9999998 -730
-740 -739.997421 -740
-742 -742.042177 -742
-744 -743.746925 -744
-745 -744.440072 -745
-745.2 -Inf -745.2

The LCDF gradient remains exactly 1 through the subnormal region, then becomes NaN when
exp(z) underflows completely. This one is least likely to happen.

  • After fix
    • Value uses log_inv_logit(z).
    • Gradients inv_logit(-z) / sigma.

Tests

  • Regression tests added. CPU tests test against known values, OpenCL tests test against CPU.
  • 9 of 16 new CPU tests and 4 of 38 OpenCL tests fail on develop and pass with this PR.
  • The fixes after review add tests against mpmath reference values for the CPU, for OpenCL and for the second derivative in nested forward mode; the review findings, the fixes and the test counts are in a comment below.

Side Effects

Removes the following comment from the logistic_lccdf and logistic_lcdf code (as the derivatives are simpler and more stable after this PR)

// TODO(Andrew) Further simplify derivatives and log-scale below

Release notes

  • Improved stability of logistic_lpdf, logistic_lccdf and logistic_lcdf derivatives.

Checklist

  • Copyright holder: Aki Vehtari

    The copyright holder is typically you or your assignee, such as a university or company. By submitting this pull request, the copyright holder is agreeing to the license the submitted work under the following licenses:
    - Code: BSD 3-clause (https://opensource.org/licenses/BSD-3-Clause)
    - Documentation: CC-BY 4.0 (https://creativecommons.org/licenses/by/4.0/)

  • the basic tests are passing

    • unit tests pass (to run, use: ./runTests.py test/unit)
    • header checks pass, (make test-headers)
    • dependencies checks pass, (make test-math-dependencies)
    • docs build, (make doxygen)
    • code passes the built in C++ standards checks (make cpplint)
  • the code is written in idiomatic C++ and changes are documented in the doxygen

  • the new changes are tested

@avehtari avehtari changed the title More stable logistic_lpdf derivative More stable logistic_lpdf/lcdf/lccdf derivatives Sep 13, 2026
@avehtari avehtari changed the title More stable logistic_lpdf/lcdf/lccdf derivatives More stable logistic_lpdf/lcdf/lccdf computation Sep 13, 2026
@stan-buildbot

Copy link
Copy Markdown
Contributor
Name Old Result New Result Ratio Performance change( 1 - new / old )
stat_comp_benchmarks/benchmarks/low_dim_gauss_mix_collapse/low_dim_gauss_mix_collapse.stan 8.31 8.26 1.01 0.62% faster
stat_comp_benchmarks/benchmarks/gp_pois_regr/gp_pois_regr.stan 2.24 2.2 1.02 1.75% faster
stat_comp_benchmarks/benchmarks/eight_schools/eight_schools.stan 0.06 0.06 1.02 1.48% faster
stat_comp_benchmarks/benchmarks/irt_2pl/irt_2pl.stan 4.84 4.73 1.02 2.32% faster
stat_comp_benchmarks/benchmarks/garch/garch.stan 0.43 0.42 1.01 0.77% faster
stat_comp_benchmarks/benchmarks/low_dim_gauss_mix/low_dim_gauss_mix.stan 2.75 2.67 1.03 2.95% faster
stat_comp_benchmarks/benchmarks/pkpd/sim_one_comp_mm_elim_abs.stan 0.25 0.24 1.02 1.74% faster
stat_comp_benchmarks/benchmarks/pkpd/one_comp_mm_elim_abs.stan 19.34 19.0 1.02 1.76% faster
stat_comp_benchmarks/benchmarks/gp_regr/gen_gp_data.stan 0.02 0.02 0.99 -1.11% slower
stat_comp_benchmarks/benchmarks/gp_regr/gp_regr.stan 0.1 0.1 1.04 3.57% faster
stat_comp_benchmarks/benchmarks/sir/sir.stan 66.74 65.12 1.02 2.42% faster
stat_comp_benchmarks/benchmarks/arK/arK.stan 1.56 1.51 1.04 3.39% faster
stat_comp_benchmarks/benchmarks/low_dim_corr_gauss/low_dim_corr_gauss.stan 0.01 0.01 1.0 0.1% faster
stat_comp_benchmarks/benchmarks/arma/arma.stan 0.28 0.28 1.03 2.7% faster
performance.compilation 242.67 239.05 1.02 1.49% faster
Mean result: 1.0177607799093016

Jenkins Console Log
Jenkins Build Stages
Commit hash: 462bc7269ad3260b4564ce2d4c0e4e32b24944aa

Machine information
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 6248 CPU @ 2.50GHz
Stepping:                                7
CPU MHz:                                 997.515
CPU max MHz:                             3900.0000
CPU min MHz:                             1000.0000
BogoMIPS:                                5000.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 Indirect target selection: Mitigation; Aligned branch/return thunks
Vulnerability Itlb multihit:             KVM: Mitigation: Split huge pages
Vulnerability L1tf:                      Not affected
Vulnerability Mds:                       Not affected
Vulnerability Meltdown:                  Not affected
Vulnerability Mmio stale data:           Mitigation; Clear CPU buffers; SMT vulnerable
Vulnerability Reg file data sampling:    Not affected
Vulnerability Retbleed:                  Mitigation; Enhanced 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; Enhanced / Automatic IBRS; IBPB conditional; PBRSB-eIBRS SW sequence; BHI SW loop, KVM SW loop
Vulnerability Srbds:                     Not affected
Vulnerability Tsa:                       Not affected
Vulnerability Tsx async abort:           Mitigation; TSX disabled
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 intel_ppin ssbd mba ibrs ibpb stibp ibrs_enhanced tpr_shadow flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid 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 vnmi pku ospke avx512_vnni 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

@avehtari

Copy link
Copy Markdown
Member Author

Follow-up

logistic_cdf carried the same exp(logistic_lpdf(y, mu, sigma)) / Pn pattern
this PR removed from the log-scale functions, so it is converted too — the
partials now accumulate inv_logit(-z) / sigma and are rescaled by the cdf
product. The quotient was 0 / 0 once Pn underflowed (NaN at z = -746 on
the CPU, and from z ≈ -709 on the device, where exp(-z) overflows first).

logistic_lpdf kept the old 2 / (1 + exp(z)) - 1 form for the y partial
while the mu partial moved to tanh(z / 2). Since d/dy == -d/dmu exactly,
that left the two disagreeing near y == mu, where the exp form loses all
relative precision:

z 2 / (1 + exp(z)) - 1 -tanh(z / 2) rel err
1e-12 -5.00044450291e-13 -5.0e-13 8.9e-05
1e-14 -4.88498130835e-15 -5.0e-15 2.3e-02
1e-16 +0.0 -5.0e-17 1.0

All three partials are now built from one tanh(z / 2) / sigma, which also
drops an exp from the OpenCL kernel.

Two smaller fixes in the same files:

  • logistic_lccdf returned from inside the accumulation loop on y == INFTY,
    keeping the partials already accumulated for the preceding elements. Both
    infinity scans now run before the loop.
  • The OpenCL logistic_lcdf and logistic_cdf computed 0 * INFTY = NaN for
    the scale partial at y == INFTY, where prim skips the element outright.

Tests: mu != 0 / sigma != 1 cases so the scale partial is not aliased by
sigma == 1; a z = 30 case for lccdf, where the old cancellation was
already 0.1 % off well before it returned -Inf; a y ≈ mu case asserting
y.adj() == -mu.adj() bit-for-bit; a vectorised case for the mu edge's
container path; and test/unit/math/rev/prob/logistic_cdf_test.cpp.

@stan-buildbot

Copy link
Copy Markdown
Contributor
Name Old Result New Result Ratio Performance change( 1 - new / old )
stat_comp_benchmarks/benchmarks/gp_regr/gen_gp_data.stan 0.04 0.04 1.01 0.55% faster
stat_comp_benchmarks/benchmarks/gp_regr/gp_regr.stan 0.17 0.16 1.02 1.72% faster
stat_comp_benchmarks/benchmarks/garch/garch.stan 0.87 0.88 0.99 -0.54% slower
stat_comp_benchmarks/benchmarks/low_dim_corr_gauss/low_dim_corr_gauss.stan 0.01 0.01 0.95 -4.84% slower
stat_comp_benchmarks/benchmarks/eight_schools/eight_schools.stan 0.11 0.11 0.99 -0.86% slower
stat_comp_benchmarks/benchmarks/low_dim_gauss_mix/low_dim_gauss_mix.stan 8.33 8.39 0.99 -0.66% slower
stat_comp_benchmarks/benchmarks/gp_pois_regr/gp_pois_regr.stan 3.68 3.69 1.0 -0.27% slower
stat_comp_benchmarks/benchmarks/pkpd/one_comp_mm_elim_abs.stan 32.8 32.93 1.0 -0.39% slower
stat_comp_benchmarks/benchmarks/pkpd/sim_one_comp_mm_elim_abs.stan 0.38 0.38 1.0 -0.44% slower
stat_comp_benchmarks/benchmarks/irt_2pl/irt_2pl.stan 6.63 6.62 1.0 0.11% faster
stat_comp_benchmarks/benchmarks/sir/sir.stan 137.75 135.43 1.02 1.69% faster
stat_comp_benchmarks/benchmarks/arK/arK.stan 3.22 3.21 1.0 0.4% faster
stat_comp_benchmarks/benchmarks/arma/arma.stan 0.59 0.6 1.0 -0.46% slower
stat_comp_benchmarks/benchmarks/low_dim_gauss_mix_collapse/low_dim_gauss_mix_collapse.stan 25.25 25.11 1.01 0.57% faster
performance.compilation 376.96 391.95 0.96 -3.98% slower
Mean result: 0.9953912496749436

Jenkins Console Log
Jenkins Build Stages
Commit hash: 4b4fb7b315c6e633d2de11a303b7b17201fbfc2b

Machine information
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:                           52 bits physical, 57 bits virtual
CPU(s):                                  192
On-line CPU(s) list:                     0-191
Thread(s) per core:                      2
Core(s) per socket:                      48
Socket(s):                               2
NUMA node(s):                            2
Vendor ID:                               AuthenticAMD
CPU family:                              25
Model:                                   17
Model name:                              AMD EPYC 9474F 48-Core Processor
Stepping:                                1
Frequency boost:                         enabled
CPU MHz:                                 1496.334
CPU max MHz:                             4114.4229
CPU min MHz:                             1500.0000
BogoMIPS:                                7189.04
Virtualization:                          AMD-V
L1d cache:                               3 MiB
L1i cache:                               3 MiB
L2 cache:                                96 MiB
L3 cache:                                512 MiB
NUMA node0 CPU(s):                       0-47,96-143
NUMA node1 CPU(s):                       48-95,144-191
Vulnerability Gather data sampling:      Not affected
Vulnerability Indirect target selection: Not affected
Vulnerability Itlb multihit:             Not affected
Vulnerability L1tf:                      Not affected
Vulnerability Mds:                       Not affected
Vulnerability Meltdown:                  Not affected
Vulnerability Mmio stale data:           Not affected
Vulnerability Reg file data sampling:    Not affected
Vulnerability Retbleed:                  Not affected
Vulnerability Spec rstack overflow:      Mitigation; Safe RET
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; Enhanced / Automatic IBRS; IBPB conditional; STIBP always-on; PBRSB-eIBRS Not affected; BHI Not affected
Vulnerability Srbds:                     Not affected
Vulnerability Tsa:                       Mitigation; Clear CPU buffers
Vulnerability Tsx async abort:           Not affected
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 mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm constant_tsc rep_good amd_lbr_v2 nopl xtopology nonstop_tsc cpuid extd_apicid aperfmperf rapl pni pclmulqdq monitor ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx f16c rdrand lahf_lm cmp_legacy svm extapic cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw ibs skinit wdt tce topoext perfctr_core perfctr_nb bpext perfctr_llc mwaitx cpb cat_l3 cdp_l3 hw_pstate ssbd mba perfmon_v2 ibrs ibpb stibp ibrs_enhanced vmmcall fsgsbase bmi1 avx2 smep bmi2 erms invpcid cqm rdt_a avx512f avx512dq rdseed adx smap avx512ifma clflushopt clwb avx512cd sha_ni avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves cqm_llc cqm_occup_llc cqm_mbm_total cqm_mbm_local user_shstk avx512_bf16 clzero irperf xsaveerptr rdpru wbnoinvd amd_ppin cppc arat npt lbrv svm_lock nrip_save tsc_scale vmcb_clean flushbyasid decodeassists pausefilter pfthreshold avic v_vmsave_vmload vgif x2avic v_spec_ctrl vnmi avx512vbmi umip pku ospke avx512_vbmi2 gfni vaes vpclmulqdq avx512_vnni avx512_bitalg avx512_vpopcntdq la57 rdpid overflow_recov succor smca fsrm flush_l1d debug_swap

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 andrjohns left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

A couple more areas which can be moved to the log-scale for a bit more precision. I've only made the comments on the prim impls, but the same applies to all

Comment thread stan/math/prim/prob/logistic_lcdf.hpp Outdated
+= -(y_dbl - mu_dbl) * sigma_inv_vec
* exp(logistic_lpdf(y_dbl, mu_dbl, sigma_dbl)) / Pn;
if constexpr (is_any_autodiff_v<T_y, T_loc, T_scale>) {
const T_partials_return deriv = inv_logit(-scaled_diff) * sigma_inv_vec;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This step is still subject to underflow for very large scaled_diff (i.e., very small sigma), which would round the derivative to 0.

You can keep things on the log-scale for a bit longer using log1m_inv_logit:

const T_partials_return log_sigma = log(sigma_vec);
const T_partials_return log_deriv = log1m_inv_logit(scaled_diff) - log_sigma;
const T_partials_return deriv = exp(log_deriv);

if constexpr (is_autodiff_v<T_y>) {
  partials<0>(ops_partials)[n] += deriv;
}
if constexpr (is_autodiff_v<T_loc>) {
  partials<1>(ops_partials)[n] -= deriv;
}
if constexpr (is_autodiff_v<T_scale>) {
  partials<2>(ops_partials)[n] -= sign(scaled_diff) * exp(log(abs(scaled_diff)) + log_deriv);
}

With corresponding re-ordering/changes for the LCCDF impls

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This and other issues may have been not included in the PR as some cases are quite narrow. The following is Claude assisted

This case needs σ < 2.3e-16 at z = 745, tightening to σ < 3e-40 at z = 800, and the largest gradient recoverable anywhere in the window is 8.9e-16 (beyond that 1/σ overflows). Note log_inv_logit(z) — the value the lcdf accumulates — also reaches exactly 0 at the same threshold where inv_logit(-z) does, so this recovers the slope of a numerically flat region.

But since you asked, I made a simpler faster solution. In your proposal log1m_inv_logit is a second log1p_exp on top of the one the lcdf already computes for the value, plus log(sigma) and exp. Measured on the derivative factor alone: 3.4 ns/element currently, 16.0 ns for your proposal. Behind value_of_rec(scaled_diff) > 700 it's 3.7 ns, about 10%, and that's a well-predicted branch. So the common path keeps inv_logit(-z) * inv_sigma and only the underflowing case takes the log route.

Left the scale partial as scaled_diff * deriv. Where deriv underflows we have |z| > 745, so z * deriv is larger than deriv and can't underflow if deriv didn't. The log form there costs a log, exp, sign and abs for no gain, and log(abs(0)) at z = 0 relies on sign(0) to clean up the resulting 0 * -inf.

Tests at σ = 1e-300, z = 800, one per function. Each asserts inv_logit(-z) == 0 at the test point, so they fail on the previous code.

Comment thread stan/math/prim/prob/logistic_lpdf.hpp Outdated
Comment thread stan/math/prim/prob/logistic_lpdf.hpp Outdated
Comment on lines +70 to 72
const T_partials_return Pn = inv_logit(scaled_diff);

P *= Pn;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This can use the same log-calculations as the lcdf (see below), accumulating on the log scale and exponentiating the result (for the derivatives as well)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Claude assisted answer:

Measured against a long double reference, exp(Σ log inv_logit) is 749 ulp at N=100, z=−0.5 against 3.0 for the product, and 641 vs 1.0 at N=10, z=−70 — exp amplifies the summed log by |log P|·eps. It also doesn't extend the range: both forms underflow at the same points, including for a single observation at z = −745.2. inv_logit has no cancellation to avoid, unlike the difference in exp_mod_normal_cdf where the log scale genuinely buys something.

The rescaling partials *= cdf does drop the case where the cdf underflows but cdf × ∂log F/∂θ is representable. That's the same σ < 1e-16 window as the tail fix, and there the cdf returns exactly 0, so logistic_lcdf is the right function. If you want this to be changes, it needs sign tracking to exponentiate each partial separately.

Comment thread stan/math/prim/prob/logistic_cdf.hpp Outdated
EXPECT_DOUBLE_EQ(0.0, cdf.val());
EXPECT_DOUBLE_EQ(0.0, y.adj());
EXPECT_DOUBLE_EQ(0.0, mu.adj());
EXPECT_DOUBLE_EQ(0.0, sigma.adj());

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

With the extra log-scale changes for the derivatives above, the adjoint for sigma here ends up being (barely) non-zero (~7.76e-322) instead of underflowing

@avehtari

Copy link
Copy Markdown
Member Author

I had tested only that OpenCL code compiles and the code matches CPU code, but it turns out the compiler can optimize things so that the accuracy drops, so I'll run additional OpenCL tests tomorrow

@stan-buildbot

Copy link
Copy Markdown
Contributor
Name Old Result New Result Ratio Performance change( 1 - new / old )
stat_comp_benchmarks/benchmarks/gp_regr/gen_gp_data.stan 0.04 0.04 0.97 -2.66% slower
stat_comp_benchmarks/benchmarks/gp_regr/gp_regr.stan 0.16 0.16 1.0 -0.39% slower
stat_comp_benchmarks/benchmarks/garch/garch.stan 0.87 0.86 1.01 0.88% faster
stat_comp_benchmarks/benchmarks/low_dim_corr_gauss/low_dim_corr_gauss.stan 0.01 0.01 1.02 1.57% faster
stat_comp_benchmarks/benchmarks/eight_schools/eight_schools.stan 0.11 0.11 1.0 0.28% faster
stat_comp_benchmarks/benchmarks/low_dim_gauss_mix/low_dim_gauss_mix.stan 8.42 8.36 1.01 0.71% faster
stat_comp_benchmarks/benchmarks/gp_pois_regr/gp_pois_regr.stan 3.69 3.7 1.0 -0.07% slower
stat_comp_benchmarks/benchmarks/pkpd/one_comp_mm_elim_abs.stan 32.83 33.79 0.97 -2.93% slower
stat_comp_benchmarks/benchmarks/pkpd/sim_one_comp_mm_elim_abs.stan 0.38 0.38 0.99 -0.89% slower
stat_comp_benchmarks/benchmarks/irt_2pl/irt_2pl.stan 6.86 6.86 1.0 0.02% faster
stat_comp_benchmarks/benchmarks/sir/sir.stan 138.66 135.79 1.02 2.07% faster
stat_comp_benchmarks/benchmarks/arK/arK.stan 3.17 3.21 0.99 -1.4% slower
stat_comp_benchmarks/benchmarks/arma/arma.stan 0.59 0.59 1.01 1.34% faster
stat_comp_benchmarks/benchmarks/low_dim_gauss_mix_collapse/low_dim_gauss_mix_collapse.stan 25.02 25.31 0.99 -1.13% slower
performance.compilation 385.92 386.62 1.0 -0.18% slower
Mean result: 0.9983483632939933

Jenkins Console Log
Jenkins Build Stages
Commit hash: 98c64f32efad1c4821e30c9f76801a0d0c89d086

Machine information
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:                           52 bits physical, 57 bits virtual
CPU(s):                                  192
On-line CPU(s) list:                     0-191
Thread(s) per core:                      2
Core(s) per socket:                      48
Socket(s):                               2
NUMA node(s):                            2
Vendor ID:                               AuthenticAMD
CPU family:                              25
Model:                                   17
Model name:                              AMD EPYC 9474F 48-Core Processor
Stepping:                                1
Frequency boost:                         enabled
CPU MHz:                                 1497.618
CPU max MHz:                             4114.4229
CPU min MHz:                             1500.0000
BogoMIPS:                                7189.39
Virtualization:                          AMD-V
L1d cache:                               3 MiB
L1i cache:                               3 MiB
L2 cache:                                96 MiB
L3 cache:                                512 MiB
NUMA node0 CPU(s):                       0-47,96-143
NUMA node1 CPU(s):                       48-95,144-191
Vulnerability Gather data sampling:      Not affected
Vulnerability Indirect target selection: Not affected
Vulnerability Itlb multihit:             Not affected
Vulnerability L1tf:                      Not affected
Vulnerability Mds:                       Not affected
Vulnerability Meltdown:                  Not affected
Vulnerability Mmio stale data:           Not affected
Vulnerability Old microcode:             Not affected
Vulnerability Reg file data sampling:    Not affected
Vulnerability Retbleed:                  Not affected
Vulnerability Spec rstack overflow:      Mitigation; Safe RET
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; Enhanced / Automatic IBRS; IBPB conditional; STIBP always-on; PBRSB-eIBRS Not affected; BHI Not affected
Vulnerability Srbds:                     Not affected
Vulnerability Tsa:                       Mitigation; Clear CPU buffers
Vulnerability Tsx async abort:           Not affected
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 mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm constant_tsc rep_good amd_lbr_v2 nopl xtopology nonstop_tsc cpuid extd_apicid aperfmperf rapl pni pclmulqdq monitor ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx f16c rdrand lahf_lm cmp_legacy svm extapic cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw ibs skinit wdt tce topoext perfctr_core perfctr_nb bpext perfctr_llc mwaitx cpb cat_l3 cdp_l3 hw_pstate ssbd mba perfmon_v2 ibrs ibpb stibp ibrs_enhanced vmmcall fsgsbase bmi1 avx2 smep bmi2 erms invpcid cqm rdt_a avx512f avx512dq rdseed adx smap avx512ifma clflushopt clwb avx512cd sha_ni avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves cqm_llc cqm_occup_llc cqm_mbm_total cqm_mbm_local user_shstk avx512_bf16 clzero irperf xsaveerptr rdpru wbnoinvd amd_ppin cppc arat npt lbrv svm_lock nrip_save tsc_scale vmcb_clean flushbyasid decodeassists pausefilter pfthreshold avic v_vmsave_vmload vgif x2avic v_spec_ctrl vnmi avx512vbmi umip pku ospke avx512_vbmi2 gfni vaes vpclmulqdq avx512_vnni avx512_bitalg avx512_vpopcntdq la57 rdpid overflow_recov succor smca fsrm flush_l1d debug_swap

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

@avehtari

avehtari commented Sep 17, 2026 •

Copy link
Copy Markdown
Member Author

I ran units tests only today on a Tesla V100 (OpenCL 3.0 CUDA) on the Aalto Triton cluster. All four test suites pass: 28 tests.

I also compared the device results against the CPU results directly, because the tests compare them only to a tolerance. The device results and the CPU results agree to 2.0 to 2.6 ulp (which is negligible difference)

@WardBrian

Copy link
Copy Markdown
Member

CI should have a GPU available, what did you try that didn’t work as you expected?

@avehtari

Copy link
Copy Markdown
Member Author

I should have written that I had not run OpenCL unit tests when I first submitted this PR, although I had checked "unit tests pass".

The additional tests comparing the accuracy between CPU and GPU with millions of evaluation points are not in the unit tests, and I did run them because in erfcx PR all unit tests did pass, but comparing CPU and GPU results did reveal that OpenCL compiler had optimized one part so that the accuracy went from 5ulp to 500ulp.

@avehtari avehtari mentioned this pull request Sep 18, 2026
4 tasks done
@avehtari

avehtari commented Oct 7, 2026

Copy link
Copy Markdown
Member Author

I just noticed that this also fixes an old issue #2827

@stan-buildbot

Copy link
Copy Markdown
Contributor
Name Old Result New Result Ratio Performance change( 1 - new / old )
stat_comp_benchmarks/benchmarks/low_dim_gauss_mix_collapse/low_dim_gauss_mix_collapse.stan 7.87 7.78 1.01 1.18% faster
stat_comp_benchmarks/benchmarks/gp_pois_regr/gp_pois_regr.stan 2.08 2.08 1.0 0.07% faster
stat_comp_benchmarks/benchmarks/eight_schools/eight_schools.stan 0.05 0.05 1.03 2.54% faster
stat_comp_benchmarks/benchmarks/irt_2pl/irt_2pl.stan 3.96 3.93 1.01 0.63% faster
stat_comp_benchmarks/benchmarks/garch/garch.stan 0.41 0.4 1.01 1.38% faster
stat_comp_benchmarks/benchmarks/low_dim_gauss_mix/low_dim_gauss_mix.stan 2.55 2.53 1.01 0.64% faster
stat_comp_benchmarks/benchmarks/pkpd/sim_one_comp_mm_elim_abs.stan 0.23 0.23 1.03 2.51% faster
stat_comp_benchmarks/benchmarks/pkpd/one_comp_mm_elim_abs.stan 17.81 17.79 1.0 0.12% faster
stat_comp_benchmarks/benchmarks/gp_regr/gen_gp_data.stan 0.02 0.02 1.03 2.97% faster
stat_comp_benchmarks/benchmarks/gp_regr/gp_regr.stan 0.1 0.09 1.04 3.74% faster
stat_comp_benchmarks/benchmarks/sir/sir.stan 62.94 62.54 1.01 0.64% faster
stat_comp_benchmarks/benchmarks/arK/arK.stan 1.46 1.45 1.01 0.79% faster
stat_comp_benchmarks/benchmarks/low_dim_corr_gauss/low_dim_corr_gauss.stan 0.01 0.01 0.99 -0.93% slower
stat_comp_benchmarks/benchmarks/arma/arma.stan 0.27 0.26 1.01 0.85% faster
performance.compilation 244.03 218.9 1.11 10.3% faster
Mean result: 1.0193568850003691

Jenkins Console Log
Jenkins Build Stages
Commit hash: 44a50912ff3f2e71023ea29a6f91adf7c6b1cf87

Machine information
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 6248 CPU @ 2.50GHz
Stepping:                                7
CPU MHz:                                 1000.234
CPU max MHz:                             3900.0000
CPU min MHz:                             1000.0000
BogoMIPS:                                5000.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 Indirect target selection: Mitigation; Aligned branch/return thunks
Vulnerability Itlb multihit:             KVM: Mitigation: Split huge pages
Vulnerability L1tf:                      Not affected
Vulnerability Mds:                       Not affected
Vulnerability Meltdown:                  Not affected
Vulnerability Mmio stale data:           Mitigation; Clear CPU buffers; SMT vulnerable
Vulnerability Old microcode:             Not affected
Vulnerability Reg file data sampling:    Not affected
Vulnerability Retbleed:                  Mitigation; Enhanced 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; Enhanced / Automatic IBRS; IBPB conditional; PBRSB-eIBRS SW sequence; BHI SW loop, KVM SW loop
Vulnerability Srbds:                     Not affected
Vulnerability Tsa:                       Not affected
Vulnerability Tsx async abort:           Mitigation; TSX disabled
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 intel_ppin ssbd mba ibrs ibpb stibp ibrs_enhanced tpr_shadow flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid 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 vnmi pku ospke avx512_vnni 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

@jachymb

jachymb commented Oct 12, 2026

Copy link
Copy Markdown
Contributor

Hi @avehtari I was working on something similar and mostly took basically the same approach here, but here are a few inconsistencies. I can send these with tests on top of this branch, or after it merges of you can copypaste the comments below to your agent.

Comments

Checked at 448dcc1 with a probe (CPU, and pocl's CPU device for the OpenCL versions), mpmath as reference. These fail; all are pre-existing on develop but sit in lines this PR restructured:

quantity inputs this branch exact
logistic_lccdf with a −inf element: the NEGATIVE_INFTY scan returns 0 for the whole call (CPU and device) y = {−inf, 0}, μ=0, σ=1 0, all partials 0 log 0.5; ∂y₁ = −0.5, ∂μ = 0.5
same y = {−inf, +inf} 0 −inf
∂σ when (y−μ)/σ overflows with finite y, μ: scaled_diff * deriv = inf·0 (lcdf, lccdf, cdf; CPU and device) lcdf(1e10, 0, 1e−300); lccdf(−1e10, 0, 1e−300); cdf(±1e10, 0, 1e−300) NaN 0
logistic_lpdf value at z = −inf: inf − inf lpdf(−1e308, 1e308, 1) NaN −inf

Fixes: in logistic_lccdf keep the +inf scan and make the -inf check a continue in the loop (device: select(y == NEGATIVE_INFTY, 0, ...) on the per-element terms instead of any_y_neg_inf); isinf(scaled_diff) ? 0 : scaled_diff * deriv for ∂σ in the three functions and their OpenCL twins; the lpdf value as −|z| − 2 log1p_exp(−|z|). The OpenCL tests compare only against the CPU, so they pass with both sides wrong; an assertion against these exact values would catch it.

One regression: with fvar<fvar<double>> the lpdf's ∂²/∂y² is now 0 for |z| > 37.4 (−0 at z = 40, exact −2.12e−18; develop correct), because fwd tanh differentiates as 1 − u². fvar<var> is fine.

@avehtari

Copy link
Copy Markdown
Member Author

@jachymb thanks for the review and suggestions. Looking at those revealed additional issues, so I'm making some commits to this PR and creating one additional PR

@avehtari
avehtari changed the base branch from develop to fix-fwd-tanh-corr-jacobian October 13, 2026 14:11
@avehtari

Copy link
Copy Markdown
Member Author

@jachymb, I could reproduce all five findings, and they are fixed now. Due to the tanh issue affecting also correlation constraints, there is a separate PR #3452 for tanh

logistic_lccdf with a -inf element. The CPU loop now skips an element with y == -inf (continue); the scan for +inf stays, so y = {-inf, +inf} returns -inf. The OpenCL version no longer returns early for -inf; it uses select(y == NEGATIVE_INFTY, 0, ...) on the value term and on the partials.

The scale partial when (y - mu) / sigma overflows. I guarded the side where the derivative factor is zero, not both sides: lcdf for z == +inf, lccdf for z == -inf, and cdf for both. On the other side the exact partial overflows, so +inf is the correctly rounded value; for example lcdf(-1e10 | 0, 1e-300) has d/dsigma = -z (1 - F) / sigma, about 1e310 * 1e300. In cdf both sides give 0, because there P = 0 when z = -inf. CPU and OpenCL.

logistic_lpdf value at z = -inf. The value is now -|z| - 2 log1p_exp(-|z|), CPU and OpenCL.

The fvar<fvar<double>> second derivative of logistic_lpdf. You are right, and -2.12e-18 is the exact value at z = 40 with sigma = 2. The cause is fwd tanh, whose derivative 1 - u * u is exactly 0 from |x| = 19.06 and has an error of up to 5.7e3 ulp for |x| from 1 to 5. I repaired it in #3452, together with the log Jacobians of the correlation transforms, which had the same cancellation (and whose forward-mode gradient was correct only because the two errors cancelled). This PR is now based on #3452 and has a test of the first and second derivative in fvar<fvar<double>> and fvar<var> at z = 1, -20, 40, 100 and at sigma = 2.

Tests. New tests compare against mpmath values, also for OpenCL, because, as you wrote, the OpenCL tests that compare with the CPU pass when both are wrong in the same way. To check that the new tests find the defects, I ran them with the headers of 448dcc178c:

  • CPU: 6 of the 9 new tests in test/unit/math/rev/prob/logistic_*_test.cpp fail; the other 3 check cases that did not change.
  • OpenCL (Tesla V100): the 5 new reference tests fail, and so does the existing opencl_matches_cpu_small_y_neg_inf, because the CPU lccdf now differs from the old OpenCL lccdf at y = -inf.
  • The new second-derivative test fails with the develop fwd/fun/tanh.hpp and passes with Accurate forward-mode tanh derivative and correlation transforms #3452.

With the current headers all tests pass: the CPU and OpenCL logistic unit tests, the existing prim logistic tests, and the generated test/prob/logistic tests (23 173 cases). Tested with develop 43bc5684a3 plus this PR (g++ 14.3), and with #3452 plus this PR (g++ 11.5).

@jachymb, please test with your Hessian/Laplace tests, too

@jachymb

jachymb commented Oct 13, 2026

Copy link
Copy Markdown
Contributor

LGTM. All five findings are fixed, and I have nothing to change here. Same for #3434

I may have some related changes in backlog, but I need to look more into that myself first, and it's probably better as a follow-up separate PR after this batch gets merged.

@stan-buildbot

Copy link
Copy Markdown
Contributor
Name Old Result New Result Ratio Performance change( 1 - new / old )
stat_comp_benchmarks/benchmarks/gp_regr/gp_regr.stan 0.22 0.22 1.0 -0.09% slower
stat_comp_benchmarks/benchmarks/gp_regr/gen_gp_data.stan 0.06 0.06 0.99 -1.04% slower
stat_comp_benchmarks/benchmarks/low_dim_corr_gauss/low_dim_corr_gauss.stan 0.02 0.02 0.99 -1.18% slower
stat_comp_benchmarks/benchmarks/arma/arma.stan 0.61 0.61 1.0 0.15% faster
stat_comp_benchmarks/benchmarks/arK/arK.stan 3.21 3.18 1.01 0.68% faster
stat_comp_benchmarks/benchmarks/pkpd/one_comp_mm_elim_abs.stan 43.43 42.16 1.03 2.92% faster
stat_comp_benchmarks/benchmarks/pkpd/sim_one_comp_mm_elim_abs.stan 0.58 0.59 0.98 -1.98% slower
stat_comp_benchmarks/benchmarks/gp_pois_regr/gp_pois_regr.stan 4.52 4.5 1.01 0.54% faster
stat_comp_benchmarks/benchmarks/low_dim_gauss_mix_collapse/low_dim_gauss_mix_collapse.stan 21.01 20.98 1.0 0.17% faster
stat_comp_benchmarks/benchmarks/garch/garch.stan 0.89 0.89 0.99 -0.87% slower
stat_comp_benchmarks/benchmarks/eight_schools/eight_schools.stan 0.11 0.11 1.0 0.28% faster
stat_comp_benchmarks/benchmarks/irt_2pl/irt_2pl.stan 8.37 8.4 1.0 -0.35% slower
stat_comp_benchmarks/benchmarks/low_dim_gauss_mix/low_dim_gauss_mix.stan 6.41 6.39 1.0 0.41% faster
stat_comp_benchmarks/benchmarks/sir/sir.stan 169.93 170.51 1.0 -0.35% slower
performance.compilation 382.0 384.26 0.99 -0.59% slower
Mean result: 0.9992485665134959

Jenkins Console Log
Jenkins Build Stages
Commit hash: a827cdd3e0feedf2727b243d86681a6a8e0fd2ba

Machine information
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:                           43 bits physical, 48 bits virtual
CPU(s):                                  256
On-line CPU(s) list:                     0-255
Thread(s) per core:                      2
Core(s) per socket:                      64
Socket(s):                               2
NUMA node(s):                            2
Vendor ID:                               AuthenticAMD
CPU family:                              23
Model:                                   49
Model name:                              AMD EPYC 7742 64-Core Processor
Stepping:                                0
Frequency boost:                         enabled
CPU MHz:                                 1485.980
CPU max MHz:                             3416.0681
CPU min MHz:                             1500.0000
BogoMIPS:                                4491.56
Virtualization:                          AMD-V
L1d cache:                               4 MiB
L1i cache:                               4 MiB
L2 cache:                                64 MiB
L3 cache:                                512 MiB
NUMA node0 CPU(s):                       0-63,128-191
NUMA node1 CPU(s):                       64-127,192-255
Vulnerability Gather data sampling:      Not affected
Vulnerability Indirect target selection: Not affected
Vulnerability Itlb multihit:             Not affected
Vulnerability L1tf:                      Not affected
Vulnerability Mds:                       Not affected
Vulnerability Meltdown:                  Not affected
Vulnerability Mmio stale data:           Not affected
Vulnerability Old microcode:             Not affected
Vulnerability Reg file data sampling:    Not affected
Vulnerability Retbleed:                  Mitigation; untrained return thunk; SMT enabled with STIBP protection
Vulnerability Spec rstack overflow:      Mitigation; Safe RET
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; Retpolines; IBPB conditional; STIBP always-on; RSB filling; PBRSB-eIBRS Not affected; BHI Not affected
Vulnerability Srbds:                     Not affected
Vulnerability Tsa:                       Not affected
Vulnerability Tsx async abort:           Not affected
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 mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc cpuid extd_apicid aperfmperf rapl pni pclmulqdq monitor ssse3 fma cx16 sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx f16c rdrand lahf_lm cmp_legacy svm extapic cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw ibs skinit wdt tce topoext perfctr_core perfctr_nb bpext perfctr_llc mwaitx cpb cat_l3 cdp_l3 hw_pstate ssbd mba ibrs ibpb stibp vmmcall fsgsbase bmi1 avx2 smep bmi2 cqm rdt_a rdseed adx smap clflushopt clwb sha_ni xsaveopt xsavec xgetbv1 xsaves cqm_llc cqm_occup_llc cqm_mbm_total cqm_mbm_local clzero irperf xsaveerptr rdpru wbnoinvd amd_ppin arat npt lbrv svm_lock nrip_save tsc_scale vmcb_clean flushbyasid decodeassists pausefilter pfthreshold avic v_vmsave_vmload vgif v_spec_ctrl umip rdpid overflow_recov succor smca sev sev_es

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

@SteveBronder
SteveBronder added this pull request to stack #3458 October 14, 2026 19:39

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

numerics Numerical issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

log1p_exp() for logistic_lcdf() and logistic_lccdf()

5 participants