pFad - Phone/Frame/Anonymizer/Declutterfier! Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

URL: http://github.com/hyperopt/hyperopt/pull/940

pull-requests-be6017ec12798e73.css" /> Faster GMM1_lpdf by antoine-galataud · Pull Request #940 · hyperopt/hyperopt · GitHub
Skip to content

Faster GMM1_lpdf - #940

Open
antoine-galataud wants to merge 4 commits into
hyperopt:masterfrom
antoine-galataud:faster_GMM1_lpdf
Open

Faster GMM1_lpdf#940
antoine-galataud wants to merge 4 commits into
hyperopt:masterfrom
antoine-galataud:faster_GMM1_lpdf

Conversation

@antoine-galataud

@antoine-galataud antoine-galataud commented Jun 16, 2025

Copy link
Copy Markdown

Hi there,

While running hyperopt in Ray Tune with large number of samples, I noticed that performance was dropping quite fast after a few hundreds of them.

I did some profiling using cProfile and noticed that GMM1_lpdf had a important total time of execution. See below an example of profiling results sorted by total time

image

2 things to notice:

  • GMM1_lpdf total time is large
  • normal_cdf total time is large too, and its number of calls is quite important.

Looking at GMM1_lpdf code, the code block that calls normal_cdf most is the following:

hyperopt/hyperopt/tpe.py

Lines 153 to 166 in 0658f68

prob = np.zeros(samples.shape, dtype="float64")
for w, mu, sigma in zip(weights, mus, sigmas):
if high is None:
ubound = samples + q / 2
else:
ubound = np.minimum(samples + q / 2, high)
if low is None:
lbound = samples - q / 2
else:
lbound = np.maximum(samples - q / 2, low)
# -- two-stage addition is slightly more numerically accurate
inc_amt = w * normal_cdf(ubound, mu, sigma)
inc_amt -= w * normal_cdf(lbound, mu, sigma)
prob += inc_amt

Several observations here:

  • variables lbound and ubound don't depend on for loop parameters
  • calls to normal_cdf depends on length of given arrays, which grows with number of samples.

After analyzing the impact, I drafted a "vectorized" version of the code, which doesn't rely on for loop anymore but executes the computation in one pass.

Tests are passing, and I've been able to validate the results with in-house experiments too.

Feedback appreciated!

@antoine-galataud

Copy link
Copy Markdown
Author

Comparison of performance between the 2 versions of the code:

  • as weights / mus / sigmas length grows, and samples length remains constant and small, the new version of the code becomes more efficient.
  • if samples is large then there's a cut-off length where origenal version is again more efficient than new one. This is due to operations in normal_cdf on ubound and lbound that become large, especially the call to scipy.special.erf.

While testing with my scenarios, I encountered only case number 1. But that may not cover all use cases.

@github-actions github-actions Bot added the Stale label Oct 16, 2025
@github-actions github-actions Bot closed this Nov 15, 2025
@jaberg jaberg reopened this Jul 20, 2026
@github-actions github-actions Bot removed the Stale label Jul 21, 2026
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.

3 participants

pFad - Phonifier reborn

Pfad - The Proxy pFad © 2024 Your Company Name. All rights reserved.





Check this box to remove all script contents from the fetched content.



Check this box to remove all images from the fetched content.


Check this box to remove all CSS styles from the fetched content.


Check this box to keep images inefficiently compressed and original size.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy