Answer first
No, do not rely on align_corners=None for device-agnostic reproducibility. Specify align_corners=True or False explicitly in torch.nn.functional.interpolate and grid_sample. There is no plan to make CPU and CUDA consistent while align_corners=None is used; the sentinel is deprecated and intentionally non-portable. Whether a future PyTorch release will change the default value from None to a concrete boolean is not settled, and the default remains None in released versions to date. Changing the default would be a breaking semantic change, so the project has moved toward deprecation and removal of the sentinel rather than unifying kernels under it.
Confirmed facts
align_corners=None is a deprecated legacy sentinel for interpolate and grid_sample. It is not a stable setting.
- Its effective meaning is version dependent and backend dependent. Recent releases emit deprecation warnings for
None.
- CPU and GPU resampling kernels are separate implementations. Even with an explicit
align_corners value, small numerical differences can remain due to float32 reduction order and kernel precision. Systematic divergence indicates different mapping semantics, not just rounding.
Likely explanation for your case
With align_corners=None the library maps the sentinel to different effective semantics on CPU vs CUDA in certain PyTorch versions. The legacy coordinate normalization differs between the True-like and False-like paths, so you see systematic output differences rather than only low-magnitude noise.
Steps needed for this case
- Pin the semantics. Replace
align_corners=None with an explicit boolean that matches your intended grid. Use the same explicit value on CPU and CUDA.
- Verify the fix with a minimal repro.
import torch
import torch.nn.functional as F
x = torch.arange(16, dtype=torch.float32).view(1,1,4,4)
def run(dev):
t = x.to(dev)
# explicit value, e.g. False
y = F.interpolate(t, size=(8,8), mode='bilinear', align_corners=False)
return y.cpu()
cpu_out = run('cpu')
gpu_out = run('cuda') if torch.cuda.is_available() else None
With an explicit align_corners, systematic divergence should disappear, leaving only expected low-magnitude numerical noise. Compare with a tolerance, not exact equality, e.g. torch.allclose(cpu_out, gpu_out, atol=1e-5, rtol=1e-5).
Note: changing from None to an explicit boolean is a semantic change to the resampling grid. Validate downstream metrics after the change.
One missing diagnostic detail that changes the recommendation: the exact PyTorch version and the full call signature you use, including size vs scale_factor, mode, and backend. The legacy mapping for None is version sensitive, and whether to pin to True or False depends on which legacy behavior you want to preserve.