-
Notifications
You must be signed in to change notification settings - Fork 29
Optimize Wigner Function and Improve make_grid with @njit for Better Performance and Memory Efficiency #504
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
PR-Agent was enabled for this repository. To continue using it, please link your git user with your CodiumAI identity here. PR Reviewer Guide 🔍Here are some key observations to aid the review process:
|
|
PR-Agent was enabled for this repository. To continue using it, please link your git user with your CodiumAI identity here. PR Code Suggestions ✨Explore these optional code suggestions:
|
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## develop #504 +/- ##
===========================================
- Coverage 89.77% 89.61% -0.16%
===========================================
Files 92 92
Lines 6072 6087 +15
===========================================
+ Hits 5451 5455 +4
- Misses 621 632 +11
... and 1 file with indirect coverage changes Continue to review full report in Codecov by Sentry.
|
mrmustard/physics/wigner.py
Outdated
| def make_grid(q_vec: np.ndarray, p_vec: np.ndarray, hbar: float): | ||
| r"""Returns two coordinate matrices `Q` and `P` from coordinate vectors | ||
| `q_vec` and `p_vec`, along with the grid over which Wigner functions can be | ||
| discretized. | ||
| """ | ||
| Q = np.outer(q_vec, np.ones_like(p_vec)) | ||
| P = np.outer(np.ones_like(q_vec), p_vec) | ||
| return Q, P, (Q + P * 1.0j) / np.sqrt(2 * hbar) | ||
| n_q = q_vec.size | ||
| n_p = p_vec.size | ||
| Q = np.empty((n_q, n_p), dtype=np.float64) | ||
| P = np.empty((n_q, n_p), dtype=np.float64) | ||
| sqrt_factor = 1.0 / np.sqrt(2.0 * hbar) | ||
|
|
||
| for i in range(n_q): | ||
| q = q_vec[i] | ||
| for j in range(n_p): | ||
| p = p_vec[j] | ||
| Q[i, j] = q | ||
| P[i, j] = p | ||
|
|
||
| grid = (Q + 1j * P) * sqrt_factor | ||
| return Q, P, grid |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion: Use NumPy's vectorized operations to improve performance in grid creation
| def make_grid(q_vec: np.ndarray, p_vec: np.ndarray, hbar: float): | |
| r"""Returns two coordinate matrices `Q` and `P` from coordinate vectors | |
| `q_vec` and `p_vec`, along with the grid over which Wigner functions can be | |
| discretized. | |
| """ | |
| Q = np.outer(q_vec, np.ones_like(p_vec)) | |
| P = np.outer(np.ones_like(q_vec), p_vec) | |
| return Q, P, (Q + P * 1.0j) / np.sqrt(2 * hbar) | |
| n_q = q_vec.size | |
| n_p = p_vec.size | |
| Q = np.empty((n_q, n_p), dtype=np.float64) | |
| P = np.empty((n_q, n_p), dtype=np.float64) | |
| sqrt_factor = 1.0 / np.sqrt(2.0 * hbar) | |
| for i in range(n_q): | |
| q = q_vec[i] | |
| for j in range(n_p): | |
| p = p_vec[j] | |
| Q[i, j] = q | |
| P[i, j] = p | |
| grid = (Q + 1j * P) * sqrt_factor | |
| return Q, P, grid | |
| @njit | |
| def make_grid(q_vec: np.ndarray, p_vec: np.ndarray, hbar: float): | |
| r"""Returns two coordinate matrices `Q` and `P` from coordinate vectors | |
| `q_vec` and `p_vec`, along with the grid over which Wigner functions can be | |
| discretized. | |
| """ | |
| Q, P = np.meshgrid(q_vec, p_vec, indexing='ij') | |
| sqrt_factor = 1.0 / np.sqrt(2.0 * hbar) | |
| grid = (Q + 1j * P) * sqrt_factor | |
| return Q, P, grid |
|
Hi @JakeKitchen we are finally getting around to this PR. Sorry for holding off for so long - many things were changing and it never felt like the moment was right. Since so much has changed, would you be able to merge develop into your branch (or open a fresh PR)? |
|
#593 opened a new PR : D |
User description
Optimized Wigner Function Iterative Computation
Context:
The
_wigner_discretized_iterativefunction calculates the Wigner function iteratively,which is essential for simulating quantum states in continuous variable quantum mechanics.
The original implementation had redundant operations, recalculations, and excessive memory
allocations, leading to performance bottlenecks. The
make_gridfunction was also optimizedwith
@njitto further enhance performance. This update improves both mathematical efficiencyand memory management.
Description of the Change:
avoid redundant calculations in each iteration.
the beginning and stored in an array. This reduces overhead inside nested loops.
function reuses memory by swapping matrices, which reduces memory allocations.
make_gridFunction:make_gridfunction was updated to use@njitto accelerate its performance.QandPcoordinate matrices are optimized to reduce overhead.sqrt_factoris used to avoid redundant calculations inside nested loops.@njit, the function is now compliant with Numba’s JIT compilation, allowingfaster and more efficient execution.
Benefits:
Improved Mathematical Efficiency:
values such as exponential terms and square roots.
the function more computationally efficient.
ensuring cache-friendlier execution.
Better Performance:
costly memory allocations, improving speed.
make_grid: Using@njitinmake_gridimproves both speed and memory efficiency,enabling seamless integration with the rest of the optimized functions.
Numba Compliance:
@njitconstraints,avoiding common type-related issues.
Possible Drawbacks:
increases memory usage at the beginning, but this is offset by performance gains during execution.
Related GitHub Issues:
NA
PR Type
enhancement, bug_fix
Description
Wireclass intensors.pyby usingfieldfor attribute initialization and improved dictionary comprehensions for better performance.make_gridfunction inwigner.pyby preallocating arrays and optimizing the computation of coordinate matrices._wigner_discretized_iterativefunction by precomputing exponential terms and square roots, reducing redundant calculations, and reusing matrices to enhance memory efficiency.Changes walkthrough 📝
tensors.py
Optimize tensor network wire and shape handlingmrmustard/math/tensor_networks/tensors.py
Wireclass attributes usingfield.comprehensions.
AdjointViewandDualViewinitializations.wigner.py
Enhance Wigner function computation efficiencymrmustard/physics/wigner.py
make_gridfunction with preallocated arrays._wigner_discretized_iterative.