Skip to content

Conversation

@codeflash-ai
Copy link

@codeflash-ai codeflash-ai bot commented Nov 12, 2025

📄 103% (1.03x) speedup for T2IAdapterInvocation.validate_ip_adapter_weight in invokeai/app/invocations/t2i_adapter.py

⏱️ Runtime : 451 microseconds 223 microseconds (best of 250 runs)

📝 Explanation and details

The optimization replaces an any() generator expression with min() and max() operations for range validation.

Key Change: Instead of iterating through each weight value with any(i < -1 or i > 2 for i in to_validate), the optimized version uses if min(to_validate) < -1 or max(to_validate) > 2: to check bounds.

Why This is Faster:

  • Reduced function call overhead: The original code calls a comparison function for every element via the generator expression. The optimized version makes only two C-level function calls (min and max) regardless of list size.
  • Better algorithmic efficiency for large lists: For lists with all valid values, both approaches scan the entire list, but min/max are implemented in C and are highly optimized for numerical operations.
  • Short-circuit behavior preserved: If the first element violates bounds, min/max can still exit early in many cases.
  • Empty list handling: Added a guard if to_validate: to avoid calling min/max on empty lists, which provides a 75% speedup for empty lists.

Performance Characteristics:

  • Small lists/single values: 8-37% faster due to reduced Python function call overhead
  • Large valid lists: 200%+ faster due to C-optimized min/max operations
  • Large lists with violations: Mixed results - early violations are detected faster, but lists with violations only at the end may be slightly slower due to full list traversal by max

Impact on Workloads: This validation function is used in T2I-Adapter weight validation during model setup, so the optimization will improve initialization performance, especially when using multiple adapters or large weight arrays.

Correctness verification report:

Test Status
⚙️ Existing Unit Tests 🔘 None Found
🌀 Generated Regression Tests 54 Passed
⏪ Replay Tests 🔘 None Found
🔎 Concolic Coverage Tests 🔘 None Found
📊 Tests Coverage 100.0%
🌀 Generated Regression Tests and Runtime

from typing import Union

imports

import pytest
from invokeai.app.invocations.t2i_adapter import T2IAdapterInvocation

------------------------

Unit Tests for T2IAdapterInvocation.validate_ip_adapter_weight

------------------------

1. Basic Test Cases

def test_single_valid_float_middle_range():
# Test a single float within the valid range
codeflash_output = T2IAdapterInvocation.validate_ip_adapter_weight(1.0) # 1.62μs -> 1.49μs (8.38% faster)

def test_single_valid_float_lower_bound():
# Test a single float at the lower bound
codeflash_output = T2IAdapterInvocation.validate_ip_adapter_weight(-1.0) # 1.54μs -> 1.32μs (16.4% faster)

def test_single_valid_float_upper_bound():
# Test a single float at the upper bound
codeflash_output = T2IAdapterInvocation.validate_ip_adapter_weight(2.0) # 1.43μs -> 1.29μs (11.3% faster)

def test_list_of_valid_floats():
# Test a list of valid floats within the range
weights = [0.0, 1.0, 1.5, -0.5, 2.0, -1.0]
codeflash_output = T2IAdapterInvocation.validate_ip_adapter_weight(weights) # 1.94μs -> 1.44μs (34.9% faster)

def test_list_with_one_value():
# Test a list with a single valid value
weights = [1.0]
codeflash_output = T2IAdapterInvocation.validate_ip_adapter_weight(weights) # 1.34μs -> 1.22μs (9.75% faster)

2. Edge Test Cases

def test_single_float_below_lower_bound():
# Test a single float just below the lower bound
with pytest.raises(ValueError, match="Control weights must be within -1 to 2 range"):
T2IAdapterInvocation.validate_ip_adapter_weight(-1.0001) # 2.20μs -> 1.60μs (37.7% faster)

def test_single_float_above_upper_bound():
# Test a single float just above the upper bound
with pytest.raises(ValueError, match="Control weights must be within -1 to 2 range"):
T2IAdapterInvocation.validate_ip_adapter_weight(2.0001) # 2.13μs -> 1.82μs (17.1% faster)

def test_list_with_value_below_lower_bound():
# Test a list where one value is below the lower bound
weights = [0.0, -1.1, 1.0]
with pytest.raises(ValueError, match="Control weights must be within -1 to 2 range"):
T2IAdapterInvocation.validate_ip_adapter_weight(weights) # 2.27μs -> 1.60μs (41.5% faster)

def test_list_with_value_above_upper_bound():
# Test a list where one value is above the upper bound
weights = [1.0, 2.1, 0.0]
with pytest.raises(ValueError, match="Control weights must be within -1 to 2 range"):
T2IAdapterInvocation.validate_ip_adapter_weight(weights) # 2.18μs -> 1.96μs (11.2% faster)

def test_list_with_multiple_invalid_values():
# Test a list with multiple invalid values (both below and above)
weights = [-1.5, 2.5, 0.0]
with pytest.raises(ValueError, match="Control weights must be within -1 to 2 range"):
T2IAdapterInvocation.validate_ip_adapter_weight(weights) # 2.00μs -> 1.55μs (28.6% faster)

def test_list_with_all_invalid_values():
# Test a list where all values are invalid
weights = [-2.0, 3.0, 2.5]
with pytest.raises(ValueError, match="Control weights must be within -1 to 2 range"):
T2IAdapterInvocation.validate_ip_adapter_weight(weights) # 1.90μs -> 1.56μs (22.0% faster)

def test_empty_list():
# Test an empty list (should not raise, as there are no invalid values)
weights = []
codeflash_output = T2IAdapterInvocation.validate_ip_adapter_weight(weights) # 1.20μs -> 684ns (74.9% faster)

def test_list_with_nan():
# Test a list containing NaN (should not raise ValueError, but could be a hidden bug)
import math
weights = [0.0, math.nan]
# math.nan is not < -1 or > 2, so should not raise, but let's check behavior
codeflash_output = T2IAdapterInvocation.validate_ip_adapter_weight(weights) # 1.67μs -> 1.35μs (23.5% faster)

def test_list_with_inf():
# Test a list containing inf (should raise ValueError)
import math
weights = [0.0, math.inf]
with pytest.raises(ValueError, match="Control weights must be within -1 to 2 range"):
T2IAdapterInvocation.validate_ip_adapter_weight(weights) # 2.20μs -> 1.85μs (19.0% faster)

def test_list_with_negative_inf():
# Test a list containing -inf (should raise ValueError)
import math
weights = [0.0, -math.inf]
with pytest.raises(ValueError, match="Control weights must be within -1 to 2 range"):
T2IAdapterInvocation.validate_ip_adapter_weight(weights) # 2.24μs -> 1.54μs (45.5% faster)

def test_non_numeric_input():
# Test a string input (should raise TypeError)
with pytest.raises(TypeError):
T2IAdapterInvocation.validate_ip_adapter_weight("not a number") # 2.82μs -> 2.37μs (18.7% faster)

def test_list_with_non_numeric():
# Test a list containing a non-numeric value (should raise TypeError)
weights = [1.0, "bad"]
with pytest.raises(TypeError):
T2IAdapterInvocation.validate_ip_adapter_weight(weights) # 2.83μs -> 2.32μs (21.8% faster)

def test_list_with_none():
# Test a list containing None (should raise TypeError)
weights = [1.0, None]
with pytest.raises(TypeError):
T2IAdapterInvocation.validate_ip_adapter_weight(weights) # 2.73μs -> 2.22μs (22.6% faster)

def test_none_input():
# Test None as input (should raise TypeError)
with pytest.raises(TypeError):
T2IAdapterInvocation.validate_ip_adapter_weight(None) # 2.38μs -> 2.16μs (9.94% faster)

3. Large Scale Test Cases

def test_large_list_all_valid():
# Test a large list (1000 elements) all valid
weights = [1.0 for _ in range(1000)]
codeflash_output = T2IAdapterInvocation.validate_ip_adapter_weight(weights) # 41.5μs -> 13.6μs (205% faster)

