Skip to content

[Test] Keep the products in test_reduction_empty_dim finite, so the prod case cannot fail at random - #3045

Merged
peterdsharpe merged 2 commits into
pytorch:mainfrom
peterdsharpe:triager-test-prod-empty-dim-flake
Oct 19, 2026
Merged

peterdsharpe merged 2 commits into
pytorch:mainfrom
peterdsharpe:triager-test-prod-empty-dim-flake

Conversation

@peterdsharpe

@peterdsharpe peterdsharpe commented Oct 19, 2026 •

Copy link
Copy Markdown
Collaborator

TestTensorDicts::test_reduction_empty_dim[prod-sub_td2-*] failed once on the free-threaded 3.15 job with "Scalars are not close! Expected nan but got 0.0." It passed on rerun. It is a flaky test, not a bug in prod.

What was wrong

The test compares td.prod(dim=()) with torch.prod(leaf) over all the elements of each leaf, on random data. In sub_td2, the leaf c holds 60 values from torch.randint(10, ...) converted to float. The exact product is 0 as soon as one value is 0. But 60 values up to 9 can reach 9**60, about 1e57, which is past float32's maximum of about 3e38. When torch.prod multiplies in an order where one partial product overflows to inf before it meets a 0, the result is inf * 0 = nan. In another order it is 0.0. The tensordict path and the direct torch.prod call on the strided view multiply in different orders, so with some seeds one gives nan and the other 0.0.

With the fixture's data, I counted 1 such seed in 3000 (seed 2123: tensordict 0.0, torch.prod nan).

The fix

For prod only, the test maps every leaf to 1 + 0.01 * x in place before it compares, under torch.no_grad() for td_params. All the products then stay finite and nonzero.

The order still changes the last bits. A lazy stack multiplies per member and then across members, and over hundreds of float32 values the result can differ from torch.prod's by up to about n * eps, above assert_close's float32 default of rtol=1.3e-6. So the prod comparisons use rtol=1e-4, atol=1e-5. The other reductions and the rest of the test are unchanged.

What I ran

  • test/tensordict/test_methods.py -k test_reduction_empty_dim with CI's environment variables, -n 2: 171 passed, 9 skipped (td_with_unbatched).
  • The sub_td2 setup of the test, with seeds 0 to 5999 and the new rescaling: 0 mismatches. Without it: 1 in 3000.
  • The test body for prod, called for each of the 20 CPU td_names with seeds 0 to 199 (4000 calls), on Python 3.12 with torch 2.14.1 and on Python 3.10 with torch 2.11.0: 0 failures. With the rescaling but the default tolerance, on torch 2.11: 16 failures, in stacked_td (5) and nested_stacked_td (11), as in CI's test-oldest-cpu job.

60 values up to 9 overflow float32, and torch.prod then gives nan or 0.0
depending on the order in which it multiplies, so the prod case failed for
some seeds. Map the leaves to 1 + 0.01 * x for prod.
@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Oct 19, 2026
@github-actions github-actions Bot added the Test label Oct 19, 2026
A lazy stack multiplies per member and then across members. Over hundreds of
float32 values near 1, that order differs from torch.prod's by up to about
n * eps, above assert_close's default rtol of 1.3e-6.
@peterdsharpe
peterdsharpe merged commit 05a217b into pytorch:main Oct 19, 2026
35 checks passed
@peterdsharpe
peterdsharpe deleted the triager-test-prod-empty-dim-flake branch October 19, 2026 10:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. Test

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant