Skip to content

⚡️ Speed up function any_symbolic_tensors by 5%#23

Open
codeflash-ai[bot] wants to merge 1 commit intomasterfrom
codeflash/optimize-any_symbolic_tensors-maxqa9k3
Open

⚡️ Speed up function any_symbolic_tensors by 5%#23
codeflash-ai[bot] wants to merge 1 commit intomasterfrom
codeflash/optimize-any_symbolic_tensors-maxqa9k3

Conversation

@codeflash-ai
Copy link
Copy Markdown

@codeflash-ai codeflash-ai bot commented May 21, 2025

📄 5% (0.05x) speedup for any_symbolic_tensors in keras/src/backend/common/keras_tensor.py

⏱️ Runtime : 3.04 milliseconds 2.89 milliseconds (best of 260 runs)

📝 Explanation and details

Here is an optimized version of your Python program, reducing runtime by.

  • Directly using tree.flatten in any_symbolic_tensors instead of the indirect tree_impl, eliminating a Python function call per iteration.
  • Inlining fast default arg assignment to minimize unnecessary allocations (by checking for None before assignment).
  • Avoiding redundant tuple creation: Only create a tuple if both args and kwargs are actually provided.
  • Your flatten() function is essentially a wrapper and already efficient, but we retain it as required, directly calling the leaf-efficient backend.

No external dependencies or behavior changes. All docstrings and signatures preserved.

Key optimizations:

  • Short-circuits the common case (nothing passed).
  • Minimizes creation of unnecessary tuples and dictionaries.
  • Uses the fastest available flatten implementation by going through tree.flatten.
  • Preserves exactly the same observable return values and semantics.

Correctness verification report:

Test Status
⚙️ Existing Unit Tests 🔘 None Found
🌀 Generated Regression Tests 77 Passed
⏪ Replay Tests 🔘 None Found
🔎 Concolic Coverage Tests 🔘 None Found
📊 Tests Coverage 83.3%
🌀 Generated Regression Tests Details
from collections import OrderedDict

# imports
import pytest  # used for our unit tests
from keras.src.backend.common.keras_tensor import any_symbolic_tensors


# Dummy KerasTensor class for testing
class KerasTensor:
    def __init__(self, value=None):
        self.value = value
from keras.src.backend.common.keras_tensor import any_symbolic_tensors

# ---------------------
# Unit Tests
# ---------------------

# 1. Basic Test Cases

def test_empty_args_and_kwargs():
    # Both args and kwargs are empty
    codeflash_output = not any_symbolic_tensors()

def test_args_with_no_keras_tensor():
    # Args contains only ints and strings
    codeflash_output = not any_symbolic_tensors(args=(1, 2, 'a', None))

def test_kwargs_with_no_keras_tensor():
    # Kwargs contains only floats and lists
    codeflash_output = not any_symbolic_tensors(kwargs={'x': 3.0, 'y': [1, 2]})

def test_args_with_keras_tensor():
    # Args contains a KerasTensor
    kt = KerasTensor(5)
    codeflash_output = any_symbolic_tensors(args=(1, kt, 3))

def test_kwargs_with_keras_tensor():
    # Kwargs contains a KerasTensor
    kt = KerasTensor('foo')
    codeflash_output = any_symbolic_tensors(kwargs={'a': 1, 'b': kt})

def test_args_and_kwargs_with_keras_tensor():
    # Both args and kwargs contain KerasTensor
    kt1 = KerasTensor(1)
    kt2 = KerasTensor(2)
    codeflash_output = any_symbolic_tensors(args=(kt1,), kwargs={'x': kt2})

def test_nested_in_list():
    # KerasTensor is nested in a list inside args
    kt = KerasTensor(7)
    codeflash_output = any_symbolic_tensors(args=([1, [kt]],))

