From 10d7875dfae067eca94511bbc6492ac411ec4e46 Mon Sep 17 00:00:00 2001 From: Mladen Kolar Date: Thu, 22 Oct 2026 23:45:19 +0400 Subject: [PATCH] Skip the cache update when a coordinate does not move, version 0.2.2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The coordinate steps of CDInverseKroneckerLoss and CDInverseReducedSymKroneckerLoss updated the p × p cache A = Σx Θ Σy after every visit, even when the coordinate did not change, as for most coordinates that stay at zero in a full pass: each visit cost O(p²), a full pass over the p² (or p(p+1)/2) coordinates O(p⁴). They now return early when the change is zero, as CovSel's CDDirectDifferenceLoss does. The iterates are bitwise unchanged. On AR(1) data with n = 500 and one BLAS thread, invQSymHessian is 3.4×, 8.4× and 18× faster at p = 30, 50 and 80, and estimate(SymmetricNormal) 1.2-1.6×. The two coordinate descent solves in invAsymHessianEstimation are 17× faster at p = 50 and 80× at p = 80, but the function only 1.2-1.4×, because its weights (_computeVar!, O(n p³) per call) now take nearly all of its time. Co-Authored-By: Claude Opus 5.5 --- Project.toml | 2 +- src/invHessianEstimationASym.jl | 4 ++++ src/invHessianEstimationSymReduced.jl | 4 ++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 580dfca..118f07f 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "DiffPrecTest" uuid = "bb4bfe13-bfd7-5c6f-a2d2-8072376c6806" authors = ["Mladen Kolar "] -version = "0.2.1" +version = "0.2.2" [deps] CoordinateDescent = "c00ed354-b9be-54b8-8a23-c5ac771bc43a" diff --git a/src/invHessianEstimationASym.jl b/src/invHessianEstimationASym.jl index 74a9bd5..1a59943 100644 --- a/src/invHessianEstimationASym.jl +++ b/src/invHessianEstimationASym.jl @@ -93,6 +93,10 @@ function CoordinateDescent.descendCoordinate!( newVal = cdprox!(g, x, j, a) h = newVal - oldVal + # nothing to update when the coordinate did not move, as for most + # coordinates that stay at zero in a full pass + iszero(h) && return h + # update internals for ac=1:p, ar=1:p @inbounds A[ar, ac] += h * Σx[ar, ri] * Σy[ci, ac] diff --git a/src/invHessianEstimationSymReduced.jl b/src/invHessianEstimationSymReduced.jl index aba500f..2683a43 100644 --- a/src/invHessianEstimationSymReduced.jl +++ b/src/invHessianEstimationSymReduced.jl @@ -123,6 +123,10 @@ function CoordinateDescent.descendCoordinate!( newVal = cdprox!(g, x, j, a) h = newVal - oldVal + # nothing to update when the coordinate did not move, as for most + # coordinates that stay at zero in a full pass + iszero(h) && return h + # update internals if ri == ci for ac=1:p, ar=1:p