Skip to content

Conversation

@codeflash-ai
Copy link
Contributor

@codeflash-ai codeflash-ai bot commented Jul 22, 2025

📄 236% (2.36x) speedup for sigmoid_stable in codeflash/process/infer.py

⏱️ Runtime : 4.55 milliseconds 1.36 milliseconds (best of 121 runs)

📝 Explanation and details

Here is a faster and more memory-efficient version of the function. The bottleneck in the original implementation is calling np.exp(x) twice for x < 0 branches. We can compute exp_x = np.exp(x) once, then reuse it for both cases.

This version calls np.exp only once and chooses the correct formulation based on x, which results in a significant speedup and less redundant computation.

Correctness verification report:

Test Status
⚙️ Existing Unit Tests 🔘 None Found
🌀 Generated Regression Tests 35 Passed
⏪ Replay Tests 2 Passed
🔎 Concolic Coverage Tests 🔘 None Found
📊 Tests Coverage 100.0%
🌀 Generated Regression Tests and Runtime
import numpy as np
# imports
import pytest  # used for our unit tests
from codeflash.process.infer import sigmoid_stable

# unit tests

# 1. Basic Test Cases

def test_sigmoid_zero():
    # Sigmoid at zero should be exactly 0.5
    codeflash_output = sigmoid_stable(0.0)

def test_sigmoid_positive_scalar():
    # Test a positive scalar input
    codeflash_output = sigmoid_stable(1.0); result = codeflash_output
    expected = 1 / (1 + np.exp(-1.0))

def test_sigmoid_negative_scalar():
    # Test a negative scalar input
    codeflash_output = sigmoid_stable(-1.0); result = codeflash_output
    expected = 1 / (1 + np.exp(1.0))

def test_sigmoid_array_basic():
    # Test with a small array of mixed values
    arr = np.array([-1.0, 0.0, 1.0])
    codeflash_output = sigmoid_stable(arr); result = codeflash_output
    expected = 1 / (1 + np.exp(-arr))


def test_sigmoid_large_positive():
    # For very large positive x, sigmoid should approach 1
    x = 1000
    codeflash_output = sigmoid_stable(x); result = codeflash_output

def test_sigmoid_large_negative():
    # For very large negative x, sigmoid should approach 0
    x = -1000
    codeflash_output = sigmoid_stable(x); result = codeflash_output

def test_sigmoid_extreme_array():
    # Array with extreme values, both large positive and negative
    arr = np.array([-1000, -100, -20, 0, 20, 100, 1000])
    codeflash_output = sigmoid_stable(arr); result = codeflash_output
    expected = 1 / (1 + np.exp(-arr))
    # For large values, expected will overflow, so use known asymptotes
    expected = np.array([0.0, 3.72007598e-44, 2.06115362e-09, 0.5, 1.0 - 2.06115362e-09, 1.0, 1.0])

def test_sigmoid_nan_input():
    # Sigmoid of NaN should be NaN
    codeflash_output = sigmoid_stable(np.nan); result = codeflash_output

def test_sigmoid_inf_input():
    # Sigmoid of +inf should be 1, -inf should be 0
    codeflash_output = sigmoid_stable(np.inf); result_pos = codeflash_output
    codeflash_output = sigmoid_stable(-np.inf); result_neg = codeflash_output

def test_sigmoid_array_inf_nan():
    # Array with inf, -inf, nan, and normal values
    arr = np.array([-np.inf, -1, 0, 1, np.inf, np.nan])
    codeflash_output = sigmoid_stable(arr); result = codeflash_output
    expected = np.array([0.0, 1 / (1 + np.exp(1)), 0.5, 1 / (1 + np.exp(-1)), 1.0, np.nan])
    for r, e in zip(result, expected):
        if np.isnan(e):
            pass
        else:
            pass

def test_sigmoid_dtype_preservation():
    # Output dtype should match input dtype for array inputs
    arr = np.array([0.0, 1.0, -1.0], dtype=np.float32)
    codeflash_output = sigmoid_stable(arr); result = codeflash_output

# 3. Large Scale Test Cases

def test_sigmoid_large_array():
    # Test with a large array (1000 elements) of random values
    np.random.seed(42)
    arr = np.random.uniform(-10, 10, size=1000)
    codeflash_output = sigmoid_stable(arr); result = codeflash_output
    expected = 1 / (1 + np.exp(-arr))

def test_sigmoid_large_array_extremes():
    # Large array with extreme values at both ends
    arr = np.concatenate([
        np.linspace(-1000, -20, 500),
        np.linspace(20, 1000, 500)
    ])
    codeflash_output = sigmoid_stable(arr); result = codeflash_output

def test_sigmoid_multidimensional_array():
    # Test with a 2D array
    arr = np.array([[-2, -1, 0], [1, 2, 3]])
    codeflash_output = sigmoid_stable(arr); result = codeflash_output
    expected = 1 / (1 + np.exp(-arr))

def test_sigmoid_large_multidimensional_array():
    # Test with a large 2D array (100x10)
    arr = np.random.uniform(-10, 10, size=(100, 10))
    codeflash_output = sigmoid_stable(arr); result = codeflash_output
    expected = 1 / (1 + np.exp(-arr))

# 4. Additional Edge Cases

def test_sigmoid_empty_array():
    # Should handle empty arrays gracefully
    arr = np.array([])
    codeflash_output = sigmoid_stable(arr); result = codeflash_output