def test_nested_in_tuple():
    # KerasTensor is nested in a tuple inside kwargs
    kt = KerasTensor(8)
    codeflash_output = any_symbolic_tensors(kwargs={'x': (1, (kt,))})

def test_nested_in_dict():
    # KerasTensor is nested in a dict inside args
    kt = KerasTensor(9)
    codeflash_output = any_symbolic_tensors(args=({'a': {'b': kt}},))

def test_nested_in_ordereddict():
    # KerasTensor is nested in an OrderedDict in kwargs
    kt = KerasTensor(10)
    od = OrderedDict([('first', 1), ('second', kt)])
    codeflash_output = any_symbolic_tensors(kwargs={'od': od})

# 2. Edge Test Cases

def test_args_is_none():
    # args is None, kwargs is not
    codeflash_output = not any_symbolic_tensors(args=None, kwargs={'a': 1})

def test_kwargs_is_none():
    # kwargs is None, args is not
    codeflash_output = not any_symbolic_tensors(args=(1, 2), kwargs=None)

def test_both_none():
    # Both args and kwargs are None
    codeflash_output = not any_symbolic_tensors(args=None, kwargs=None)

def test_empty_tuple_and_dict():
    # Args is empty tuple, kwargs is empty dict
    codeflash_output = not any_symbolic_tensors(args=(), kwargs={})

def test_empty_list_and_dict():
    # Args is empty list, kwargs is empty dict
    codeflash_output = not any_symbolic_tensors(args=[], kwargs={})


def test_non_iterable_non_keras_tensor():
    # Args is a single non-iterable, non-KerasTensor
    codeflash_output = not any_symbolic_tensors(args=5)

def test_non_iterable_keras_tensor():
    # Args is a single KerasTensor
    kt = KerasTensor(11)
    codeflash_output = any_symbolic_tensors(args=kt)

def test_kwargs_with_none_value():
    # Kwargs contains None value
    codeflash_output = not any_symbolic_tensors(kwargs={'a': None})

def test_args_with_multiple_types():
    # Args contains mixed types including a nested KerasTensor
    kt = KerasTensor(12)
    codeflash_output = any_symbolic_tensors(args=(1, 'a', [None, (3.14, kt)]))

def test_kwargs_with_multiple_types():
    # Kwargs contains mixed types including a nested KerasTensor
    kt = KerasTensor(13)
    codeflash_output = any_symbolic_tensors(kwargs={'x': {'y': [0, kt]}})

def test_args_with_empty_dict():
    # Args contains an empty dict
    codeflash_output = not any_symbolic_tensors(args=({},))

def test_kwargs_with_empty_list():
    # Kwargs contains an empty list
    codeflash_output = not any_symbolic_tensors(kwargs={'x': []})

def test_args_with_falsey_values():
    # Args contains falsey values (0, '', False, None)
    codeflash_output = not any_symbolic_tensors(args=(0, '', False, None))

def test_kwargs_with_falsey_values():
    # Kwargs contains falsey values (0, '', False, None)
    codeflash_output = not any_symbolic_tensors(kwargs={'a': 0, 'b': '', 'c': False, 'd': None})

def test_args_with_multiple_keras_tensors():
    # Args contains multiple KerasTensors
    kt1 = KerasTensor(14)
    kt2 = KerasTensor(15)
    codeflash_output = any_symbolic_tensors(args=(kt1, kt2))

def test_kwargs_with_multiple_keras_tensors():
    # Kwargs contains multiple KerasTensors
    kt1 = KerasTensor(16)
    kt2 = KerasTensor(17)
    codeflash_output = any_symbolic_tensors(kwargs={'a': kt1, 'b': kt2})

def test_args_and_kwargs_with_multiple_keras_tensors():
    # Both args and kwargs contain multiple KerasTensors
    kt1 = KerasTensor(18)
    kt2 = KerasTensor(19)
    codeflash_output = any_symbolic_tensors(args=(kt1,), kwargs={'a': kt2})

