gemini-code-assist[bot] commented on code in PR #19907:
URL: https://github.com/apache/tvm/pull/19907#discussion_r3490269290
##########
python/tvm/relax/frontend/onnx/onnx_frontend.py:
##########
@@ -3893,6 +3893,117 @@ def _impl_v23(cls, bb, inputs, attr, params):
return output
+class GroupNormalization(OnnxOpConverter):
+ """Converts an onnx GroupNormalization node into an equivalent Relax
expression"""
+
+ @classmethod
+ def _impl_v18(cls, bb, inputs, attr, params):
+ data = inputs[0]
+ scale = inputs[1]
+ bias = inputs[2]
Review Comment:

We can use `get_constant` to resolve `scale` and `bias` to constants if they
are initializers. This allows us to perform the per-group to per-channel
expansion at import time using NumPy, avoiding redundant `reshape` and
`broadcast_to` operators in the Relax graph.
```suggestion
data = inputs[0]
scale = get_constant(inputs[1], params)
bias = get_constant(inputs[2], params)
```
##########
python/tvm/relax/frontend/onnx/onnx_frontend.py:
##########
@@ -3893,6 +3893,117 @@ def _impl_v23(cls, bb, inputs, attr, params):
return output
+class GroupNormalization(OnnxOpConverter):
+ """Converts an onnx GroupNormalization node into an equivalent Relax
expression"""
+
+ @classmethod
+ def _impl_v18(cls, bb, inputs, attr, params):
+ data = inputs[0]
+ scale = inputs[1]
+ bias = inputs[2]
+ num_groups = attr["num_groups"]
+ epsilon = attr.get("epsilon", 1e-05)
+
+ ndim = _get_known_tensor_rank(data)
+ if ndim is None:
+ raise ValueError("GroupNormalization requires a statically known
input rank.")
+
+ ty = data.ty
+ if not isinstance(ty, relax.TensorType) or len(ty.shape) < 2:
+ raise ValueError(
+ "GroupNormalization-18 requires a statically typed input with
rank >= 2."
+ )
+
+ if num_groups <= 0:
+ raise ValueError(
+ f"GroupNormalization requires num_groups to be positive, got
{num_groups}."
+ )
+
+ channel_dim = ty.shape[1]
+ if not isinstance(channel_dim, tirx.IntImm):
+ raise ValueError(
+ "GroupNormalization-18 requires a statically known channel
count "
+ "to expand per-group scale/bias to per-channel."
+ )
+
+ channels = int(channel_dim)
+ if channels % num_groups != 0:
+ raise ValueError(
+ f"GroupNormalization requires num_groups to divide channel
count, "
+ f"but got C={channels} and num_groups={num_groups}."
+ )
+
+ channels_per_group = channels // num_groups
+
+ scale = relax.op.reshape(scale, [num_groups, 1])
+ scale = relax.op.broadcast_to(scale, [num_groups, channels_per_group])
+ scale = relax.op.reshape(scale, [channels])
+
+ bias = relax.op.reshape(bias, [num_groups, 1])
+ bias = relax.op.broadcast_to(bias, [num_groups, channels_per_group])
+ bias = relax.op.reshape(bias, [channels])
Review Comment:

If `scale` and `bias` are resolved to constants, we can expand them directly
using `_np.repeat` at import time. This simplifies the generated Relax graph by
eliminating unnecessary `reshape` and `broadcast_to` operations.
```suggestion
if isinstance(scale, relax.Constant):
scale = relax.const(_np.repeat(scale.data.numpy(),
channels_per_group), scale.ty.dtype)
else:
scale = relax.op.reshape(scale, [num_groups, 1])
scale = relax.op.broadcast_to(scale, [num_groups,
channels_per_group])
scale = relax.op.reshape(scale, [channels])
if isinstance(bias, relax.Constant):
bias = relax.const(_np.repeat(bias.data.numpy(),
channels_per_group), bias.ty.dtype)
else:
bias = relax.op.reshape(bias, [num_groups, 1])
bias = relax.op.broadcast_to(bias, [num_groups,
channels_per_group])
bias = relax.op.reshape(bias, [channels])
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]