def test_large_list_one_invalid_at_start():
# Test a large list (1000 elements) with first element invalid
weights = [-1.1] + [1.0 for _ in range(999)]
with pytest.raises(ValueError, match="Control weights must be within -1 to 2 range"):
T2IAdapterInvocation.validate_ip_adapter_weight(weights) # 2.13μs -> 7.76μs (72.5% slower)

def test_large_list_one_invalid_at_end():
# Test a large list (1000 elements) with last element invalid
weights = [1.0 for _ in range(999)] + [2.1]
with pytest.raises(ValueError, match="Control weights must be within -1 to 2 range"):
T2IAdapterInvocation.validate_ip_adapter_weight(weights) # 42.1μs -> 14.1μs (198% faster)

def test_large_list_one_invalid_in_middle():
# Test a large list (1000 elements) with one invalid value in the middle
weights = [1.0 for _ in range(500)] + [-2.0] + [1.0 for _ in range(499)]
with pytest.raises(ValueError, match="Control weights must be within -1 to 2 range"):
T2IAdapterInvocation.validate_ip_adapter_weight(weights) # 22.3μs -> 7.82μs (185% faster)

def test_large_list_all_invalid():
# Test a large list (1000 elements) all invalid
weights = [3.0 for _ in range(1000)]
with pytest.raises(ValueError, match="Control weights must be within -1 to 2 range"):
T2IAdapterInvocation.validate_ip_adapter_weight(weights) # 2.08μs -> 14.0μs (85.1% slower)

def test_large_list_all_at_lower_bound():
# Test a large list (1000 elements) all at lower bound
weights = [-1.0 for _ in range(1000)]
codeflash_output = T2IAdapterInvocation.validate_ip_adapter_weight(weights) # 41.5μs -> 13.6μs (205% faster)

def test_large_list_all_at_upper_bound():
# Test a large list (1000 elements) all at upper bound
weights = [2.0 for _ in range(1000)]
codeflash_output = T2IAdapterInvocation.validate_ip_adapter_weight(weights) # 41.4μs -> 13.5μs (208% faster)

def test_large_list_mixed_valid():
# Test a large list (1000 elements) with values at lower, upper, and mid-range
weights = [-1.0, 0.0, 1.0, 2.0] * 250 # 1000 elements
codeflash_output = T2IAdapterInvocation.validate_ip_adapter_weight(weights) # 41.1μs -> 13.6μs (203% faster)

codeflash_output is used to check that the output of the original code is the same as that of the optimized code.

#------------------------------------------------
from typing import Union

imports

import pytest
from invokeai.app.invocations.t2i_adapter import T2IAdapterInvocation

unit tests

-------------------------

1. Basic Test Cases

-------------------------

def test_single_valid_weight_middle():
# Test with a single valid float in the middle of the range
codeflash_output = T2IAdapterInvocation.validate_ip_adapter_weight(0.5) # 2.06μs -> 1.76μs (17.1% faster)

def test_single_valid_weight_lower_bound():
# Test with a single valid float at the lower bound
codeflash_output = T2IAdapterInvocation.validate_ip_adapter_weight(-1.0) # 1.65μs -> 1.42μs (16.3% faster)

def test_single_valid_weight_upper_bound():
# Test with a single valid float at the upper bound
codeflash_output = T2IAdapterInvocation.validate_ip_adapter_weight(2.0) # 1.56μs -> 1.35μs (15.6% faster)

def test_list_valid_weights_various():
# Test with a list of valid weights within range
weights = [0.0, 1.0, -0.5, 2.0, -1.0, 1.5]
codeflash_output = T2IAdapterInvocation.validate_ip_adapter_weight(weights) # 1.91μs -> 1.52μs (25.7% faster)

def test_list_valid_weights_all_zeros():
# Test with a list of zeros
weights = [0.0, 0.0, 0.0]
codeflash_output = T2IAdapterInvocation.validate_ip_adapter_weight(weights) # 1.56μs -> 1.31μs (19.4% faster)

-------------------------

2. Edge Test Cases

-------------------------

