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

オープン 初心者向け
#4,860 コメント 0 件 リアクション 0 件 担当者 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 内)から始め、剰余を計算する前に浮動小数点の商がどのように切り捨てられているかを確認してください。issue の再現スクリプトを CUDA マシンで実行し、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時間
マージ済み PR(30日)
62

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

pytorch/TensorRT のほかの issue

pytorch/TensorRT の issue をすべて見る

似ている issue

Python の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。