def test_args_with_generator():
    # Args is a generator that yields a KerasTensor
    kt = KerasTensor(20)
    def gen():
        yield 1
        yield kt
        yield 3
    codeflash_output = any_symbolic_tensors(args=tuple(gen()))

def test_kwargs_with_ordereddict():
    # Kwargs is an OrderedDict with KerasTensor
    kt = KerasTensor(21)
    od = OrderedDict([('a', 1), ('b', kt)])
    codeflash_output = any_symbolic_tensors(kwargs=od)

# 3. Large Scale Test Cases

def test_large_args_no_keras_tensor():
    # Large args tuple, no KerasTensor
    large_args = tuple(range(1000))
    codeflash_output = not any_symbolic_tensors(args=large_args)

def test_large_args_with_keras_tensor_at_start():
    # Large args tuple, KerasTensor at start
    kt = KerasTensor(22)
    large_args = (kt,) + tuple(range(999))
    codeflash_output = any_symbolic_tensors(args=large_args)

def test_large_args_with_keras_tensor_at_end():
    # Large args tuple, KerasTensor at end
    kt = KerasTensor(23)
    large_args = tuple(range(999)) + (kt,)
    codeflash_output = any_symbolic_tensors(args=large_args)

def test_large_args_with_keras_tensor_in_middle():
    # Large args tuple, KerasTensor in the middle
    kt = KerasTensor(24)
    large_args = tuple(range(500)) + (kt,) + tuple(range(499))
    codeflash_output = any_symbolic_tensors(args=large_args)

def test_large_nested_structure_with_keras_tensor():
    # Deeply nested structure, KerasTensor deeply nested
    kt = KerasTensor(25)
    nested = [ [ [ [i for i in range(10)] for _ in range(10)] for _ in range(5)] for _ in range(2)]
    # Insert KerasTensor deep inside
    nested[1][4][9][9] = kt
    codeflash_output = any_symbolic_tensors(args=(nested,))

def test_large_kwargs_no_keras_tensor():
    # Large kwargs dict, no KerasTensor
    large_kwargs = {f'key{i}': i for i in range(1000)}
    codeflash_output = not any_symbolic_tensors(kwargs=large_kwargs)

def test_large_kwargs_with_keras_tensor():
    # Large kwargs dict, KerasTensor at a random key
    kt = KerasTensor(26)
    large_kwargs = {f'key{i}': i for i in range(999)}
    large_kwargs['special'] = kt
    codeflash_output = any_symbolic_tensors(kwargs=large_kwargs)

def test_large_args_and_kwargs_with_keras_tensor():
    # Large args and kwargs, KerasTensor in both
    kt1 = KerasTensor(27)
    kt2 = KerasTensor(28)
    large_args = tuple(range(500)) + (kt1,) + tuple(range(499))
    large_kwargs = {f'key{i}': i for i in range(999)}
    large_kwargs['another'] = kt2
    codeflash_output = any_symbolic_tensors(args=large_args, kwargs=large_kwargs)

def test_large_structure_all_keras_tensors():
    # All elements are KerasTensors
    large_args = tuple(KerasTensor(i) for i in range(1000))
    codeflash_output = any_symbolic_tensors(args=large_args)

def test_large_structure_no_keras_tensor():
    # Large nested structure, no KerasTensor
    nested = [ [ [ [i for i in range(10)] for _ in range(10)] for _ in range(5)] for _ in range(2)]
    codeflash_output = not any_symbolic_tensors(args=(nested,))
# codeflash_output is used to check that the output of the original code is the same as that of the optimized code.

import pytest
from keras.src.backend.common.keras_tensor import any_symbolic_tensors


# Dummy KerasTensor class for testing purposes
class KerasTensor:
    def __init__(self, value=None):
        self.value = value
from keras.src.backend.common.keras_tensor import any_symbolic_tensors

# ----------------------------
# Basic Test Cases
# ----------------------------

