Baike.dev
All toolsOnline toolsAI codingTrendingOpen sourceNewsSubmit
Log in
Back to tool/Back to issues
#106452·tensorflow

tf.nn.conv2d exhibits unexpected FP32 numerical divergence compared to reference convolution (CPU, VALID, stride=1) on M2

Author: MartyLinZYCreated Dec 17, 2025Updated Oct 2, 2026
Labelsstat:awaiting responsetype:bugstaleTF 2.19

Issue type

Bug

Have you reproduced the bug with TensorFlow Nightly?

No

Source

source

TensorFlow version

2.21.0

Custom code

Yes

OS platform and distribution

macOS 15.7.2 (arm64)

Mobile device

No response

Python version

3.12.8

Bazel version

No response

GCC/compiler version

No response

CUDA/cuDNN version

No response

GPU model and memory

No response

Current behavior?

We observed a systematic numerical divergence in tf.nn.conv2d when running FP32 convolutions on CPU, compared against an equivalent reference implementation (validated via cross-framework testing).

Under the following strictly controlled conditions:

FP32 inputs and kernel weights

CPU execution

stride = 1

padding = "VALID"

no bias

correct memory layout (NHWC + HWIO)

deterministic inputs (fixed random tensors)

the output values from tf.nn.conv2d differ from the reference results with relative errors up to ~1e-3, which is significantly larger than expected for deterministic FP32 CPU convolutions.

This behavior was discovered during cross-framework fuzzing, where PyTorch’s conv2d was used as a validated reference. While output shapes match exactly, the numerical discrepancy appears consistent and reproducible.

Standalone code to reproduce the issue

bash
import numpy as np
import tensorflow as tf
import torch
import torch.nn.functional as F

# ---- Parameters ----
N, C_in, C_out = 2, 7, 8
H, W = 9, 18
k = 5
stride = 1
padding = "VALID"

# Generate identical FP32 inputs
x = np.random.randn(N, C_in, H, W).astype(np.float32)
w = np.random.randn(C_out, C_in, k, k).astype(np.float32)

# ---- TensorFlow (NHWC / HWIO) ----
x_tf = tf.convert_to_tensor(np.transpose(x, (0, 2, 3, 1)))
w_tf = tf.convert_to_tensor(np.transpose(w, (2, 3, 1, 0)))

y_tf = tf.nn.conv2d(
    x_tf,
    w_tf,
    strides=[1, stride, stride, 1],
    padding=padding
)
y_tf_np = tf.transpose(y_tf, (0, 3, 1, 2)).numpy()

# ---- Reference (PyTorch, NCHW / OIHW) ----
x_pt = torch.from_numpy(x)
w_pt = torch.from_numpy(w)

y_ref = F.conv2d(x_pt, w_pt, stride=stride, padding=0)
y_ref_np = y_ref.detach().cpu().numpy()

# ---- Comparison ----
abs_diff = np.abs(y_tf_np - y_ref_np)
rel_diff = abs_diff / (np.abs(y_ref_np) + 1e-12)

print("Output shapes:", y_tf_np.shape, y_ref_np.shape)
print("Max abs error:", abs_diff.max())
print("Max rel error:", rel_diff.max())

Relevant log output

bash

Source: tensorflow/tensorflow

View original on GitHubView discussion on GitHub