Skip to content

⚡️ Speed up function erfinv by 148% - #7

Open
codeflash-ai[bot] wants to merge 1 commit into
masterfrom
codeflash/optimize-erfinv-max95krv
Open

⚡️ Speed up function erfinv by 148%#7
codeflash-ai[bot] wants to merge 1 commit into
masterfrom
codeflash/optimize-erfinv-max95krv

Conversation

@codeflash-ai

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

Copy link
Copy Markdown

📄 148% (1.48x) speedup for erfinv in keras/src/backend/jax/math.py

⏱️ Runtime : 22.9 milliseconds 9.26 milliseconds (best of 139 runs)

📝 Explanation and details

Here’s an optimized rewrite for your provided code. The current version is already fairly minimal, but calling jax.lax.erf_inv dispatches to JAX internals, and there is a slightly faster way by using jax.scipy.special.erfinv, which applies XLA fusion/matching and is the preferred interface for element-wise operations in JAX. Also, if you expect input arrays, using @jax.jit for Just-In-Time compilation will further optimize its runtime.

Here’s the faster rewrite.

Key changes:

  • Uses jax.scipy.special.erfinv for best-in-class performance and compatibility.
  • Decorated the function with @jax.jit for auto-compilation and faster repeated calls, especially for array inputs.

Return values and signature are unchanged.

Correctness verification report:

Test Status
⚙️ Existing Unit Tests 🔘 None Found
🌀 Generated Regression Tests 2041 Passed
⏪ Replay Tests 🔘 None Found
🔎 Concolic Coverage Tests 🔘 None Found
📊 Tests Coverage 100.0%
🌀 Generated Regression Tests Details
import math  # for math.erf, math.erfc, math.sqrt, math.isnan, math.isinf, math.isclose

# function to test
import jax
# imports
import pytest  # used for our unit tests
from keras.src.backend.jax.math import erfinv


# Helper: Reference implementation using math.erf and binary search for scalar x in (-1, 1)
def reference_erfinv(y, tol=1e-12, max_iter=100):
    # Only valid for -1 < y < 1
    if not (-1 < y < 1):
        raise ValueError("Input out of domain for reference_erfinv")
    # Use binary search in [-10, 10]
    lo, hi = -10.0, 10.0
    for _ in range(max_iter):
        mid = (lo + hi) / 2.0
        erf_mid = math.erf(mid)
        if abs(erf_mid - y) < tol:
            return mid
        if erf_mid < y:
            lo = mid
        else:
            hi = mid
    return (lo + hi) / 2.0

# -------------------------
# 1. Basic Test Cases
# -------------------------

def test_erfinv_zero():
    # erf(0) == 0, so erfinv(0) == 0
    codeflash_output = erfinv(0.0); result = codeflash_output



def test_erfinv_reference_match():
    # Compare against reference implementation for random values in (-0.99, 0.99)
    test_values = [-0.99, -0.75, -0.33, 0.12, 0.42, 0.77, 0.99]
    for x in test_values:
        ref = reference_erfinv(x)
        codeflash_output = erfinv(x); result = codeflash_output

# -------------------------
# 2. Edge Test Cases
# -------------------------

def test_erfinv_domain_edges():
    # erfinv(1) == +inf, erfinv(-1) == -inf
    codeflash_output = erfinv(1.0); pos_inf = codeflash_output
    codeflash_output = erfinv(-1.0); neg_inf = codeflash_output

def test_erfinv_near_domain_edges():
    # Values very close to -1 and 1 should yield very large magnitude results
    for x in [1-1e-16, -1+1e-16]:
        codeflash_output = erfinv(x); result = codeflash_output


def test_erfinv_nan():
    # erfinv(nan) should return nan
    codeflash_output = erfinv(float('nan')); result = codeflash_output

def test_erfinv_inf():
    # erfinv(+inf) and erfinv(-inf) should return nan
    for x in [float('inf'), float('-inf')]:
        codeflash_output = erfinv(x); result = codeflash_output

def test_erfinv_extreme_small_values():
    # For very small values, erfinv(x) ~ x * sqrt(pi)/2
    for x in [-1e-10, 1e-10, -1e-20, 1e-20]:
        approx = x * math.sqrt(math.pi) / 2
        codeflash_output = erfinv(x); result = codeflash_output

# -------------------------
# 3. Large Scale Test Cases
# -------------------------

def test_erfinv_many_values():
    # Test erfinv on a large number of values in (-0.999, 0.999)
    # Should not raise or return nan for valid domain
    values = [(-0.999 + 1.998 * i / 999) for i in range(1000)]
    for x in values:
        codeflash_output = erfinv(x); result = codeflash_output

def test_erfinv_vectorized_accuracy():
    # For a large vector, math.erf(erfinv(x)) ~ x
    values = [(-0.999 + 1.998 * i / 999) for i in range(1000)]
    for x in values:
        codeflash_output = erfinv(x); inv = codeflash_output
        back = math.erf(inv)



import math  # for math.erf, math.erfc, math.sqrt, math.isclose, etc.
import random  # for generating random floats

# function to test
import jax
# imports
import pytest  # used for our unit tests
from keras.src.backend.jax.math import erfinv

# ------------------------------
# 1. BASIC TEST CASES
# ------------------------------

def test_erfinv_zero():
    # erf(0) == 0, so erfinv(0) == 0
    assert_close(erfinv(0.0), 0.0)





def test_erfinv_nan_input():
    # erfinv(nan) should return nan
    codeflash_output = erfinv(float('nan')); result = codeflash_output




def test_erfinv_symmetry():
    # erfinv(-x) == -erfinv(x)
    for x in [-0.99, -0.5, -0.1, 0.0, 0.1, 0.5, 0.99]:
        codeflash_output = erfinv(x); y1 = codeflash_output
        codeflash_output = erfinv(-x); y2 = codeflash_output
        assert_close(y1, -y2)

# ------------------------------
# 3. LARGE SCALE TEST CASES
# ------------------------------

To edit these changes git checkout codeflash/optimize-erfinv-max95krv and push.

Codeflash

Here’s an optimized rewrite for your provided code. The current version is already fairly minimal, but calling `jax.lax.erf_inv` dispatches to JAX internals, and there is a slightly faster way by using `jax.scipy.special.erfinv`, which applies XLA fusion/matching and is the preferred interface for element-wise operations in JAX. Also, if you expect input arrays, using `@jax.jit` for Just-In-Time compilation will further optimize its runtime.

Here’s the faster rewrite.



**Key changes:**
- Uses `jax.scipy.special.erfinv` for best-in-class performance and compatibility.
- Decorated the function with `@jax.jit` for auto-compilation and faster repeated calls, especially for array inputs.

Return values and signature are unchanged.
@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 01: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