⚡️ Speed up method LogitDynamics.time_series by 21%#105
Open
codeflash-ai[bot] wants to merge 1 commit intomainfrom
Open
⚡️ Speed up method LogitDynamics.time_series by 21%#105codeflash-ai[bot] wants to merge 1 commit intomainfrom
LogitDynamics.time_series by 21%#105codeflash-ai[bot] wants to merge 1 commit intomainfrom
Conversation
The optimized code achieves a **20% speedup** through three key changes that reduce overhead in computationally intensive paths: ## Key Optimizations ### 1. **Eliminated Redundant `check_random_state` Calls in Hot Loop** The original code called `check_random_state(random_state)` **three times per iteration** in `time_series`: - Once before the loop (necessary) - Once inside the loop before calling `_play` (redundant) - Once again when `init_actions is None` (acceptable) **Impact:** The line profiler shows this redundant call consumed **35.2% of total runtime** (66.3ms out of 188.4ms). The optimized version calls it **once** at the start of `time_series`, then reuses the validated random state throughout the loop, eliminating ~8,300 redundant validation calls. ### 2. **Replaced List Slice Copy with Direct Assignment** Changed `out[t, :] = actions[:]` to `out[t, :] = actions`. The slice copy `actions[:]` creates an unnecessary intermediate list copy on every iteration. **Impact:** While small per iteration (~80ns), this eliminates 8,300+ allocations in typical workloads, reducing memory pressure. ### 3. **Optimized Initialization with `np.moveaxis` and `keepdims`** Replaced the transpose pattern: ```python payoff_array_rotated = player.payoff_array.transpose((*range(1, self.N), 0)) payoff_array_rotated -= payoff_array_rotated.max(axis=-1)[..., np.newaxis] ``` with: ```python payoff_array_rotated = np.moveaxis(player.payoff_array, 0, -1) payoff_array_rotated -= payoff_array_rotated.max(axis=-1, keepdims=True) ``` **Why faster:** `np.moveaxis` is a simpler operation than constructing complex transpose tuples, and `keepdims=True` avoids the `[..., np.newaxis]` indexing overhead for broadcasting. ### 4. **Minor: Generator Expression Instead of List Comprehension** In `random_pure_actions`, changed from list comprehension to generator expression. This defers evaluation until `tuple()` consumes it, avoiding an intermediate list allocation. ## Test Case Analysis The optimizations excel particularly on: - **Long time series** (500-1000 steps): 25-30% speedup as redundant checks dominate - **Already-validated random states** (RandomState/Generator objects): 10-30% speedup since the object bypasses the integer-seed creation overhead - **Multiple players**: 17-18% speedup as the initialization optimization compounds across players The optimization maintains identical deterministic behavior (same random sequences) while reducing computational overhead in the critical path where `time_series` is called repeatedly with long sequences—typical usage in game theory simulations.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
📄 21% (0.21x) speedup for
LogitDynamics.time_seriesinquantecon/game_theory/logitdyn.py⏱️ Runtime :
32.9 milliseconds→27.2 milliseconds(best of91runs)📝 Explanation and details
The optimized code achieves a 20% speedup through three key changes that reduce overhead in computationally intensive paths:
Key Optimizations
1. Eliminated Redundant
check_random_stateCalls in Hot LoopThe original code called
check_random_state(random_state)three times per iteration intime_series:_play(redundant)init_actions is None(acceptable)Impact: The line profiler shows this redundant call consumed 35.2% of total runtime (66.3ms out of 188.4ms). The optimized version calls it once at the start of
time_series, then reuses the validated random state throughout the loop, eliminating ~8,300 redundant validation calls.2. Replaced List Slice Copy with Direct Assignment
Changed
out[t, :] = actions[:]toout[t, :] = actions. The slice copyactions[:]creates an unnecessary intermediate list copy on every iteration.Impact: While small per iteration (~80ns), this eliminates 8,300+ allocations in typical workloads, reducing memory pressure.
3. Optimized Initialization with
np.moveaxisandkeepdimsReplaced the transpose pattern:
with:
Why faster:
np.moveaxisis a simpler operation than constructing complex transpose tuples, andkeepdims=Trueavoids the[..., np.newaxis]indexing overhead for broadcasting.4. Minor: Generator Expression Instead of List Comprehension
In
random_pure_actions, changed from list comprehension to generator expression. This defers evaluation untiltuple()consumes it, avoiding an intermediate list allocation.Test Case Analysis
The optimizations excel particularly on:
The optimization maintains identical deterministic behavior (same random sequences) while reducing computational overhead in the critical path where
time_seriesis called repeatedly with long sequences—typical usage in game theory simulations.✅ Correctness verification report:
🌀 Click to see Generated Regression Tests
To edit these changes
git checkout codeflash/optimize-LogitDynamics.time_series-mkp2g50land push.