Replace two-einsum OuterProductMean with fused three-way einsum#674
Replace two-einsum OuterProductMean with fused three-way einsum#674mooreneural wants to merge 1 commit into
Conversation
|
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
|
@googlebot rescan |
Manual testing: serialization bug fix (
|
* Reported in #674 by @mooreneural, thanks! PiperOrigin-RevId: 922659727 Change-Id: I7db6bca087a2bf3c4b2c327e360b804ddf72c9d4
|
GPU memory optimization benchmark results on RTX 5080 (16 GB VRAM), JAX 0.10.2, bfloat16 OuterProductMean at N=1024 residues, MSA depth=512:
3.56x memory reduction with no throughput regression (0.97x, within noise). At larger sequence lengths (N=2048+) where the standard path's intermediate grows to ~1 GB+, |
|
Thank you for pulling in the docstring fixes, @Augustin-Zidek I appreciate the acknowledgment. I'll keep the remaining items in this PR (serialization fix + GPU optimization) available for review whenever the team has bandwidth. |
|
Hi, thanks for submitting this PR. What worries is the size: 1.7k lines code is it hard to review dilligently and also it would increas our maintenance burden (for comparison, the entire AlphaFold 3 source code is 24k lines of code, so this PR increases its size by 7%). Could you update the PR to contain only the outer product change and nothing more (i.e. remove the typo fixes, unrelated parallel code and the unrelated XLA cache code)? If I didn't miss anything, this change should be just a few line change in Moreover, how did you test this? Did you test that this doesn't change numerics? |
|
Hi @Augustin-Zidek, I've stripped the PR down to just the OuterProductMean change; parallel.py, xla_cache.py, the benchmark script, and the serialization fix are all removed. The test files are also removed since AF3 doesn't use that pattern. What remains (160 lines total):
Numerical testing: verified on RTX 5080, JAX 0.10.2, bfloat16, N=1024 residues, MSA depth=512:
|
|
Thanks, could you squash and rebase this on top of HEAD? There are some license changes and changes from other commits in this PR that should not be there. Moreover, is there any reason to put this behind a flag and in a separate module? I.e. if it is the same speed and uses less memory, why not use that by default? I would also inline the implementation, so the change truly becomes just a single file change over a few lines of code. |
|
@Augustin-Zidek, totally agree on both points, will squash to a single commit and rebase onto HEAD, and making it the default (no flag, inlined directly in modules.py) is the right call. The change is a strict improvement so there's no reason to gate it. Making it default should meaningfully extend what’s feasible on consumer and mid-range GPUs without any tradeoff. I'll have the cleaned-up push ready in a few hours. Thanks for the continued engagement on this. I look forward to contributing to AF3. |
The standard compute_chunk materialises a [N, C_outer, C_outer, chunk] intermediate (~256 MB at N=1024, C=32, chunk=128, bfloat16). Replacing the two separate einsums with a single three-way einsum lets XLA contract the two C_outer dimensions before summing over the MSA axis, reducing peak intermediate memory to ~72 MB (3.56x reduction). Verified numerically: max absolute difference vs original = 0.0 in bfloat16 on RTX 5080, JAX 0.10.2, N=1024 residues, MSA depth=512.
|
@Augustin-Zidek Re-ran numerical verification after inlining: Output shape: (128, 1024, 128) Single file change, 5 insertions, 3 deletions. |
* Uses significantly less RAM (256 -> 72 MB for 1024-token input). Inspired by #674, thank you very much for the suggestion @mooreneural. PiperOrigin-RevId: 941052434 Change-Id: I0f1cfa6a16f7f2da4371a0c0c53642ef26b1328c
|
Hello Clay, I've now done this in 7b4c2a5, sorry for the delay. I got the code even simpler by removing the unnecessary transposes before and after the einsum. I will make sure to credit you in the release notes for v3.0.4. Thanks again for this optimisation! |
|
@Augustin-Zidek Wow! How exciting. Thank you so much for taking my suggestions into the next release. I wanted to ask if you'd connect with me on LinkedIn https://www.linkedin.com/in/claynovel Best, |
Replaces the two-einsum OuterProductMean chunk computation with a single
three-way einsum, letting XLA contract the two C_outer dimensions before
summing over the MSA axis. Single file change, always-on.
The change
Standard path (~256 MB intermediate at N=1024, C_outer=32, chunk=128, bfloat16):
Fused path (~72 MB peak):
Numerical testing
Verified on RTX 5080, JAX 0.10.2, bfloat16, N=1024 residues, MSA depth=512:
Files changed