def test_single_weight_below_lower_bound():
# Test with a single weight just below the lower bound
with pytest.raises(ValueError):
T2IAdapterInvocation.validate_ip_adapter_weight(-1.00001) # 2.23μs -> 1.67μs (33.6% faster)

def test_single_weight_above_upper_bound():
# Test with a single weight just above the upper bound
with pytest.raises(ValueError):
T2IAdapterInvocation.validate_ip_adapter_weight(2.00001) # 2.24μs -> 1.85μs (21.1% faster)

def test_list_weight_contains_invalid_low():
# Test with a list containing one invalid (too low) value
weights = [0.0, -1.1, 1.0]
with pytest.raises(ValueError):
T2IAdapterInvocation.validate_ip_adapter_weight(weights) # 2.26μs -> 1.65μs (37.0% faster)

def test_list_weight_contains_invalid_high():
# Test with a list containing one invalid (too high) value
weights = [0.0, 2.1, 1.0]
with pytest.raises(ValueError):
T2IAdapterInvocation.validate_ip_adapter_weight(weights) # 2.19μs -> 1.90μs (15.8% faster)

def test_list_weight_multiple_invalid():
# Test with a list containing multiple invalid values (both low and high)
weights = [-2.0, 2.5, 0.0]
with pytest.raises(ValueError):
T2IAdapterInvocation.validate_ip_adapter_weight(weights) # 1.92μs -> 1.51μs (27.1% faster)

def test_empty_list():
# Test with an empty list (should be valid, as there are no invalid elements)
weights = []
codeflash_output = T2IAdapterInvocation.validate_ip_adapter_weight(weights) # 1.16μs -> 661ns (74.9% faster)

def test_non_float_type_string():
# Test with a string input (should raise TypeError)
with pytest.raises(TypeError):
T2IAdapterInvocation.validate_ip_adapter_weight("not_a_float") # 2.86μs -> 2.40μs (19.3% faster)

def test_non_float_type_dict():
# Test with a dict input (should raise TypeError)
with pytest.raises(TypeError):
T2IAdapterInvocation.validate_ip_adapter_weight({'a': 1}) # 2.73μs -> 2.36μs (15.6% faster)

def test_list_with_non_float_element():
# Test with a list containing a non-float element (should raise TypeError)
with pytest.raises(TypeError):
T2IAdapterInvocation.validate_ip_adapter_weight([0.0, "bad", 1.0]) # 2.67μs -> 2.33μs (14.6% faster)

-------------------------

3. Large Scale Test Cases

-------------------------

def test_large_list_all_valid():
# Test with a large list of valid weights (all 1.0)
weights = [1.0] * 999
codeflash_output = T2IAdapterInvocation.validate_ip_adapter_weight(weights) # 41.6μs -> 13.7μs (203% faster)

def test_large_list_one_invalid_low():
# Test with a large list where one value is just below the lower bound
weights = [0.5] * 500 + [-1.0001] + [1.5] * 498
with pytest.raises(ValueError):
T2IAdapterInvocation.validate_ip_adapter_weight(weights) # 22.3μs -> 7.79μs (186% faster)

def test_large_list_one_invalid_high():
# Test with a large list where one value is just above the upper bound
weights = [0.5] * 600 + [2.0001] + [1.5] * 398
with pytest.raises(ValueError):
T2IAdapterInvocation.validate_ip_adapter_weight(weights) # 26.2μs -> 14.2μs (84.8% faster)

def test_large_list_edge_values():
# Test with a large list containing only edge values (-1.0 and 2.0)
weights = [-1.0, 2.0] * 499 + [0.0]
codeflash_output = T2IAdapterInvocation.validate_ip_adapter_weight(weights) # 41.8μs -> 13.5μs (209% faster)

def test_large_list_all_invalid():
# Test with a large list where all values are invalid
weights = [-2.0] * 999
with pytest.raises(ValueError):
T2IAdapterInvocation.validate_ip_adapter_weight(weights) # 1.98μs -> 7.63μs (74.1% slower)

-------------------------

4. Additional Robustness Tests

-------------------------

