⚡️ Speed up function hh_payoff_player by 72%
#76
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.
📄 72% (0.72x) speedup for
hh_payoff_playerinquantecon/game_theory/polymatrix_game.py⏱️ Runtime :
518 milliseconds→300 milliseconds(best of13runs)📝 Explanation and details
The optimized code achieves a 72% speedup by eliminating the expensive nested list comprehension with
np.vstackthat dominated the original implementation (64.1% of runtime).Key Optimizations:
Pre-allocated Arrays: Instead of building
hh_actions_and_payoffsthrough repeatednp.vstackandnp.hstackcalls (which create many intermediate arrays), the optimized version pre-allocateshh_actionsandcombined_payoffsarrays upfront based on computed dimensions.Vectorized One-Hot Encoding: The original code used
np.eye(nfg.nums_actions[p])[action_combination[p]]inside a list comprehension for each action combination. The optimized version uses advanced indexinghh_actions[np.arange(n_combinations), col_offset + actions_p] = 1.0to set all one-hot values in a single vectorized operation per player.Direct Array Construction: Converting
product(*action_ranges)to a NumPy array upfront enables efficient column-wise slicing (action_combinations[:, p]) instead of repeatedly unpacking tuples in list comprehensions.Performance Analysis:
The line profiler shows the critical bottleneck moved from array construction (64.1% → 0.8%) to the
lstsqcall (35% → 97% of remaining time), which is unavoidable. Test results show consistent speedups:Impact on Workloads:
The
function_referencesshow this function is called in a hot path withinPolymatrixGame.from_nf(), which iterates over all players and their actions (nested loops). For a game with N players and A actions each, this means N×A calls tohh_payoff_player. The optimization's impact scales quadratically with game size, making it particularly valuable for the library's typical use cases involving multi-player games with numerous actions.The optimizations are most effective for games with many players and actions (see the 196% speedup for 5-player games), while maintaining correctness for edge cases like single-action scenarios.
✅ Correctness verification report:
🌀 Click to see Generated Regression Tests
To edit these changes
git checkout codeflash/optimize-hh_payoff_player-mjw5cd12and push.