def test_empty_args_and_kwargs():
    # Both args and kwargs are empty
    codeflash_output = any_symbolic_tensors()
    codeflash_output = any_symbolic_tensors(())
    codeflash_output = any_symbolic_tensors([], {})

def test_args_with_no_symbolic():
    # Only plain types in args
    codeflash_output = any_symbolic_tensors(args=(1, 2, 3))
    codeflash_output = any_symbolic_tensors(args=["a", "b", None])

def test_kwargs_with_no_symbolic():
    # Only plain types in kwargs
    codeflash_output = any_symbolic_tensors(kwargs={"a": 1, "b": 2})
    codeflash_output = any_symbolic_tensors(kwargs={"foo": None})

def test_args_with_symbolic():
    # One KerasTensor in args
    kt = KerasTensor()
    codeflash_output = any_symbolic_tensors(args=(1, kt, 3))
    codeflash_output = any_symbolic_tensors(args=(kt,))

def test_kwargs_with_symbolic():
    # One KerasTensor in kwargs
    kt = KerasTensor()
    codeflash_output = any_symbolic_tensors(kwargs={"a": kt, "b": 2})
    codeflash_output = any_symbolic_tensors(kwargs={"foo": kt})

def test_args_and_kwargs_with_symbolic():
    # KerasTensor in both args and kwargs
    kt1 = KerasTensor()
    kt2 = KerasTensor()
    codeflash_output = any_symbolic_tensors(args=(kt1,), kwargs={"a": kt2})

def test_args_and_kwargs_without_symbolic():
    # No KerasTensor in either args or kwargs
    codeflash_output = any_symbolic_tensors(args=(1, 2), kwargs={"a": "b"})

# ----------------------------
# Edge Test Cases
# ----------------------------

def test_none_args_and_kwargs():
    # Explicit None for both
    codeflash_output = any_symbolic_tensors(args=None, kwargs=None)

def test_nested_structures_with_symbolic():
    # Nested lists/tuples/dicts containing KerasTensor
    kt = KerasTensor()
    codeflash_output = any_symbolic_tensors(args=([1, [2, (3, kt)]],))
    codeflash_output = any_symbolic_tensors(kwargs={"a": {"b": [kt]}})
    codeflash_output = any_symbolic_tensors(args=(((1, 2), [3, [4, kt]]),))

def test_nested_structures_without_symbolic():
    # Nested lists/tuples/dicts without KerasTensor
    codeflash_output = any_symbolic_tensors(args=([1, [2, (3, 4)]],))
    codeflash_output = any_symbolic_tensors(kwargs={"a": {"b": [5]}})
    codeflash_output = any_symbolic_tensors(args=(((1, 2), [3, [4, 5]]),))

def test_args_and_kwargs_are_scalars():
    # Single scalar as args or kwargs
    codeflash_output = any_symbolic_tensors(args=1)
    codeflash_output = any_symbolic_tensors(kwargs=2)

def test_args_and_kwargs_are_none():
    # None as args or kwargs
    codeflash_output = any_symbolic_tensors(args=None)
    codeflash_output = any_symbolic_tensors(kwargs=None)

def test_mixed_types_in_args_and_kwargs():
    # Mixture of types, including KerasTensor
    kt = KerasTensor()
    codeflash_output = any_symbolic_tensors(args=(1, "a", [None, kt, 3.5]))
    codeflash_output = any_symbolic_tensors(kwargs={"a": [1, 2], "b": (kt,)})


def test_multiple_keras_tensors():
    # Multiple KerasTensors in various places
    kt1 = KerasTensor()
    kt2 = KerasTensor()
    codeflash_output = any_symbolic_tensors(args=(kt1, [kt2]))

def test_falsey_values():
    # Falsey values in args/kwargs (0, False, '', etc.)
    codeflash_output = any_symbolic_tensors(args=(0, False, '', [], {}, None))

