🐛 [Bug] torch.fmod returns a tiny value with the wrong sign when the float quotient rounds up

未关闭 适合新手
#4,860 0 条评论 0 个 reaction 已指派 1 人 在 GitHub 查看

维护者通常 3 天内回复

@micwill755 已经在做这个了。

开始于 2026年11月10日。

  • #4861 来自 @usmanmateen —— 未关闭

评估

难度
2/5
预计耗时
1-3 小时
新手友好度
70/100
Issue 类型
缺陷
描述清晰度
描述清楚
活跃度
活跃
技术栈
python
领域
compilers

调研方向

从 impl.elementwise.fmod 及其辅助函数 trunc_div(位于 py/torch_tensorrt/dynamo/conversion/impl/elementwise/ops.py)开始,检查在计算余数之前浮点商是如何向下取整的。在 CUDA 机器上运行 issue 中的复现脚本,并将 4.2 / 1.4 以及 0.1 回绕的情况与 torch.fmod 进行比较。完成标准是:浮点 fmod 的结果在符号和数值上与 PyTorch 一致,且整数行为保持不变。

由索引模型根据 Issue 内容生成。

描述

Bug Description

torch.fmod(a, b) on floating point tensors returns a tiny value with the wrong sign when a / b rounds up to a whole number. In float32, torch.fmod(4.2, 1.4) is 1.3999999 in PyTorch and -1.19e-07 in Torch-TensorRT. The result of fmod always has the sign of a, so a negative result for a positive a is never right. It shows up when wrapping values by a period: fmod(x, 0.1) for x = 0.1, 0.2, ..., 10.0 differs from PyTorch for 43 of the 100 values.

impl.elementwise.fmod in py/torch_tensorrt/dynamo/conversion/impl/elementwise/ops.py computes input - trunc_div(input, other) * other, and trunc_div takes FLOOR_DIV of |input| and |other|. For floats, the division is rounded before it's floored. In float32, 4.2 / 1.4 is 2.99999991, which rounds to 3.0, so the quotient comes out as 3 instead of 2 and input - 3 * other is just below zero. PyTorch computes fmod exactly and gets 2.

torch.remainder (%) gives the right result for these inputs.

To Reproduce

import torch
import torch_tensorrt


class Fmod(torch.nn.Module):
    def forward(self, a, b):
        return torch.fmod(a, b)


def trt(model, *args):
    return torch_tensorrt.compile(model.eval().cuda(), ir="dynamo", inputs=list(args), min_block_size=1)(*args)


a = torch.tensor([4.2, -4.2, 0.7, 5.0], device="cuda")
b = torch.tensor([1.4, 1.4, 0.1, 3.0], device="cuda")
print(Fmod()(a, b).tolist())
print(trt(Fmod(), a, b).tolist())

# Wrapping multiples of 0.1 by 0.1
x = torch.arange(1, 101, device="cuda") * 0.1
period = torch.full_like(x, 0.1)
expected, got = Fmod()(x, period), trt(Fmod(), x, period)
print((got - expected).abs().gt(1e-3).sum().item(), "of", x.numel(), "differ")

Output:

[1.3999998569488525, -1.3999998569488525, 0.09999997913837433, 2.0]
[-1.1920928955078125e-07, 1.1920928955078125e-07, -2.2351741790771484e-08, 2.0]
43 of 100 differ

Expected behavior

The same results as PyTorch, which always have the sign of a.

Environment

  • Torch-TensorRT Version: 2.14.0 (pip). fmod and trunc_div are the same on main.
  • PyTorch Version: 2.14.1+cu130
  • CPU Architecture: x86_64
  • OS: Ubuntu 26.04 (WSL2)
  • How you installed PyTorch: pip
  • Python version: 3.12
  • CUDA version: 13.0 (TensorRT 11.1.0.106)
  • GPU models and configuration: NVIDIA GeForce RTX 5060 Ti, driver 596.49

Additional context

I found this with torchparity, a tool I'm writing that runs PyTorch ops through converters and compares the results with eager PyTorch. I have a fix with tests and can open a PR. When the result has the sign opposite to input, it adds |other| back with the sign of input. Integer inputs are unchanged.

#4786 changes trunc_div for large integers and doesn't cover this.

主要语言
Python
星标
3k
派生
421
平均合并
4 天 7 小时
30 天内合并 PR
62

环境准备

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

pytorch/TensorRT 的其他 Issue

查看 pytorch/TensorRT 的全部 Issue

相似的 Issue

更多 Python Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。