Skip to content

⚡️ Speed up method DiagonalGridSearchOptimizer.grid_move by 108% #66

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

misrasaurabh1
Copy link

📄 108% (1.08x) speedup for DiagonalGridSearchOptimizer.grid_move in src/gradient_free_optimizers/optimizers/grid/diagonal_grid_search.py

⏱️ Runtime : 5.84 milliseconds 2.81 milliseconds (best of 55 runs)

📝 Explanation and details

To optimize the given DiagonalGridSearchOptimizer implementation, we can focus on improving the performance of the grid_move method by avoiding repeated calls to np.prod which is computationally expensive if repeatedly used. Additionally, we can use Python's integer arithmetic to achieve our requirements more efficiently. Below is the optimized code.

Explanation of Optimizations.

  1. Precompute cumulative products: The cumulative product of dimensions (cumprod_dims) is computed only once, and in reverse order. This helps in avoiding repeated computation via np.prod, making the process faster.
  2. Use of divmod: The divmod function replaces the need to use division and remainder operations separately, thus making the operations more efficient.
  3. Avoid recursive slicing of lists: By precomputing the cumulative products, we avoid multiple slicing operations within the loop, which can be expensive.

This optimization primarily focuses on improving the efficiency of the grid_move function which is the core logic for this optimizer.

Correctness verification report:

Test Status
⚙️ Existing Unit Tests 🔘 None Found
🌀 Generated Regression Tests 1028 Passed
⏪ Replay Tests 🔘 None Found
🔎 Concolic Coverage Tests 🔘 None Found
📊 Tests Coverage 100.0%
🌀 Generated Regression Tests Details
import numpy as np
# imports
import pytest  # used for our unit tests
from gradient_free_optimizers.optimizers.base_optimizer import BaseOptimizer
from gradient_free_optimizers.optimizers.core_optimizer import CoreOptimizer
from gradient_free_optimizers.optimizers.grid.diagonal_grid_search import \
    DiagonalGridSearchOptimizer

# Author: Simon Blanke
# Email: simon.blanke@yahoo.com
# License: MIT License




class BaseOptimizer(CoreOptimizer):
    def __init__(
        self,
        search_space,
        initialize={"grid": 4, "random": 2, "vertices": 4},
        constraints=[],
        random_state=None,
        rand_rest_p=0,
        nth_process=None,
    ):
        super().__init__(
            search_space=search_space,
            initialize=initialize,
            constraints=constraints,
            random_state=random_state,
            rand_rest_p=rand_rest_p,
            nth_process=nth_process,
        )

        self.optimizers = [self]


# unit tests

# Mock the necessary parts of the optimizer
class MockConv:
    def __init__(self, dim_sizes):
        self.dim_sizes = dim_sizes
        self.n_dimensions = len(dim_sizes)

class MockOptimizer(DiagonalGridSearchOptimizer):
    def __init__(self, dim_sizes, high_dim_pointer):
        self.conv = MockConv(dim_sizes)
        self.high_dim_pointer = high_dim_pointer

# Basic Functionality
def test_basic_single_dimension():
    optimizer = MockOptimizer([10], 3)

def test_basic_multiple_dimensions():
    optimizer = MockOptimizer([3, 3], 4)

# Edge Cases


def test_high_dimensionality():
    optimizer = MockOptimizer([10] * 100, 123456789)
    codeflash_output = optimizer.grid_move(); result = codeflash_output


def test_random_pointers_fixed_dimensions():
    dim_sizes = [10, 10, 10]
    pointer = np.random.randint(0, 1000)
    optimizer = MockOptimizer(dim_sizes, pointer)
    codeflash_output = optimizer.grid_move(); result = codeflash_output

def test_random_dimension_sizes():
    dim_sizes = [np.random.randint(1, 10) for _ in range(10)]
    pointer = np.random.randint(0, np.prod(dim_sizes))
    optimizer = MockOptimizer(dim_sizes, pointer)
    codeflash_output = optimizer.grid_move(); result = codeflash_output