# ----------------------------
# Large Scale Test Cases
# ----------------------------

def test_large_args_no_symbolic():
    # Large list of non-KerasTensor objects
    large_list = [i for i in range(1000)]
    codeflash_output = any_symbolic_tensors(args=large_list)

def test_large_args_with_symbolic_at_start():
    # Large list, KerasTensor at the start
    kt = KerasTensor()
    large_list = [kt] + [i for i in range(999)]
    codeflash_output = any_symbolic_tensors(args=large_list)

def test_large_args_with_symbolic_at_end():
    # Large list, KerasTensor at the end
    kt = KerasTensor()
    large_list = [i for i in range(999)] + [kt]
    codeflash_output = any_symbolic_tensors(args=large_list)

def test_large_args_with_symbolic_in_middle():
    # Large list, KerasTensor in the middle
    kt = KerasTensor()
    large_list = [i for i in range(500)] + [kt] + [i for i in range(499)]
    codeflash_output = any_symbolic_tensors(args=large_list)

def test_large_nested_structure_with_symbolic():
    # Deeply nested structure, KerasTensor buried inside
    kt = KerasTensor()
    nested = [ [ [ [ [ [kt] ] ] ] ] ]  # 6 levels deep
    codeflash_output = any_symbolic_tensors(args=nested)

def test_large_kwargs_with_symbolic():
    # Large dict, KerasTensor as one of the values
    kt = KerasTensor()
    large_dict = {str(i): i for i in range(999)}
    large_dict["symbolic"] = kt
    codeflash_output = any_symbolic_tensors(kwargs=large_dict)

def test_large_kwargs_no_symbolic():
    # Large dict, no KerasTensor
    large_dict = {str(i): i for i in range(1000)}
    codeflash_output = any_symbolic_tensors(kwargs=large_dict)

def test_large_combined_args_and_kwargs():
    # Both args and kwargs are large, only one KerasTensor present
    kt = KerasTensor()
    large_args = [i for i in range(500)]
    large_kwargs = {str(i): i for i in range(499)}
    large_args.append(kt)
    codeflash_output = any_symbolic_tensors(args=large_args, kwargs=large_kwargs)

def test_large_combined_args_and_kwargs_no_symbolic():
    # Both args and kwargs are large, no KerasTensor
    large_args = [i for i in range(500)]
    large_kwargs = {str(i): i for i in range(499)}
    codeflash_output = any_symbolic_tensors(args=large_args, kwargs=large_kwargs)
# codeflash_output is used to check that the output of the original code is the same as that of the optimized code.

To edit these changes git checkout codeflash/optimize-any_symbolic_tensors-maxqa9k3 and push.

Codeflash

Here is an optimized version of your Python program, reducing runtime by.

- **Directly using `tree.flatten`** in `any_symbolic_tensors` instead of the indirect `tree_impl`, eliminating a Python function call per iteration.
- **Inlining fast default arg assignment** to minimize unnecessary allocations (by checking for `None` before assignment).
- **Avoiding redundant tuple creation:** Only create a tuple if both `args` and `kwargs` are actually provided.
- Your `flatten()` function is essentially a wrapper and already efficient, but we retain it as required, directly calling the leaf-efficient backend.

**No external dependencies or behavior changes. All docstrings and signatures preserved.**



**Key optimizations:**
- Short-circuits the common case (nothing passed).
- Minimizes creation of unnecessary tuples and dictionaries.
- Uses the fastest available flatten implementation by going through `tree.flatten`.
- Preserves exactly the same observable return values and semantics.
@codeflash-ai codeflash-ai bot added the ⚡️ codeflash Optimization PR opened by Codeflash AI label May 21, 2025
@codeflash-ai codeflash-ai bot requested a review from HeshamHM28 May 21, 2025 09:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

⚡️ codeflash Optimization PR opened by Codeflash AI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants