Files
trellis2-ROCm/ggml/docs/metal-conv-transpose-2d.md
T
2026-08-16 18:33:03 +07:00

1.8 KiB

ggml CONV_TRANSPOSE_2D semantics

Source of truth: ggml_compute_forward_conv_transpose_2d().

This note documents the exact contract the Metal kernel mirrors.

Tensor layouts

  • src0 weights: (KW, KH, Cout, Cin), contiguous, F16 in the CPU implementation used by SAM.
  • src1 input: (IW, IH, Cin, N), contiguous, F32.
  • dst output: (OW, OH, Cout, N), F32.

For ggml_conv_transpose_2d_p0() the output size is:

  • OW = (IW - 1) * stride + KW
  • OH = (IH - 1) * stride + KH

The p0 variant used here has:

  • zero padding only
  • one shared spatial stride s0
  • no dilation
  • no output padding
  • no bias term

CPU computation

The CPU implementation permutes weights and inputs into temporary buffers, zeros dst, then performs a scatter-add over output channel, input spatial position, and kernel tap:

for out_c in [0, Cout):
  for in_y in [0, IH):
    for in_x in [0, IW):
      for kh in [0, KH):
        for kw in [0, KW):
          dst[in_x * stride + kw, in_y * stride + kh, out_c] +=
            dot(input[in_x, in_y, :, 0], weight[kw, kh, out_c, :, 0])

The Metal reference kernel uses the equivalent gather form for one output element:

dst[ow, oh, out_c] =
  sum over kh, kw, in_c where
    ow = in_x * stride + kw
    oh = in_y * stride + kh
  of weight[kw, kh, out_c, in_c] * input[in_x, in_y, in_c]

Numeric behavior

  • input source type: F32, but the CPU implementation first packs it to F16
  • weight type: F16 or F32 on Metal, F16 in the CPU path used here
  • multiply inputs: F16 x F16 in the reference CPU path
  • accumulation type: float
  • output type: F32

Scope

The current CPU implementation only uses batch N = 1 in practice for this path, and the Metal implementation matches that contract explicitly.