Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion onnxscript/function_libs/torch_lib/ops/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -2127,7 +2127,7 @@ def aten_conv3d(

if bias is None:
weight_dim_0 = op.Shape(weight, start=0, end=1)
bias_shape = op.Concat(weight_dim_0, op.Constant(value_ints=[2]), axis=0)
bias_shape = op.Expand(weight_dim_0, op.Constant(value_ints=[1]))
zero = op.CastLike(0.0, input)
bias = op.Expand(zero, bias_shape)

Expand Down
27 changes: 27 additions & 0 deletions tests/function_libs/torch_lib/e2e_ops_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import math
import unittest

import onnx

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
import onnx

import parameterized

# TODO(pytorch/pytorch#129279): Migrate these tests to the PyTorch repo
Expand Down Expand Up @@ -1004,6 +1005,32 @@ def forward(self, x):
got = onnx_program.call_reference({"x": inputs[0]})
torch.testing.assert_close(expected, got[0])

def test_conv3d_without_bias_produces_1d_bias(self):
class Model(torch.nn.Module):
def __init__(self):
super().__init__()
self.conv = torch.nn.Conv3d(3, 4, kernel_size=2, bias=False)

def forward(self, x):
return self.conv(x)

onnx_program = torch.onnx.export(
Model().eval(), (torch.randn(1, 3, 8, 8, 8),), dynamo=True, optimize=False
)
_testing.assert_onnx_program(onnx_program)

# The bias synthesized for a bias-less conv must be 1D ([out_channels]) to
# match the ONNX Conv spec. See https://github.com/microsoft/onnxscript/issues/2931.
inferred = onnx.shape_inference.infer_shapes(onnx_program.model_proto, data_prop=True)
shape_ranks = {
value_info.name: len(value_info.type.tensor_type.shape.dim)
for value_info in inferred.graph.value_info
if value_info.type.tensor_type.HasField("shape")
}
conv_nodes = [node for node in inferred.graph.node if node.op_type == "Conv"]
self.assertEqual(len(conv_nodes), 1)
self.assertEqual(shape_ranks[conv_nodes[0].input[2]], 1)
Comment on lines +1022 to +1032

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok to review this part as assert_onnx_program will already run the model and validate the shapes.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before I drop it: the synthesized bias is all zeros, so assert_onnx_program passes even with the rank-2 bias. The conv output is numerically identical, so only the rank check fails (2 != 1) before the fix, which is the part that actually pins this regression. If you'd rather rely on assert_onnx_program for path coverage here, I'll remove the block and the onnx import to match the convention in the suite.



if __name__ == "__main__":
unittest.main()
Loading