Skip to content

[bugfix] track delta embeddings by owner-qualified FQN - #607

Merged
tiankongdeguiji merged 5 commits into
alibaba:masterfrom
tiankongdeguiji:codex/fix-delta-embedding-fqn-tracking
Jul 27, 2026
Merged

[bugfix] track delta embeddings by owner-qualified FQN#607
tiankongdeguiji merged 5 commits into
alibaba:masterfrom
tiankongdeguiji:codex/fix-delta-embedding-fqn-tracking

Conversation

@tiankongdeguiji

@tiankongdeguiji tiankongdeguiji commented Jul 26, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • track touched embedding IDs by canonical, owner-qualified table FQN
  • keep same-named tables under different sharded EC/EBC owners independent
  • use FQN keys throughout shard metadata, static weights, dynamic modules, lookup validation, and parquet output
  • omit retained FQN buckets that have no unread IDs, allowing later quiet dump intervals to complete normally
  • use TorchRec 1.7's concrete owner, grouped-lookup, embedding-config, sharding-metadata, ShardedTensor, and DTensor interfaces
  • fail fast on unsupported lookup and weight implementations
  • bump the TorchEasyRec version to 1.3.6

Root cause

The previous tracking path built global mappings keyed by raw table name. When separate sharded modules owned tables with the same name, the later mapping could overwrite the earlier one, causing feature mappings, touched IDs, and embedding lookups to resolve to the wrong owner.

Additionally, DeltaStoreTrec.delete(up_to_idx=...) retains FQN buckets with empty lookup lists. A later interval with no new IDs for a previously seen table could therefore reach torch.cat([]) inside TorchRec's get_unique() implementation instead of reaching the dumper's empty-output path.

Implementation

The delta dump now has an ID-only tracker built directly on TorchRec's abstract ModelDeltaTracker. Each lookup callback uses its owning sharded module to resolve a module-local feature-to-FQN mapping, so IDs remain attached to the exact EC/EBC owner that produced them.

DeltaEmbeddingDumper carries that FQN directly through metadata and storage collection and into table_fqn output. Dynamicemb extracts only the final table-name component where its table index API requires it; no fqn_to_table mapping is introduced.

The tracker builds unique rows only from unread lookups in each FQN bucket and omits buckets with no unread IDs. Consumer cursors, delete-on-read, compaction, and empty-shard behavior remain unchanged.

The implementation intentionally uses the supported TorchRec 1.7 interfaces instead of accepting arbitrary lookalike objects through defensive reflection. The sole remaining getattr selects the active protobuf oneof field. The parquet schema, configuration, and dump scheduling are unchanged.

Test Plan

Run in the tzrec130 environment:

  • PYTHONPATH=. python -m tzrec.utils.delta_embedding_dump_test — 43 tests passed, including two consecutive intervals where the second has no unread IDs, duplicate EC/EBC owners, row-wise sharding, static and DTensor weights, pause guards, dynamicemb, and multi-process DMP regressions
  • pre-commit run -a — passed
  • git diff --check — passed
  • python scripts/pyre_check.py — blocked by existing environment/repository constraints: the committed .pyre_configuration is invalid JSON, and the Pyre backend requires newer GLIBC/GLIBCXX symbols than the host provides

ModelDeltaTrackerTrec keyed raw table names globally, so same-named tables owned by different sharded modules overwrote mappings. Track callback IDs, weights, dynamic modules, and shard metadata by owner-qualified FQN.
@tiankongdeguiji
tiankongdeguiji marked this pull request as ready for review July 26, 2026 04:41
@tiankongdeguiji tiankongdeguiji added the codex-review Let Codex Review label Jul 26, 2026
@github-actions github-actions Bot removed the codex-review Let Codex Review label Jul 26, 2026
@tiankongdeguiji tiankongdeguiji changed the title [bugfix] track delta embeddings by table FQN [bugfix] track delta embeddings by owner-qualified FQN Jul 26, 2026
@tiankongdeguiji
tiankongdeguiji marked this pull request as draft July 26, 2026 04:43
@tiankongdeguiji
tiankongdeguiji marked this pull request as ready for review July 26, 2026 04:45
Comment thread tzrec/utils/delta_embedding_dump.py Outdated
index_start = max(self.per_consumer_batch_idx.values())
if index_start < index_end:
self.store.compact(index_start, index_end)
tracker_rows = self.store.get_unique(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

DeltaStoreTrec.delete(up_to_idx=...) retains FQN buckets with empty lookup lists. After one dump, if a previously seen table has no unread IDs in a later interval, this reaches torch.cat([]) inside get_unique() and aborts before the dumper's empty-output path. Please prune/omit empty unread buckets and add a two-interval regression.

@github-actions

Copy link
Copy Markdown
Contributor

Static review complete. I left one inline comment: after a prior dump, DeltaStoreTrec retains empty FQN buckets, so a previously seen table with no unread IDs in a later interval can trigger torch.cat([]) and abort dumping. No other noteworthy findings. Tests and builds were not run, as requested.

DeltaStoreTrec retains empty FQN buckets after delete-on-read, causing its unique-row path to concatenate no tensors. Build rows only from unread lookups and omit empty buckets.
@tiankongdeguiji
tiankongdeguiji merged commit 7d559d7 into alibaba:master Jul 27, 2026
7 checks passed
eric-gecheng added a commit to eric-gecheng/TorchEasyRec that referenced this pull request Jul 27, 2026
Reconciles master alibaba#604 (online dense export), alibaba#607 (track delta by
owner-qualified FQN), alibaba#608 (export sparse by table FQN), and alibaba#609
(drop INPUT_TILE mapping) with the branch's FeatureStore delta-dump work.

Keeps master alibaba#607's FQN-keyed delta tracking (local ModelDeltaTracker
subclass, source/table_fqn schema) and alibaba#608's FQN sparse-export naming as
the canonical base, and re-grafts the branch's FeatureStore upload,
minute-cadence, and synced-dataloader-exhaustion onto alibaba#607's dumper. The
uploader reads table_fqn and publishes remap_input_tile_user_key(table_fqn)
as the FeatureStore embedding_name, aligning delta upload with alibaba#608's
export naming and serving. Synced-exhaustion is kept so alibaba#607's
_sync_final_step boundary-skip does not drop a shorter-exhausted rank's
trailing delta (SEANQ). alibaba#604's online dense export and alibaba#609's INPUT_TILE
removal are adopted as-is; main.py keeps the synced-exhaustion gating and
FeatureStore start/close hooks.

Co-Authored-By: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants