Skip to content

incrementally sync generation cache from storage - #237

Draft
yen-0 wants to merge 1 commit into
optuna:mainfrom
yen-0:feature/nsgaii_incremental_indexing
Draft

incrementally sync generation cache from storage#237
yen-0 wants to merge 1 commit into
optuna:mainfrom
yen-0:feature/nsgaii_incremental_indexing

Conversation

@yen-0

@yen-0 yen-0 commented Aug 28, 2026

Copy link
Copy Markdown
Collaborator

Motivation

  • Optimize performance by avoiding full historical trial scans when fetching generation indexes.
  • Ensure accurate tracking and synchronization of in-flight (Running/Waiting) trials from concurrent workers.

Description of Changes

  • GenerationIndexCache Added: Encapsulated generation_to_numbers, unfinished_trial_numbers (HashSet), and unseen_trial_start behind #[derive(Default)].
  • Incremental Sync (sync_generation_cache): Updated logic to process only new trials from unseen_trial_start, re-check incomplete trials, and reset when the trial list shrinks.
  • Testing: Added unit tests verifying newly appended trials, re-checked unfinished trials, and cache reset handling.

Co-authored-by: Hemmi Shinichi <shemmi@preferred.jp>
@yen-0
yen-0 force-pushed the feature/nsgaii_incremental_indexing branch from 74418b1 to 68b71c0 Compare August 28, 2026 03:38
@c-bata

c-bata commented Aug 28, 2026

Copy link
Copy Markdown
Member

Thank you for your pull request. I executed the following benchmark, but I cannot see a huge improvement with this PR. Do you have any thoughts on why that might be?

Benchmark scripts

import itertools
import time
import optunahub
import rustuna
from rustuna.converter import to_rustuna_directions

wfg = optunahub.load_module("benchmarks/wfg")


def run_optimize(problem, n_trials):
    sampler = rustuna.samplers.NSGAIISampler(seed=1)

    def objective(trial):
        params = {
            name: trial.suggest_float(name, dist.low, dist.high)
            for name, dist in problem.search_space.items()
        }
        value = problem.evaluate(params)
        return list(value)

    directions = [d.name.lower() for d in problem.directions]
    study = rustuna.create_study(sampler=sampler, directions=directions)
    study.optimize(objective, n_trials=n_trials)
    return study


def _valid_wfg_k(dimension: int, n_objectives: int = 2) -> int:
    """A k valid for the whole WFG suite: k<dim, k%(M-1)==0, (dim-k) even."""
    base = 2 * (n_objectives - 1)
    for k in [base, base - 1, base + 1, 1, 2, 3, 4]:
        if k < 1 or k >= dimension:
            continue
        if (n_objectives > 1) and (k % (n_objectives - 1) != 0):
            continue
        try:
            wfg.Problem(function_id=4, n_objectives=n_objectives, dimension=dimension, k=k)
            return k
        except AssertionError:
            continue
    raise ValueError(f"no valid k for dimension={dimension}")


def main():
    for n_trials, n_params in itertools.product([1000, 10000, 100000], [40]):
        k = _valid_wfg_k(n_params, 2)
        problem = wfg.Problem(function_id=4, n_objectives=2, dimension=n_params, k=k)
        start = time.time()
        rustuna_study = run_optimize(problem, n_trials)
        elapsed_rustuna = time.time() - start
        print(f"Rustuna\t{n_trials=}\telapsed={elapsed_rustuna:.3f}")
        assert len(rustuna_study.get_trials(states=[rustuna.trial.TrialState.COMPLETE])) == n_trials

if __name__ == "__main__":
    main()

main branch

% python ./bench_ngaii.py
Rustuna n_trials=1000   elapsed=0.057
Rustuna n_trials=10000  elapsed=1.617
Rustuna n_trials=100000 elapsed=128.034

This PR

% python ./bench_ngaii.py
Rustuna n_trials=1000   elapsed=0.056
Rustuna n_trials=10000  elapsed=1.497
Rustuna n_trials=100000 elapsed=123.207

PR #179 (4d9b3c5)

% python ../tmp/bench_ngaii.py
Rustuna n_trials=1000   elapsed=0.050
Rustuna n_trials=10000  elapsed=0.537
Rustuna n_trials=100000 elapsed=7.878

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.

4 participants