def test_list_with_nan():
# Test with a list containing float('nan')
import math
weights = [0.0, float('nan'), 1.0]
# nan is not less than -1 or greater than 2, so it should pass
# But comparing nan with < or > returns False, so this passes unless you want to explicitly catch nan
codeflash_output = T2IAdapterInvocation.validate_ip_adapter_weight(weights) # 1.81μs -> 1.40μs (29.0% faster)

def test_list_with_inf():
# Test with a list containing float('inf')
weights = [0.0, float('inf'), 1.0]
with pytest.raises(ValueError):
T2IAdapterInvocation.validate_ip_adapter_weight(weights) # 2.24μs -> 1.86μs (20.6% faster)

def test_list_with_negative_inf():
# Test with a list containing float('-inf')
weights = [0.0, float('-inf'), 1.0]
with pytest.raises(ValueError):
T2IAdapterInvocation.validate_ip_adapter_weight(weights) # 2.25μs -> 1.50μs (49.9% faster)

def test_list_with_bool_values():
# Test with a list containing boolean values (should pass, as bool is a subclass of int)
weights = [True, False, 1.0]
codeflash_output = T2IAdapterInvocation.validate_ip_adapter_weight(weights) # 1.74μs -> 1.53μs (13.7% faster)

def test_list_with_int_values():
# Test with a list containing int values (should pass, as ints are valid floats)
weights = [0, 1, -1, 2]
codeflash_output = T2IAdapterInvocation.validate_ip_adapter_weight(weights) # 1.61μs -> 1.36μs (18.4% faster)

def test_single_int_value():
# Test with a single int value
codeflash_output = T2IAdapterInvocation.validate_ip_adapter_weight(1) # 1.48μs -> 1.22μs (21.1% faster)

def test_list_with_mixed_int_and_float():
# Test with a list containing both int and float values
weights = [0, 1.0, -1, 2.0]
codeflash_output = T2IAdapterInvocation.validate_ip_adapter_weight(weights) # 1.69μs -> 1.61μs (5.09% faster)

def test_list_with_none():
# Test with a list containing None (should raise TypeError)
weights = [0.0, None, 1.0]
with pytest.raises(TypeError):
T2IAdapterInvocation.validate_ip_adapter_weight(weights) # 2.92μs -> 2.41μs (21.6% faster)

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-T2IAdapterInvocation.validate_ip_adapter_weight-mhvf8oya and push.

Codeflash Static Badge

The optimization replaces an `any()` generator expression with `min()` and `max()` operations for range validation. 

**Key Change:** Instead of iterating through each weight value with `any(i < -1 or i > 2 for i in to_validate)`, the optimized version uses `if min(to_validate) < -1 or max(to_validate) > 2:` to check bounds.

**Why This is Faster:**
- **Reduced function call overhead**: The original code calls a comparison function for every element via the generator expression. The optimized version makes only two C-level function calls (`min` and `max`) regardless of list size.
- **Better algorithmic efficiency for large lists**: For lists with all valid values, both approaches scan the entire list, but `min/max` are implemented in C and are highly optimized for numerical operations.
- **Short-circuit behavior preserved**: If the first element violates bounds, `min/max` can still exit early in many cases.
- **Empty list handling**: Added a guard `if to_validate:` to avoid calling `min/max` on empty lists, which provides a 75% speedup for empty lists.

**Performance Characteristics:**
- **Small lists/single values**: 8-37% faster due to reduced Python function call overhead
- **Large valid lists**: 200%+ faster due to C-optimized `min/max` operations  
- **Large lists with violations**: Mixed results - early violations are detected faster, but lists with violations only at the end may be slightly slower due to full list traversal by `max`

**Impact on Workloads:** This validation function is used in T2I-Adapter weight validation during model setup, so the optimization will improve initialization performance, especially when using multiple adapters or large weight arrays.
@codeflash-ai codeflash-ai bot requested a review from mashraf-222 November 12, 2025 03:09
@codeflash-ai codeflash-ai bot added ⚡️ codeflash Optimization PR opened by Codeflash AI 🎯 Quality: High Optimization Quality according to Codeflash labels Nov 12, 2025
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 🎯 Quality: High Optimization Quality according to Codeflash

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant