⚡️ Speed up method T2IAdapterField.validate_ip_adapter_weight by 149%
#130
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
📄 149% (1.49x) speedup for
T2IAdapterField.validate_ip_adapter_weightininvokeai/app/invocations/t2i_adapter.py⏱️ Runtime :
621 microseconds→249 microseconds(best of235runs)📝 Explanation and details
The optimization replaces the
any()generator expression withmin()andmax()functions for boundary validation, achieving a 149% speedup.Key optimization:
any(i < -1 or i > 2 for i in to_validate)performs element-by-element comparisons that can short-circuit early but requires two comparisons per elementmin(to_validate) < -1 or max(to_validate) > 2uses Python's built-inmin()andmax()functions implemented in C, which are highly optimized for finding extrema in a single passWhy this is faster:
min()andmax()are implemented in C and optimized for numerical operations, avoiding Python's interpreter overhead for each comparisonPerformance characteristics from tests:
min()must scan the entire list), but still faster overall due to C implementationThe optimization particularly benefits validation-heavy workflows in AI model inference where weight arrays are frequently validated, making it ideal for production environments with repeated model invocations.
✅ Correctness verification report:
🌀 Generated Regression Tests and Runtime
from typing import Union
imports
import pytest # used for our unit tests
from invokeai.app.invocations.t2i_adapter import T2IAdapterField
unit tests
----- Basic Test Cases -----
def test_single_valid_weight_lower_bound():
# Test with a single float at the lower bound
codeflash_output = T2IAdapterField.validate_ip_adapter_weight(-1.0) # 2.08μs -> 1.77μs (17.4% faster)
def test_single_valid_weight_upper_bound():
# Test with a single float at the upper bound
codeflash_output = T2IAdapterField.validate_ip_adapter_weight(2.0) # 1.67μs -> 1.43μs (17.2% faster)
def test_single_valid_weight_middle():
# Test with a single float in the middle of the range
codeflash_output = T2IAdapterField.validate_ip_adapter_weight(0.5) # 1.63μs -> 1.37μs (18.7% faster)
def test_list_valid_weights():
# Test with a list of floats all within bounds
weights = [0.0, 1.0, -1.0, 2.0, 1.5]
codeflash_output = T2IAdapterField.validate_ip_adapter_weight(weights) # 1.98μs -> 1.57μs (26.1% faster)
def test_single_valid_weight_as_int():
# Test with a single integer value within bounds
codeflash_output = T2IAdapterField.validate_ip_adapter_weight(1) # 1.52μs -> 1.28μs (19.0% faster)
def test_list_valid_weights_with_ints():
# Test with a list containing both ints and floats within bounds
weights = [0, 1.0, -1, 2]
codeflash_output = T2IAdapterField.validate_ip_adapter_weight(weights) # 1.82μs -> 1.59μs (14.4% faster)
----- Edge Test Cases -----
def test_single_weight_below_lower_bound():
# Test with a single float below the lower bound
with pytest.raises(ValueError):
T2IAdapterField.validate_ip_adapter_weight(-1.0001) # 2.27μs -> 1.69μs (34.6% faster)
def test_single_weight_above_upper_bound():
# Test with a single float above the upper bound
with pytest.raises(ValueError):
T2IAdapterField.validate_ip_adapter_weight(2.0001) # 2.24μs -> 1.83μs (22.2% faster)
def test_list_with_one_invalid_weight_below():
# Test with a list containing one weight below lower bound
weights = [0.0, -1.1, 1.0]
with pytest.raises(ValueError):
T2IAdapterField.validate_ip_adapter_weight(weights) # 2.35μs -> 1.67μs (40.3% faster)
def test_list_with_one_invalid_weight_above():
# Test with a list containing one weight above upper bound
weights = [1.0, 2.1, 0.5]
with pytest.raises(ValueError):
T2IAdapterField.validate_ip_adapter_weight(weights) # 2.21μs -> 1.83μs (21.1% faster)
def test_list_with_multiple_invalid_weights():
# Test with a list containing several invalid weights
weights = [-2.0, 3.0, 0.0]
with pytest.raises(ValueError):
T2IAdapterField.validate_ip_adapter_weight(weights) # 2.01μs -> 1.52μs (32.4% faster)
def test_empty_list():
# Test with an empty list (should pass, as no invalid weights exist)
weights = []
codeflash_output = T2IAdapterField.validate_ip_adapter_weight(weights) # 1.27μs -> 675ns (88.9% faster)
def test_single_weight_at_exact_bounds():
# Test with weights at exactly -1 and 2
codeflash_output = T2IAdapterField.validate_ip_adapter_weight(-1) # 1.55μs -> 1.36μs (13.3% faster)
codeflash_output = T2IAdapterField.validate_ip_adapter_weight(2) # 732ns -> 650ns (12.6% faster)
def test_list_with_nan_weight():
# Test with a list containing a NaN value (should not raise, as NaN is not < -1 or > 2)
import math
weights = [0.5, math.nan]
# NaN does not compare True for < or >, so should pass
codeflash_output = T2IAdapterField.validate_ip_adapter_weight(weights) # 1.73μs -> 1.36μs (27.6% faster)
def test_list_with_inf_weight():
# Test with a list containing an infinite value (should raise)
weights = [0.5, float('inf')]
with pytest.raises(ValueError):
T2IAdapterField.validate_ip_adapter_weight(weights) # 2.27μs -> 1.84μs (23.3% faster)
def test_list_with_negative_inf_weight():
# Test with a list containing a negative infinite value (should raise)
weights = [0.5, float('-inf')]
with pytest.raises(ValueError):
T2IAdapterField.validate_ip_adapter_weight(weights) # 2.41μs -> 1.67μs (45.0% faster)
def test_list_with_none_weight():
# Test with a list containing None (should raise TypeError)
weights = [0.5, None]
with pytest.raises(TypeError):
T2IAdapterField.validate_ip_adapter_weight(weights) # 3.11μs -> 2.47μs (26.1% faster)
def test_single_weight_none():
# Test with a single None value (should raise TypeError)
with pytest.raises(TypeError):
T2IAdapterField.validate_ip_adapter_weight(None) # 2.61μs -> 2.20μs (18.9% faster)
def test_single_weight_string():
# Test with a single string value (should raise TypeError)
with pytest.raises(TypeError):
T2IAdapterField.validate_ip_adapter_weight("foo") # 2.54μs -> 2.15μs (18.1% faster)
def test_list_with_string_weight():
# Test with a list containing a string value (should raise TypeError)
weights = [1.0, "bar"]
with pytest.raises(TypeError):
T2IAdapterField.validate_ip_adapter_weight(weights) # 2.60μs -> 2.27μs (14.9% faster)
def test_list_with_object_weight():
# Test with a list containing a non-numeric object (should raise TypeError)
weights = [1.0, object()]
with pytest.raises(TypeError):
T2IAdapterField.validate_ip_adapter_weight(weights) # 2.69μs -> 2.15μs (25.1% faster)
def test_list_with_bool_weight():
# Test with a list containing a boolean value (should pass, as bool is a subclass of int)
weights = [True, False, 1.0]
# True == 1, False == 0, both within [-1,2]
codeflash_output = T2IAdapterField.validate_ip_adapter_weight(weights) # 1.81μs -> 1.63μs (11.0% faster)
def test_single_weight_bool():
# Test with a single boolean value (should pass)
codeflash_output = T2IAdapterField.validate_ip_adapter_weight(True) # 1.73μs -> 1.38μs (25.9% faster)
codeflash_output = T2IAdapterField.validate_ip_adapter_weight(False) # 794ns -> 637ns (24.6% faster)
----- Large Scale Test Cases -----
def test_large_list_all_valid_weights():
# Test with a large list of valid weights
weights = [1.0 for _ in range(1000)]
codeflash_output = T2IAdapterField.validate_ip_adapter_weight(weights) # 41.5μs -> 13.6μs (205% faster)
def test_large_list_one_invalid_weight_at_start():
# Test with a large list with one invalid weight at the start
weights = [-1.1] + [1.0 for _ in range(999)]
with pytest.raises(ValueError):
T2IAdapterField.validate_ip_adapter_weight(weights) # 2.21μs -> 7.86μs (71.9% slower)
def test_large_list_one_invalid_weight_at_end():
# Test with a large list with one invalid weight at the end
weights = [1.0 for _ in range(999)] + [2.1]
with pytest.raises(ValueError):
T2IAdapterField.validate_ip_adapter_weight(weights) # 42.2μs -> 14.2μs (198% faster)
def test_large_list_one_invalid_weight_in_middle():
# Test with a large list with one invalid weight in the middle
weights = [1.0 for _ in range(500)] + [-2.0] + [1.0 for _ in range(499)]
with pytest.raises(ValueError):
T2IAdapterField.validate_ip_adapter_weight(weights) # 22.4μs -> 7.89μs (184% faster)
def test_large_list_all_at_lower_bound():
# Test with a large list of weights all at the lower bound
weights = [-1.0 for _ in range(1000)]
codeflash_output = T2IAdapterField.validate_ip_adapter_weight(weights) # 41.6μs -> 13.7μs (203% faster)
def test_large_list_all_at_upper_bound():
# Test with a large list of weights all at the upper bound
weights = [2.0 for _ in range(1000)]
codeflash_output = T2IAdapterField.validate_ip_adapter_weight(weights) # 41.7μs -> 13.6μs (206% faster)
def test_large_list_with_inf():
# Test with a large list containing an inf value
weights = [1.0 for _ in range(999)] + [float('inf')]
with pytest.raises(ValueError):
T2IAdapterField.validate_ip_adapter_weight(weights) # 42.4μs -> 14.2μs (199% faster)
def test_large_list_with_none():
# Test with a large list containing a None value
weights = [1.0 for _ in range(999)] + [None]
with pytest.raises(TypeError):
T2IAdapterField.validate_ip_adapter_weight(weights) # 43.2μs -> 8.66μs (398% faster)
def test_large_list_with_string():
# Test with a large list containing a string value
weights = [1.0 for _ in range(999)] + ["bad"]
with pytest.raises(TypeError):
T2IAdapterField.validate_ip_adapter_weight(weights) # 42.6μs -> 8.47μs (403% 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 # used for our unit tests
from invokeai.app.invocations.t2i_adapter import T2IAdapterField
=========================
Unit Tests for validate_ip_adapter_weight
=========================
--- 1. Basic Test Cases ---
def test_single_weight_at_lower_bound():
# Test with a single float at the lower bound (-1)
codeflash_output = T2IAdapterField.validate_ip_adapter_weight(-1) # 1.96μs -> 1.76μs (11.7% faster)
def test_single_weight_at_upper_bound():
# Test with a single float at the upper bound (2)
codeflash_output = T2IAdapterField.validate_ip_adapter_weight(2) # 1.60μs -> 1.24μs (29.6% faster)
def test_single_weight_in_middle():
# Test with a single float in the middle of the range
codeflash_output = T2IAdapterField.validate_ip_adapter_weight(0.5) # 1.81μs -> 1.37μs (31.5% faster)
def test_list_of_weights_all_valid():
# Test with a list of floats all within the valid range
valid_weights = [0, 1, -1, 2, 1.5]
codeflash_output = T2IAdapterField.validate_ip_adapter_weight(valid_weights) # 2.03μs -> 1.73μs (17.3% faster)
def test_list_with_one_value_at_lower_bound():
# Test with a list containing the lower bound
valid_weights = [0.2, -1, 1.9]
codeflash_output = T2IAdapterField.validate_ip_adapter_weight(valid_weights) # 1.77μs -> 1.52μs (16.2% faster)
def test_list_with_one_value_at_upper_bound():
# Test with a list containing the upper bound
valid_weights = [1.2, 2, 0.8]
codeflash_output = T2IAdapterField.validate_ip_adapter_weight(valid_weights) # 1.70μs -> 1.57μs (8.03% faster)
--- 2. Edge Test Cases ---
def test_weight_below_lower_bound():
# Test with a single float below the lower bound
with pytest.raises(ValueError):
T2IAdapterField.validate_ip_adapter_weight(-1.0001) # 2.29μs -> 1.66μs (37.8% faster)
def test_weight_above_upper_bound():
# Test with a single float above the upper bound
with pytest.raises(ValueError):
T2IAdapterField.validate_ip_adapter_weight(2.0001) # 2.22μs -> 1.83μs (21.7% faster)
def test_list_with_one_invalid_low():
# Test with a list containing one value below the lower bound
weights = [0.5, -1.1, 1.0]
with pytest.raises(ValueError):
T2IAdapterField.validate_ip_adapter_weight(weights) # 2.33μs -> 1.72μs (35.6% faster)
def test_list_with_one_invalid_high():
# Test with a list containing one value above the upper bound
weights = [1.9, 2.1, 0.0]
with pytest.raises(ValueError):
T2IAdapterField.validate_ip_adapter_weight(weights) # 2.21μs -> 1.98μs (11.8% faster)
def test_list_with_all_invalid():
# Test with a list where all values are invalid
weights = [-2, 3]
with pytest.raises(ValueError):
T2IAdapterField.validate_ip_adapter_weight(weights) # 1.99μs -> 1.58μs (26.1% faster)
def test_list_with_mixed_valid_and_invalid():
# Test with a list containing both valid and invalid values
weights = [0.5, -1, 2, 2.5]
with pytest.raises(ValueError):
T2IAdapterField.validate_ip_adapter_weight(weights) # 2.40μs -> 2.15μs (11.3% faster)
def test_empty_list():
# Test with an empty list (should pass, as no invalid weights)
codeflash_output = T2IAdapterField.validate_ip_adapter_weight([]) # 1.21μs -> 724ns (66.9% faster)
def test_weight_as_integer():
# Test with integer values at bounds
codeflash_output = T2IAdapterField.validate_ip_adapter_weight(-1) # 1.48μs -> 1.29μs (14.5% faster)
codeflash_output = T2IAdapterField.validate_ip_adapter_weight(2) # 736ns -> 677ns (8.71% faster)
def test_list_of_integers():
# Test with a list of integer values within bounds
weights = [-1, 0, 1, 2]
codeflash_output = T2IAdapterField.validate_ip_adapter_weight(weights) # 1.53μs -> 1.37μs (11.4% faster)
def test_list_with_float_and_int_mix():
# Test with a mix of floats and ints
weights = [0, 1.5, 2, -1]
codeflash_output = T2IAdapterField.validate_ip_adapter_weight(weights) # 1.71μs -> 1.53μs (11.4% faster)
def test_weight_as_string_should_fail():
# Test with a string input (should raise TypeError from comparison)
with pytest.raises(TypeError):
T2IAdapterField.validate_ip_adapter_weight("1") # 2.71μs -> 2.37μs (14.7% faster)
def test_list_with_string_should_fail():
# Test with a list containing a string (should raise TypeError)
with pytest.raises(TypeError):
T2IAdapterField.validate_ip_adapter_weight([1, "2", 0]) # 2.75μs -> 2.27μs (21.1% faster)
def test_none_should_fail():
# Test with None as input (should raise TypeError)
with pytest.raises(TypeError):
T2IAdapterField.validate_ip_adapter_weight(None) # 2.56μs -> 2.22μs (15.7% faster)
def test_list_with_none_should_fail():
# Test with a list containing None (should raise TypeError)
with pytest.raises(TypeError):
T2IAdapterField.validate_ip_adapter_weight([1, None, 0]) # 2.62μs -> 2.10μs (24.5% faster)
def test_list_with_inf_should_fail():
# Test with a list containing float('inf') (should raise ValueError)
weights = [0.5, float('inf')]
with pytest.raises(ValueError):
T2IAdapterField.validate_ip_adapter_weight(weights) # 2.96μs -> 2.40μs (23.1% faster)
def test_list_with_neg_inf_should_fail():
# Test with a list containing float('-inf') (should raise ValueError)
weights = [0.5, float('-inf')]
with pytest.raises(ValueError):
T2IAdapterField.validate_ip_adapter_weight(weights) # 2.56μs -> 1.67μs (53.1% faster)
--- 3. Large Scale Test Cases ---
def test_large_list_all_valid():
# Test with a large list of valid weights (size ~1000)
weights = [1.0 for _ in range(1000)]
codeflash_output = T2IAdapterField.validate_ip_adapter_weight(weights) # 41.7μs -> 13.8μs (202% faster)
def test_large_list_with_one_invalid_low():
# Test with a large list where one value is invalid (below lower bound)
weights = [1.0 for _ in range(999)] + [-1.01]
with pytest.raises(ValueError):
T2IAdapterField.validate_ip_adapter_weight(weights) # 42.4μs -> 7.84μs (441% faster)
def test_large_list_with_one_invalid_high():
# Test with a large list where one value is invalid (above upper bound)
weights = [1.0 for _ in range(999)] + [2.01]
with pytest.raises(ValueError):
T2IAdapterField.validate_ip_adapter_weight(weights) # 42.3μs -> 14.2μs (197% faster)
def test_large_list_at_bounds():
# Test with a large list alternating between bounds
weights = [-1, 2] * 500
codeflash_output = T2IAdapterField.validate_ip_adapter_weight(weights) # 34.1μs -> 12.1μs (182% faster)
def test_large_list_all_invalid():
# Test with a large list where all values are invalid
weights = [-2 for _ in range(1000)]
with pytest.raises(ValueError):
T2IAdapterField.validate_ip_adapter_weight(weights) # 2.06μs -> 6.59μs (68.7% slower)
To edit these changes
git checkout codeflash/optimize-T2IAdapterField.validate_ip_adapter_weight-mhvf20xuand push.