# Degenerate Cases
def test_single_element_each_dimension():
    optimizer = MockOptimizer([1, 1, 1], 0)

def test_all_dimensions_one_except_one():
    optimizer = MockOptimizer([1, 1, 1, 10], 5)

# Sequential Pointers
def test_sequential_pointers_fixed_dimensions():
    dim_sizes = [4, 4]
    for pointer in range(16):
        optimizer = MockOptimizer(dim_sizes, pointer)
        codeflash_output = optimizer.grid_move(); result = codeflash_output

def test_sequential_pointers_large_dimensions():
    dim_sizes = [100, 100]
    for pointer in range(1000):
        optimizer = MockOptimizer(dim_sizes, pointer)
        codeflash_output = optimizer.grid_move(); result = codeflash_output

# Performance and Scalability
def test_very_large_dimension_sizes():
    optimizer = MockOptimizer([10000, 10000], 50000000)
    codeflash_output = optimizer.grid_move(); result = codeflash_output

def test_high_dimensionality_large_sizes():
    optimizer = MockOptimizer([100] * 20, 1234567890)
    codeflash_output = optimizer.grid_move(); result = codeflash_output
# codeflash_output is used to check that the output of the original code is the same as that of the optimized code.

import numpy as np
# imports
import pytest  # used for our unit tests
from gradient_free_optimizers.optimizers.base_optimizer import BaseOptimizer
from gradient_free_optimizers.optimizers.core_optimizer import CoreOptimizer
from gradient_free_optimizers.optimizers.grid.diagonal_grid_search import \
    DiagonalGridSearchOptimizer

# Author: Simon Blanke
# Email: simon.blanke@yahoo.com
# License: MIT License

class BaseOptimizer(CoreOptimizer):
    def __init__(
        self,
        search_space,
        initialize={"grid": 4, "random": 2, "vertices": 4},
        constraints=[],
        random_state=None,
        rand_rest_p=0,
        nth_process=None,
    ):
        super().__init__(
            search_space=search_space,
            initialize=initialize,
            constraints=constraints,
            random_state=random_state,
            rand_rest_p=rand_rest_p,
            nth_process=nth_process,
        )

        self.optimizers = [self]

# unit tests

# Basic Functionality Tests



















from gradient_free_optimizers.optimizers.grid.diagonal_grid_search import DiagonalGridSearchOptimizer

To edit these changes git checkout codeflash/optimize-DiagonalGridSearchOptimizer.grid_move-m8gnxbqn and push.

Codeflash

codeflash-ai bot and others added 2 commits March 20, 2025 01:18
To optimize the given `DiagonalGridSearchOptimizer` implementation, we can focus on improving the performance of the `grid_move` method by avoiding repeated calls to `np.prod` which is computationally expensive if repeatedly used. Additionally, we can use Python's integer arithmetic to achieve our requirements more efficiently. Below is the optimized code.



### Explanation of Optimizations.
1. **Precompute cumulative products:** The cumulative product of dimensions (`cumprod_dims`) is computed only once, and in reverse order. This helps in avoiding repeated computation via `np.prod`, making the process faster.
2. **Use of `divmod`:** The `divmod` function replaces the need to use division and remainder operations separately, thus making the operations more efficient.
3. **Avoid recursive slicing of lists:** By precomputing the cumulative products, we avoid multiple slicing operations within the loop, which can be expensive.

This optimization primarily focuses on improving the efficiency of the `grid_move` function which is the core logic for this optimizer.
@misrasaurabh1
Copy link
Author

Hi, can I help in any way with moving forward with merging this optimization?

@SimonBlanke
Copy link
Owner

Could you provide measurements of the speedup in a realistic example? You could use a test-function for this.

@misrasaurabh1
Copy link
Author

HI @SimonBlanke , the performance was measured with the set of examples that are attached in the "Generated Regression Tests Details" in the PR description.

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.

2 participants