Add _prev_waiting_trial_number in InMemoryStorage to improve the efficiency of _pop_waiting_trial_id#5993
Conversation
Performance ImprovementThis change improves performance by reducing the overhead of fetching all trials. Below are benchmark results comparing the current master branch. Here is the code used to generate the results above |
|
@not522 Could you review this PR? |
_prev_waiting_trial_number in InMemoryStorage to improve the efficiency of pop_waiting_trials
|
Let me show you the performance improvement with various examples. |
Performance ImprovementBelow are benchmark results comparing the performance before and after this PR using different scenarios. 1.
|
percall (cumtime / ncalls) of pop_waiting_trials |
Before (master) | After (PR) |
|---|---|---|
| n_trials = 100 | 0.000066482 ± 0.00002 | 0.000034141 ± 0.000007 |
| n_trials = 1000 | 0.000241295 ± 0.00001 | 0.0000334922 ± 0.000004 |
| n_trials = 10000 | 0.0024929083 | 0.0000391722 |
This PR significantly improves performance because _get_all_trials(state=TrialState.WAITING) now only checks the last trial's state instead of iterating over all trials.
Here is the code used to generate this data.
import optuna
import cProfile
study = optuna.create_study()
def objective(trial):
x = trial.suggest_uniform("x", -10, 10)
return x**2
def profile_objective():
study.optimize(objective, n_trials=num_of_trials)
profiller = cProfile.Profile()
profiller.run('profile_objective()')
2. study.enqueue_trial() followed by study.optimize()
percall (cumtime / ncalls) of pop_waiting_trials |
Before (master) | After (PR) |
|---|---|---|
| # of enqueue trials = 10 | 0.0002664 ± 0.0004 | 0.0001398 ± 0.00004 |
| # of enqueue trials = 100 | 0.000206 ± 0.00007 | 0.0003954 ± 0.0002 |
| # of enqueue trials = 1000 | 0.0007885 ± 0.0008 | 0.0010906 ± 0.0001 |
I was not really sure why this test generates some difference.
Here is the code used to generate this data.
import optuna
import cProfile
study = optuna.create_study()
def objective(trial):
x = trial.suggest_uniform("x", -10, 10)
return x**2
for i in range(-num_of_waiting_trials // 2, num_of_waiting_trials // 2):
study.enqueue_trial({"x": i})
def profile_objective():
study.optimize(objective, n_trials=1)
profiller = cProfile.Profile()
profiller.run('profile_objective()')
3. study.optimize() for n_trials = 500, followed by study.enqueue_trial() for 100 trials, then study.optimize(n_trials=1), profiled with cProfile
percall (cumtime / ncalls) of pop_waiting_trials |
Before (master) | After (PR) |
|---|---|---|
| 0.0006159 ± 0.0003 | 0.0004844 ± 0.0003 |
The performance improvement comes from optimizing the logic: previously, the function checked all 500 + 100 trials, whereas the new implementation only checks 100 trials.
Here is the code used to generate this data.
import optuna
import cProfile
study = optuna.create_study()
def objective(trial):
x = trial.suggest_uniform("x", -10, 10)
return x**2
study.optimize(objective, n_trials=500)
for i in range(-50, 50):
study.enqueue_trial({"x": i})
def profile_objective():
study.optimize(objective, n_trials=1)
profiller = cProfile.Profile()
profiller.run('profile_objective()')
Benchmarking Details
- Each test, except for the one with
n_trials= 10,000, was conducted 10 times, alternating between the master branch and the PR branch in every iteration (i.e.,master → PR → master → PR → ...). - The average and standard deviation were computed.
- Raw data is available here.
|
Could you share benchmarks with larger |
|
Sure. But let me do it with n_trials = 10,000 and for a single iteration since my PC isn't powerful enough and doing optimization with larger number of n_trials needs significant amount of time |
|
@not522 I added the data to the comment above. The improvement is significant—total execution time for |
not522
left a comment
There was a problem hiding this comment.
Thank you for your update! LGTM!
_prev_waiting_trial_number in InMemoryStorage to improve the efficiency of pop_waiting_trials_prev_waiting_trial_number in InMemoryStorage to improve the efficiency of _pop_waiting_trial_id


Motivation
Description of the changes
_prev_waiting_trial_idin InMemoryStorage to improve efficiency ofget_all_trials(states = (TrialState.WAITING)).