Skip to content

Add Sinkhorn functions - #298

Merged
skyw merged 10 commits into
NVIDIA-NeMo:mainfrom
mkhona-nvidia:mkhona/add-sinkhorn-embedding-optimizer
Sep 11, 2026
Merged

skyw merged 10 commits into
NVIDIA-NeMo:mainfrom
mkhona-nvidia:mkhona/add-sinkhorn-embedding-optimizer

Conversation

@mkhona-nvidia

Copy link
Copy Markdown
Contributor

No description provided.

Signed-off-by: mkhona <mkhona@nvidia.com>
@mkhona-nvidia
mkhona-nvidia requested a review from skyw September 10, 2026 19:05
@copy-pr-bot

copy-pr-bot Bot commented Sep 10, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@greptile-apps

greptile-apps Bot commented Sep 10, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 5/5

The PR appears safe to merge; no actionable correctness, security, or repository-rule violations remain.

Summary

  • Masks inactive or near-zero rows before normalization.
  • Alternates row and column L2 normalization in an FP32 workspace.
  • Validates matrix shape, dtype, and numerical parameters.
  • Exports and documents the helper and adds reference, numerical, validation, and contract tests.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart LR
    U[Signed 2D update] --> V[Validate shape, dtype, and parameters]
    V --> F[Copy to FP32 workspace]
    F --> M[Mask near-zero rows]
    M --> R[Normalize rows]
    R --> C[Alternate column and row normalization]
    C --> S[Scale by sqrt of column count]
    S --> O[Return new tensor in input dtype and device]
Loading

Reviews (10) · Last reviewed commit: "Clarify Sinkhorn normalization step coun..."

Comment thread emerging_optimizers/embedding_optimizers/__init__.py Outdated
Signed-off-by: mkhona <mkhona@nvidia.com>
Signed-off-by: mkhona <mkhona@nvidia.com>
Signed-off-by: mkhona <mkhona@nvidia.com>
Signed-off-by: mkhona <mkhona@nvidia.com>
Signed-off-by: mkhona <mkhona@nvidia.com>
Signed-off-by: mkhona <mkhona@nvidia.com>
# Apply the first row step separately, then express each remaining iteration as a column/row pair.
balanced_update.div_(row_norms.add_(eps))
for _ in range(num_steps // 2):
# Normalize columns along the row/token dimension.

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.

remove not very meaningful comment, and potentially wrong if used in say some image model. code is clean enough.


# Apply the first row step separately, then express each remaining iteration as a column/row pair.
balanced_update.div_(row_norms.add_(eps))
for _ in range(num_steps // 2):

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.

Q: why num_steps is set up this way? positive integer // 2?

I can see each loop normalize twice, but positive integer // 2 has no value in the code. num_xxx_steps would be a better name if num_steps to loop count may cause confusion.

Comment thread tests/test_sinkhorn.py Outdated
torch.cuda.manual_seed_all(FLAGS.seed)


def _sinkhorn_balance_reference(

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.

AI copying code as reference? that's a bad reference in case both are wrong.
Implement reference in a different way, could be a very naive serial CPU version.

Comment thread tests/test_sinkhorn.py


class SinkhornBalanceTest(parameterized.TestCase):
def test_defaults_match_deepseek_v41(self) -> None:

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.

Use inspect to check default value would be a better implementation for the purpose of this test.

Comment thread tests/test_sinkhorn.py Outdated
((17, 5), torch.bfloat16, 11, 1.0),
((6, 6), torch.float32, 7, 0.0),
)
def test_matches_step_by_step_reference(self, shape, dtype, num_steps, zero_row_threshold) -> None:

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.

if not exact match, test name should say "close_to"

Comment thread tests/test_sinkhorn.py Outdated
rtol=0.05,
)

def test_single_step_converts_unit_row_l2_norm_to_unit_rms(self) -> None:

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.

Too many tests don't really add more protections. Use your best judgement to remove and keep the essential ones.

Comment thread tests/test_sinkhorn.py Outdated

self.assertFalse(result.requires_grad)

@parameterized.parameters(torch.float64, torch.int64, torch.complex64)

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.

Nit: Combine input validation to the same test, otherwise it gets too noisy.

Signed-off-by: mkhona <mkhona@nvidia.com>
Signed-off-by: mkhona <mkhona@nvidia.com>
skyw
skyw previously approved these changes Sep 11, 2026
Args:
update: Dense signed update with shape ``(num_rows, num_columns)``.
eps: Numerical stability term added to each row or column norm.
num_steps: Total positive odd number of individual axis-normalization steps.

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.

Nit: if we keep this, would be better to explain how steps are counted and why positive odd number here.

Signed-off-by: mkhona <mkhona@nvidia.com>
@mkhona-nvidia

Copy link
Copy Markdown
Contributor Author

/ok to test aa26a46

@skyw
skyw enabled auto-merge (squash) September 11, 2026 17:38
@skyw skyw changed the title Add Sinkhorn embedding optimizer Add Sinkhorn functions Sep 11, 2026
@skyw
skyw merged commit 36f7033 into NVIDIA-NeMo:main Sep 11, 2026
31 checks passed

This branch was successfully deployed

2 active deployments
public — aa26a460 Deployed Sep 11, 2026 by copy-pr-bot[bot] via release / finalize / notify #253
test — aa26a460 Deployed Sep 11, 2026 by copy-pr-bot[bot] via cicd-wait-in-queue #1025
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