def test_sigmoid_object_array():
    # Should raise TypeError when input is of object dtype (non-numeric)
    arr = np.array(['a', 'b', 'c'], dtype=object)
    with pytest.raises(TypeError):
        sigmoid_stable(arr)
# codeflash_output is used to check that the output of the original code is the same as that of the optimized code.

import math  # for math.exp, math.isclose

import numpy as np
# imports
import pytest  # used for our unit tests
from codeflash.process.infer import sigmoid_stable

# unit tests

# --- Basic Test Cases ---

def test_sigmoid_basic_zero():
    # Sigmoid(0) == 0.5
    codeflash_output = sigmoid_stable(0); result = codeflash_output

def test_sigmoid_basic_positive_scalar():
    # Sigmoid(1) == 1/(1+exp(-1))
    expected = 1 / (1 + math.exp(-1))
    codeflash_output = sigmoid_stable(1); result = codeflash_output

def test_sigmoid_basic_negative_scalar():
    # Sigmoid(-1) == 1/(1+exp(1))
    expected = 1 / (1 + math.exp(1))
    codeflash_output = sigmoid_stable(-1); result = codeflash_output

def test_sigmoid_basic_array():
    # Test with a small array of mixed values
    arr = np.array([-2, -1, 0, 1, 2])
    expected = 1 / (1 + np.exp(-arr))
    codeflash_output = sigmoid_stable(arr); result = codeflash_output

# --- Edge Test Cases ---

def test_sigmoid_large_positive():
    # For large x, sigmoid(x) approaches 1
    large_pos = 1000
    codeflash_output = sigmoid_stable(large_pos); result = codeflash_output

def test_sigmoid_large_negative():
    # For large negative x, sigmoid(x) approaches 0
    large_neg = -1000
    codeflash_output = sigmoid_stable(large_neg); result = codeflash_output

def test_sigmoid_extreme_array():
    # Array with extreme values
    arr = np.array([-1000, -100, -10, 0, 10, 100, 1000])
    expected = np.array([0.0, 3.72007598e-44, 4.53978687e-05, 0.5, 0.9999546, 1.0, 1.0])
    codeflash_output = sigmoid_stable(arr); result = codeflash_output

def test_sigmoid_nan_input():
    # If input is nan, output should be nan
    arr = np.array([np.nan, 0, 1])
    codeflash_output = sigmoid_stable(arr); result = codeflash_output

def test_sigmoid_inf_input():
    # Test with inf and -inf
    arr = np.array([np.inf, -np.inf, 0])
    codeflash_output = sigmoid_stable(arr); result = codeflash_output

def test_sigmoid_empty_array():
    # Empty input should return empty output
    arr = np.array([])
    codeflash_output = sigmoid_stable(arr); result = codeflash_output

def test_sigmoid_object_dtype_raises():
    # Passing an object array with non-numeric types should raise an error
    arr = np.array(['a', None, 1], dtype=object)
    with pytest.raises(TypeError):
        sigmoid_stable(arr)

# --- Large Scale Test Cases ---

def test_sigmoid_large_array_performance():
    # Test with a large array of 1000 elements
    arr = np.linspace(-10, 10, 1000)
    expected = 1 / (1 + np.exp(-arr))
    codeflash_output = sigmoid_stable(arr); result = codeflash_output

def test_sigmoid_large_array_extremes():
    # Test with a large array of extreme values
    arr = np.concatenate([np.full(500, -1000), np.full(500, 1000)])
    codeflash_output = sigmoid_stable(arr); result = codeflash_output

def test_sigmoid_large_random_array():
    # Test with a large array of random floats
    rng = np.random.default_rng(42)
    arr = rng.uniform(-50, 50, size=1000)
    expected = 1 / (1 + np.exp(-arr))
    codeflash_output = sigmoid_stable(arr); result = codeflash_output

# --- Additional Edge Cases ---


def test_sigmoid_dtype_preservation():
    # Output should be float64 for float64 input
    arr = np.array([1, 2, 3], dtype=np.float64)
    codeflash_output = sigmoid_stable(arr); result = codeflash_output

def test_sigmoid_int_input():
    # Integer input should work and return float output
    arr = np.array([1, 2, 3], dtype=int)
    codeflash_output = sigmoid_stable(arr); result = codeflash_output

def test_sigmoid_broadcasting():
    # Test broadcasting with mixed shape input
    arr = np.array([[0, 1], [-1, -2]])
    expected = 1 / (1 + np.exp(-arr))
    codeflash_output = sigmoid_stable(arr); 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.
⏪ Replay Tests and Runtime
Test File::Test Function Original ⏱️ Optimized ⏱️ Speedup

To edit these changes git checkout codeflash/optimize-sigmoid_stable-mde515y6 and push.

Codeflash

Here is a faster and more memory-efficient version of the function. The bottleneck in the original implementation is calling `np.exp(x)` twice for `x < 0` branches. We can compute `exp_x = np.exp(x)` once, then reuse it for both cases.



This version calls `np.exp` only once and chooses the correct formulation based on `x`, which results in a significant speedup and less redundant computation.
@codeflash-ai codeflash-ai bot added the ⚡️ codeflash Optimization PR opened by Codeflash AI label Jul 22, 2025
@codeflash-ai codeflash-ai bot requested a review from misrasaurabh1 July 22, 2025 06:12
@codeflash-ai codeflash-ai bot deleted the codeflash/optimize-sigmoid_stable-mde515y6 branch July 24, 2025 20:54
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.

1 participant