Skip to content

feat(compression): add DECODE operator insertion#3624

Open
rkuester wants to merge 4 commits into
tensorflow:mainfrom
rkuester:feat-decode-submit
Open

feat(compression): add DECODE operator insertion#3624
rkuester wants to merge 4 commits into
tensorflow:mainfrom
rkuester:feat-decode-submit

Conversation

@rkuester

@rkuester rkuester commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Insert DECODE operators before consumers of compressed tensors. Each
consumer gets its own DECODE operator to support alternate decompression
memory, which resets allocations between DECODE invocations.

After insertion, compressed tensors are rewritten to hold encoded data
as UINT8 with shape matching byte count.

Compression tooling only; adds decode_insert.py and its test, no
runtime changes.

Part of the DECODE compression-tooling stack.

BUG=#3256

Insert DECODE operators before consumers of compressed tensors. Each
consumer gets its own DECODE operator to support alternate decompression
memory, which resets allocations between DECODE invocations.

After insertion, compressed tensors are rewritten to hold encoded data
as UINT8 with shape matching byte count.

BUG=part of tensorflow#3256
@rkuester rkuester requested a review from a team as a code owner July 6, 2026 20:42
@rkuester rkuester added the ci:full Triggers the comprehensive cross-platform test suite. label Jul 6, 2026
@rkuester rkuester temporarily deployed to integration-test July 6, 2026 20:42 — with GitHub Actions Inactive
@rkuester rkuester requested a review from veblush July 6, 2026 22:34
if not consumers:
# Check if tensor is a subgraph output
is_output = tensor in subgraph.outputs
if is_output:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess if it_output should be outside of if not consumers? It might be consumed and an oiutput of subgraph?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right: the check missed tensors that are both consumed by an operator and listed as a subgraph output, so a subgraph would have output the encoded bytes instead of the decoded values. Addressed in 3999889 by treating the output list as one more consumer, fed by a DECODE appended after the last operator.

f3a8e56 pulls forward a fix from later in the series: separate DECODEs per tensor don't work with alternate decompression memory when the decoded values are needed at the same time, and with output handling added, it's even more worth getting this right initially than rewriting it later. It's a separate commit for easy review, relying on the squash when the PR merges.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rkuester @veblush Passing the output of DECODE to or from a subgraph simply won't work (for a number of reasons, primarily involving the WHILE operator and the tensor copying that occurs between subgraphs and the calling operator). The design document will be updated to address what to do in this situation.

for consumer in info.consumers:
consumer_pairs.append((consumer, info))

consumer_pairs.sort(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be slow because of subgraph.operators.index in the sort?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in 50f2fcf: a position map built once per subgraph replaces the scans in the sort and insertions.

rkuester added 3 commits July 7, 2026 12:50
A compressed tensor can be listed in a subgraph's output list, where it
is read not by an operator, but by the operator calling the subgraph
(IF, WHILE), which copies subgraph outputs when the subgraph returns,
or by the client, which reads model outputs after invocation.

DECODE insertion previously checked the output list only for tensors
with no consumers, and refused those as unsupported. A tensor both
consumed and listed as an output slipped through: the pass rewired its
consumers to decoded values, then rewrote the tensor to hold encoded
bytes, which the output list delivered as if decoded.

Treat the output list as one more consumer, one which reads its tensors
only after the last operator runs. Append a DECODE after the last
operator for each compressed tensor in the output list, and rewire the
list entry to the decoded value.

BUG=part of tensorflow#3256
A consumer reading several compressed tensors needs all their decoded
values at once, but under alternate decompression memory, values
produced by different DECODE operators cannot coexist: each DECODE
resets the allocation offset during Prepare, placing every DECODE's
outputs at the same address, so each DECODE overwrites the outputs of
the one before it. Decoding a consumer's tensors with separate DECODE
operators corrupts all but the last value.

Decode all compressed tensors read by one consumer with a single
DECODE operator carrying one encoded/ancillary input pair and one
output per tensor. Outputs of a single DECODE coexist, since the
allocation reset happens between operators, not between the outputs
of one.

The subgraph output list, treated as one more consumer, gets the same:
one DECODE, appended after the last operator, decodes every compressed
tensor in the list.

BUG=part of tensorflow#3256
DECODE insertion sorted consumers and located insertion points with
list.index, a linear scan of the operator list per lookup. Build a map
of operator positions once per subgraph and consult it instead.

The positions recorded before any insertion remain correct throughout:
consumers are handled in reverse position order, so each insertion
falls after every consumer still to be processed.

BUG=part of tensorflow#3256
@rkuester rkuester deployed to integration-test July 7, 2026 18:48 — with GitHub Actions Active
@rkuester rkuester requested review from ddavis-2015 and veblush July 7, 2026 19:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci:full Triggers the comprehensive cross-platform test suite.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants