Skip to content

[MRG] Fix device placement in batch Sinkhorn (solve_batch on GPU) - #851

Open
tomMoral wants to merge 4 commits into
PythonOT:masterfrom
tomMoral:fix-batch-sinkhorn-device
Open

[MRG] Fix device placement in batch Sinkhorn (solve_batch on GPU)#851
tomMoral wants to merge 4 commits into
PythonOT:masterfrom
tomMoral:fix-batch-sinkhorn-device

Conversation

@tomMoral

@tomMoral tomMoral commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)

Motivation and context / Related issue

ot.solve_batch(M, reg=..., method="sinkhorn") crashes on GPU with

RuntimeError: Expected all tensors to be on the same device, but found at least two devices, cuda:0 and cpu!

whenever the torch default device is CPU while the inputs are on CUDA. In
bregman_projection_batch, the scaling vectors f/g were allocated with a
bare nx.ones((B, n)), so they landed on the default (CPU) device and clashed
with the GPU K on the first iteration. The log-domain and proximal solvers
were unaffected (their u/v inits already use type_as).

Reproduced and both the fix and the refactor verified on an NVIDIA V100S
(torch 2.6.0+cu118): all batch paths now run on cuda:0, and a marginal passed
on the wrong device now raises a clear assert_same_dtype_device error instead
of a deep RuntimeError.

How has this been tested (if it applies)

  • New test_solve_batch_device exercises every method on each available device.
  • New test_unif_shape / test_check_marginal cover the utility additions.

Description

Two commits:

  1. Fix — give f/g (and the default a/b) the input backend/device via
    type_as in bregman_projection_batch.
  2. Refactor — the if a is None: a = nx.ones(...) / n idiom was duplicated
    across all five batch solvers (each an opportunity to forget type_as).
    Add ot.utils.check_marginal (fills a uniform marginal on the inputs'
    backend/device when None, otherwise validates shape + dtype/device), extend
    ot.utils.unif to accept a shape tuple (normalized over the last axis, fully
    backward compatible), and route all five sites through check_marginal.

PR checklist

  • I have read the CONTRIBUTING document.
  • The documentation is up-to-date with the changes I made (check RELEASES.md).
  • All tests passed, and additional code has been covered with new tests.
  • I have added the PR and Issue fix to the RELEASES.md file.

🤖 Generated with Claude Code

@codecov

codecov Bot commented Sep 9, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.38710% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 96.84%. Comparing base (6372a66) to head (9bebead).

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #851      +/-   ##
==========================================
- Coverage   96.85%   96.84%   -0.01%     
==========================================
  Files         128      128              
  Lines       26160    26195      +35     
==========================================
+ Hits        25337    25369      +32     
- Misses        823      826       +3     
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant