Repository navigation
Run relation attention on packed tokens in GraphTransformerEncoder - #857
Draft
kmontemayor2-sc wants to merge 32 commits into
Draft
kmontemayor2-sc wants to merge 32 commits into
kmontemayor2-sc wants to merge 32 commits into
Conversation
… a per-layer pair bias edge_type_bilinear and edge_type_hgt no longer force the padded path. Each layer scatters the per-edge relation scores into the padded-grid pair bias (on top of any pairwise bias) and attends on the grid SDPA backend. The packed layout now carries relation edges for either relation mode. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…r syncs or breaks a compiled graph to_dense_batch compared the longest sequence with max_seq_len on the host and the boolean gather ran nonzero; both broke every compiled layer that uses the grid backend into several graphs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d the pairwise-bias compile caveat Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…id per forward, shared score scatter - Relation attention scores use matmul plus an elementwise sum instead of a three-operand einsum, whose opt_einsum path guarded on per-relation edge counts and recompiled every batch under torch.compile. - The padded-key mask, per-key and per-pair biases are combined into one grid once per encoder forward (PackedAttentionBias.grid); layers use it as is and relation attention adds its scores to a single copy. - The padded and packed paths share _accumulate_relation_attention_scores, which also drops the padded path's per-relation host reads. - Tests: pairwise bias with relation attention against the padded path, and a compile test over batches with different edge counts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A one-L4 measurement showed rebuilding the grid per layer wins or ties the once-per-forward grid: compiled 4-9% faster, 20-25% lower compiled-inference peak, equal training memory. Remove PackedAttentionBias.grid and the once-per-forward build; relation attention copies bias.per_pair per layer. The matmul+sum relation scores and the shared score-accumulation helper stay. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The whole-encoder compile tests ran only at inference. This CUDA test compiles the whole encoder with inductor in train mode. For each config it compares the loss and every parameter gradient to the eager encoder over five batches, and checks that the batches after the second do not recompile. Configs: anchor_only and neighbor readout, per-key anchor bias, pairwise bias (with both readouts), bilinear and HGT relation attention, and the edge_type_attention relation message mode. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> # Conflicts: # gigl/nn/graph_transformer.py
# Conflicts: # gigl/nn/graph_transformer.py
_lookup_pairwise_relative_features returns None only without pairwise matrices, which the configured projection rules out. The explicit check also gives _pairwise_pair_bias a Tensor type. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The pairwise projection output is permuted to [batch, heads, seq, seq], so its last dim has a stride of num_heads. Every layer's attention read that strided bias. One contiguous copy in _packed_attention_bias removes the strided read from each layer. One L4, 3 layers, hidden 512, 8 heads, max_seq_len 256, random weights, pairwise bias. Same process and batches; strided bias in every layer vs contiguous once: - inference (512 anchors, fp32+TF32), eager: 290.9 vs 188.6 ms, peak 7920 vs 5615 MiB - inference, per-layer compile: 183.9 vs 147.0 ms, peak 5163 vs 5419 MiB - training (bf16 autocast), eager: 661.8 vs 370.3 ms, peak 8726 vs 6263 MiB - training, per-layer compile: 368.1 vs 276.4 ms, peak 6666 vs 5452 MiB fp32 parity of the two: output max abs diff 1.3e-7, gradient relative L2 5.3e-7. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> # Conflicts: # gigl/nn/graph_transformer.py
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> # Conflicts: # CHANGELOG.md
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Conflicts resolved: CHANGELOG.md (kept the PR 5c entry with the readout and khop wording), tests/unit/nn/packed_graph_transformer_test.py (kept the self-loop and all-filtered assertions inside the shared filtered-edge helper; took the PPR hop-embedding test).
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
… accumulator Tests now call _add_relation_attention_bias with attn_bias=None. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This branch has not been deployed
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.
Summary
GraphTransformerEncoderon CUDA now keeps configs withrelation_attention_mode="edge_type_bilinear"or"edge_type_hgt"on the packed-token path instead of falling back to padded sequences. Together with the earlier packed-path PRs in this stack, this leaves onlyppr_weight,ppr_relation_features, non-khopsequences,hop_distance > 4, CPU, and oversized k-hop candidate sets on the padded path.The PR also removes a per-batch cost from the packed pairwise attention bias (the bias is now made contiguous once per forward) and adds a training test that compiles the whole encoder.
Approach
.item()reads that made the padded path graph-break undertorch.compile, and the packed path does not recompile when per-relation edge counts change between batches..contiguous()once per forward so each layer's attention reads a dense tensor.User-facing changes
relation_attention_modevaluesedge_type_bilinearandedge_type_hgtare accepted on the packed path (anyrelation_message_mode, both readout modes, with or without pairwise biases). Embeddings and gradients match the padded path up to float error. No config or API changes.GraphTransformerEncoderLayer.forward_packednow raisesValueErroronly whenlayout.relation_edgesis missing for a relation attention or message mode; it no longer rejects relation attention.CHANGELOG.mdentry now lists every config the packed path supports at this point in the stack, including the neighbor readout, attention dropout and pairwise biases from the earlier PRs.torch.compile, the packed path builds 35 graphs in inference (3 after the first batch) and 60 in training, with long warmup (about 108 s in inference). Timing is stable after warmup. This is not fixed here.Verification
ruff check,ruff format --checkanddprint checkpass at this tip.make unit_test_py(includingtype_check, CPU) at an earlier tip of this branch: 1563 tests, OK, 45 skipped.outsampling direction, neighbor readout, pairwise bias), training gradients, filtered-edge gradients, and no recompiles across batches.tests/unit/nn/packed_attention_test.py,tests/unit/nn/packed_graph_transformer_test.py,tests/unit/nn/graph_transformer_test.py,tests/unit/transforms/graph_transformer_test.py,tests/unit/transforms/static_khop_test.py) at this tip: 322 passed, 0 skipped.Performance
One L4, torch 2.8.0+cu128, random weights, 3 layers, hidden 512, 8 heads,
anchor_onlyreadout, max_seq_len 256. Inference: 512 anchors per batch, fp32 with TF32, mean of 40 batches. Training: bf16 autocast, mean of 24 steps. Times are ms per batch or step; memory is peak allocated.Relation attention
edge_type_bilinear, padded vs packed:The padded per-layer compile has 52 (inference) and 62 (training) graph breaks in
_get_relation_segmentsand.item()reads; the packed path has 0 and 1. The compiled ratios therefore flatter the packed path; the eager ratios (1.4x inference, 1.6x training) are the conservative ones.Pairwise bias, padded vs packed, at this PR's tip:
The base branch's packed pairwise-bias inference was 293.2 ms eager and 184.9 ms per-layer compile (same config, measured at the base tip). In a same-process A/B, the contiguous bias takes packed inference eager from 290.9 to 188.6 ms (fp32 output max abs diff 1.3e-7, gradient relative L2 5.3e-7). Per-layer-compile inference peak rises 256 MiB (5154 to 5410 MiB).
🤖 Generated with Claude Code