src/ops_spatial.cpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // brotensor public op wrappers — 2D/3D spatial, conv, norm, pool, StyleGAN. | ||
| 2 | |||
| 3 | #include <brotensor/ops.h> | ||
| 4 | #include <brotensor/tensor.h> | ||
| 5 | #include <brotensor/detail/dispatch.h> | ||
| 6 | |||
| 7 | #include <stdexcept> | ||
| 8 | |||
| 9 | namespace brotensor { | ||
| 10 | |||
| 11 | // ─── Conv2d ──────────────────────────────────────────────────────────────── | ||
| 12 | |||
| 13 | 104 | void conv2d_forward(const Tensor& X, const Tensor& Wt, const Tensor* bias, | |
| 14 | int N, int C_in, int H, int W, | ||
| 15 | int C_out, int kH, int kW, | ||
| 16 | int stride_h, int stride_w, | ||
| 17 | int pad_h, int pad_w, | ||
| 18 | int dil_h, int dil_w, | ||
| 19 | int groups, Tensor& Y) { | ||
| 20 | 104 | BROTENSOR_CHECK_SPATIAL_2D("conv2d_forward", X, N, C_in, H, W); | |
| 21 | 104 | const auto& v = detail::dispatch_with_opts(X, Wt, {bias, &Y}); | |
| 22 |
1/2✓ Branch 0 taken 104 times.
✗ Branch 1 not taken.
|
104 | if (!v.conv2d_forward) detail::throw_not_implemented("conv2d_forward", X.device); |
| 23 | 104 | detail::adopt_output(Y, X.device); | |
| 24 | 208 | v.conv2d_forward(X, Wt, bias, N, C_in, H, W, C_out, kH, kW, | |
| 25 | 104 | stride_h, stride_w, pad_h, pad_w, dil_h, dil_w, groups, Y); | |
| 26 | 104 | } | |
| 27 | |||
| 28 | 54 | void conv2d_backward_input(const Tensor& Wt, const Tensor& dY, | |
| 29 | int N, int C_in, int H, int W, | ||
| 30 | int C_out, int kH, int kW, | ||
| 31 | int stride_h, int stride_w, | ||
| 32 | int pad_h, int pad_w, | ||
| 33 | int dil_h, int dil_w, | ||
| 34 | int groups, Tensor& dX) { | ||
| 35 |
1/2✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
|
54 | if (N <= 0 || C_in <= 0 || H <= 0 || W <= 0 || C_out <= 0) { |
| 36 | ✗ | detail::throw_spatial_2d_error("conv2d_backward_input", "dY", | |
| 37 | ✗ | N, C_in, H, W, dY.rows, dY.cols); | |
| 38 | } | ||
| 39 |
6/12✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 54 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 54 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 54 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 54 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 54 times.
|
54 | if (kH > 0 && kW > 0 && stride_h > 0 && stride_w > 0 && dil_h > 0 && dil_w > 0) { |
| 40 | 54 | const int H_out = (H + 2 * pad_h - dil_h * (kH - 1) - 1) / stride_h + 1; | |
| 41 | 54 | const int W_out = (W + 2 * pad_w - dil_w * (kW - 1) - 1) / stride_w + 1; | |
| 42 |
2/4✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 54 times.
|
54 | if (H_out > 0 && W_out > 0) { |
| 43 | 54 | BROTENSOR_CHECK_SPATIAL_2D("conv2d_backward_input", dY, N, C_out, H_out, W_out); | |
| 44 | 54 | } | |
| 45 | 54 | } | |
| 46 | 54 | const auto& v = detail::dispatch(Wt, dY, dX); | |
| 47 |
1/2✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
|
54 | if (!v.conv2d_backward_input) detail::throw_not_implemented("conv2d_backward_input", Wt.device); |
| 48 | 54 | detail::adopt_output(dX, Wt.device); | |
| 49 | 108 | v.conv2d_backward_input(Wt, dY, N, C_in, H, W, C_out, kH, kW, | |
| 50 | 54 | stride_h, stride_w, pad_h, pad_w, dil_h, dil_w, groups, dX); | |
| 51 | 54 | } | |
| 52 | |||
| 53 | 44 | void conv2d_backward_weight(const Tensor& X, const Tensor& dY, | |
| 54 | int N, int C_in, int H, int W, | ||
| 55 | int C_out, int kH, int kW, | ||
| 56 | int stride_h, int stride_w, | ||
| 57 | int pad_h, int pad_w, | ||
| 58 | int dil_h, int dil_w, | ||
| 59 | int groups, Tensor& dWt) { | ||
| 60 | 44 | BROTENSOR_CHECK_SPATIAL_2D("conv2d_backward_weight", X, N, C_in, H, W); | |
| 61 | 44 | const auto& v = detail::dispatch(X, dY, dWt); | |
| 62 |
1/2✓ Branch 0 taken 44 times.
✗ Branch 1 not taken.
|
44 | if (!v.conv2d_backward_weight) detail::throw_not_implemented("conv2d_backward_weight", X.device); |
| 63 | 44 | detail::adopt_output(dWt, X.device); | |
| 64 | 88 | v.conv2d_backward_weight(X, dY, N, C_in, H, W, C_out, kH, kW, | |
| 65 | 44 | stride_h, stride_w, pad_h, pad_w, dil_h, dil_w, groups, dWt); | |
| 66 | 44 | } | |
| 67 | |||
| 68 | 33 | void conv2d_backward_bias(const Tensor& dY, | |
| 69 | int N, int C_out, int H_out, int W_out, | ||
| 70 | Tensor& dB) { | ||
| 71 | 33 | BROTENSOR_CHECK_SPATIAL_2D("conv2d_backward_bias", dY, N, C_out, H_out, W_out); | |
| 72 | 33 | const auto& v = detail::dispatch(dY, dB); | |
| 73 |
1/2✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
|
33 | if (!v.conv2d_backward_bias) detail::throw_not_implemented("conv2d_backward_bias", dY.device); |
| 74 | 33 | detail::adopt_output(dB, dY.device); | |
| 75 | 33 | v.conv2d_backward_bias(dY, N, C_out, H_out, W_out, dB); | |
| 76 | 33 | } | |
| 77 | |||
| 78 | 10 | void conv2d_int8w_fp16_forward(const Tensor& X, | |
| 79 | const Tensor& W_int8, const Tensor& scales, | ||
| 80 | const Tensor* bias, | ||
| 81 | int N, int C_in, int H, int W, | ||
| 82 | int C_out, int kH, int kW, | ||
| 83 | int stride_h, int stride_w, | ||
| 84 | int pad_h, int pad_w, | ||
| 85 | int dil_h, int dil_w, int groups, | ||
| 86 | Tensor& Y) { | ||
| 87 | 10 | BROTENSOR_CHECK_SPATIAL_2D("conv2d_int8w_fp16_forward", X, N, C_in, H, W); | |
| 88 | 10 | const auto& v = detail::dispatch_with_opts(X, W_int8, {&scales, bias, &Y}); | |
| 89 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
10 | if (!v.conv2d_int8w_fp16_forward) |
| 90 | ✗ | detail::throw_not_implemented("conv2d_int8w_fp16_forward", X.device); | |
| 91 | 10 | detail::adopt_output(Y, X.device); | |
| 92 | 20 | v.conv2d_int8w_fp16_forward(X, W_int8, scales, bias, | |
| 93 | 10 | N, C_in, H, W, C_out, kH, kW, | |
| 94 | 10 | stride_h, stride_w, pad_h, pad_w, | |
| 95 | 10 | dil_h, dil_w, groups, Y); | |
| 96 | 10 | } | |
| 97 | |||
| 98 | 18 | void deform_conv2d_forward(const Tensor& X, const Tensor& offset, | |
| 99 | const Tensor* mask, const Tensor& Wt, | ||
| 100 | const Tensor* bias, | ||
| 101 | int N, int C_in, int H, int W, | ||
| 102 | int C_out, int kH, int kW, | ||
| 103 | int stride_h, int stride_w, | ||
| 104 | int pad_h, int pad_w, | ||
| 105 | int dil_h, int dil_w, | ||
| 106 | int groups, int deform_groups, Tensor& Y) { | ||
| 107 | 18 | BROTENSOR_CHECK_SPATIAL_2D("deform_conv2d_forward", X, N, C_in, H, W); | |
| 108 | 18 | const auto& v = detail::dispatch_with_opts(X, Wt, {&offset, mask, bias, &Y}); | |
| 109 |
1/2✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
|
18 | if (!v.deform_conv2d_forward) detail::throw_not_implemented("deform_conv2d_forward", X.device); |
| 110 | 18 | detail::adopt_output(Y, X.device); | |
| 111 | 36 | v.deform_conv2d_forward(X, offset, mask, Wt, bias, N, C_in, H, W, | |
| 112 | 18 | C_out, kH, kW, stride_h, stride_w, pad_h, pad_w, | |
| 113 | 18 | dil_h, dil_w, groups, deform_groups, Y); | |
| 114 | 18 | } | |
| 115 | |||
| 116 | // ─── Conv3d ──────────────────────────────────────────────────────────────── | ||
| 117 | |||
| 118 | 45 | void conv3d_forward(const Tensor& X, const Tensor& Wt, const Tensor* bias, | |
| 119 | int N, int C_in, int T, int H, int W, | ||
| 120 | int C_out, int kT, int kH, int kW, | ||
| 121 | int stride_t, int stride_h, int stride_w, | ||
| 122 | int pad_t, int pad_h, int pad_w, | ||
| 123 | int dil_t, int dil_h, int dil_w, | ||
| 124 | int groups, Tensor& Y) { | ||
| 125 | 45 | BROTENSOR_CHECK_SPATIAL_3D("conv3d_forward", X, N, C_in, T, H, W); | |
| 126 | 45 | const auto& v = detail::dispatch_with_opts(X, Wt, {bias, &Y}); | |
| 127 |
1/2✓ Branch 0 taken 45 times.
✗ Branch 1 not taken.
|
45 | if (!v.conv3d_forward) detail::throw_not_implemented("conv3d_forward", X.device); |
| 128 | 45 | detail::adopt_output(Y, X.device); | |
| 129 | 90 | v.conv3d_forward(X, Wt, bias, N, C_in, T, H, W, C_out, kT, kH, kW, | |
| 130 | 45 | stride_t, stride_h, stride_w, | |
| 131 | 45 | pad_t, pad_h, pad_w, | |
| 132 | 45 | dil_t, dil_h, dil_w, groups, Y); | |
| 133 | 45 | } | |
| 134 | |||
| 135 | 9 | void conv3d_int8w_fp16_forward(const Tensor& X, const Tensor& W_int8, | |
| 136 | const Tensor& scales, const Tensor* bias, | ||
| 137 | int N, int C_in, int T, int H, int W, | ||
| 138 | int C_out, int kT, int kH, int kW, | ||
| 139 | int stride_t, int stride_h, int stride_w, | ||
| 140 | int pad_t, int pad_h, int pad_w, | ||
| 141 | int dil_t, int dil_h, int dil_w, | ||
| 142 | int groups, Tensor& Y) { | ||
| 143 | 9 | BROTENSOR_CHECK_SPATIAL_3D("conv3d_int8w_fp16_forward", X, N, C_in, T, H, W); | |
| 144 | 9 | const auto& v = detail::dispatch_with_opts(X, W_int8, {&scales, bias, &Y}); | |
| 145 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1 time.
|
9 | if (!v.conv3d_int8w_fp16_forward) |
| 146 | 1 | detail::throw_not_implemented("conv3d_int8w_fp16_forward", X.device); | |
| 147 | 8 | detail::adopt_output(Y, X.device); | |
| 148 | 16 | v.conv3d_int8w_fp16_forward(X, W_int8, scales, bias, | |
| 149 | 8 | N, C_in, T, H, W, C_out, kT, kH, kW, | |
| 150 | 8 | stride_t, stride_h, stride_w, | |
| 151 | 8 | pad_t, pad_h, pad_w, | |
| 152 | 8 | dil_t, dil_h, dil_w, groups, Y); | |
| 153 | 8 | } | |
| 154 | |||
| 155 | // ─── GroupNorm ───────────────────────────────────────────────────────────── | ||
| 156 | |||
| 157 | 41 | void group_norm_forward(const Tensor& X, const Tensor& gamma, const Tensor& beta, | |
| 158 | int N, int C, int H, int W, int num_groups, | ||
| 159 | float eps, Tensor& Y) { | ||
| 160 | 41 | BROTENSOR_CHECK_SPATIAL_2D("group_norm_forward", X, N, C, H, W); | |
| 161 | 41 | const auto& v = detail::dispatch(X, gamma, beta, Y); | |
| 162 |
1/2✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
|
41 | if (!v.group_norm_forward) detail::throw_not_implemented("group_norm_forward", X.device); |
| 163 | 41 | detail::adopt_output(Y, X.device); | |
| 164 | 41 | v.group_norm_forward(X, gamma, beta, N, C, H, W, num_groups, eps, Y); | |
| 165 | 41 | } | |
| 166 | |||
| 167 | 32 | void group_norm_backward(const Tensor& X, const Tensor& gamma, const Tensor& dY, | |
| 168 | int N, int C, int H, int W, int num_groups, float eps, | ||
| 169 | Tensor& dX, Tensor& dGamma, Tensor& dBeta) { | ||
| 170 | 32 | BROTENSOR_CHECK_SPATIAL_2D("group_norm_backward", X, N, C, H, W); | |
| 171 | 32 | BROTENSOR_CHECK_SPATIAL_2D("group_norm_backward", dY, N, C, H, W); | |
| 172 | 32 | const auto& v = detail::dispatch(X, gamma, dY, dX, dGamma, dBeta); | |
| 173 |
1/2✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
|
32 | if (!v.group_norm_backward) detail::throw_not_implemented("group_norm_backward", X.device); |
| 174 | 32 | detail::adopt_output(dX, X.device); | |
| 175 | 32 | detail::adopt_output(dGamma, X.device); | |
| 176 | 32 | detail::adopt_output(dBeta, X.device); | |
| 177 | 64 | v.group_norm_backward(X, gamma, dY, N, C, H, W, num_groups, eps, | |
| 178 | 32 | dX, dGamma, dBeta); | |
| 179 | 32 | } | |
| 180 | |||
| 181 | // ─── Activations ─────────────────────────────────────────────────────────── | ||
| 182 | |||
| 183 | 575 | void silu_forward(const Tensor& x, Tensor& y) { | |
| 184 | 575 | const auto& v = detail::dispatch(x, y); | |
| 185 |
1/2✓ Branch 0 taken 575 times.
✗ Branch 1 not taken.
|
575 | if (!v.silu_forward) detail::throw_not_implemented("silu_forward", x.device); |
| 186 | 575 | detail::adopt_output(y, x.device); | |
| 187 | 575 | v.silu_forward(x, y); | |
| 188 | 575 | } | |
| 189 | 12 | void silu_backward(const Tensor& x, const Tensor& dY, Tensor& dX) { | |
| 190 | 12 | const auto& v = detail::dispatch(x, dY, dX); | |
| 191 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | if (!v.silu_backward) detail::throw_not_implemented("silu_backward", x.device); |
| 192 | 12 | detail::adopt_output(dX, x.device); | |
| 193 | 12 | v.silu_backward(x, dY, dX); | |
| 194 | 12 | } | |
| 195 | 12 | void gelu_forward(const Tensor& x, Tensor& y) { | |
| 196 | 12 | const auto& v = detail::dispatch(x, y); | |
| 197 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | if (!v.gelu_forward) detail::throw_not_implemented("gelu_forward", x.device); |
| 198 | 12 | detail::adopt_output(y, x.device); | |
| 199 | 12 | v.gelu_forward(x, y); | |
| 200 | 12 | } | |
| 201 | 8 | void gelu_backward(const Tensor& x, const Tensor& dY, Tensor& dX) { | |
| 202 | 8 | const auto& v = detail::dispatch(x, dY, dX); | |
| 203 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | if (!v.gelu_backward) detail::throw_not_implemented("gelu_backward", x.device); |
| 204 | 8 | detail::adopt_output(dX, x.device); | |
| 205 | 8 | v.gelu_backward(x, dY, dX); | |
| 206 | 8 | } | |
| 207 | 10 | void gelu_exact_forward(const Tensor& x, Tensor& y) { | |
| 208 | 10 | const auto& v = detail::dispatch(x, y); | |
| 209 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
10 | if (!v.gelu_exact_forward) detail::throw_not_implemented("gelu_exact_forward", x.device); |
| 210 | 10 | detail::adopt_output(y, x.device); | |
| 211 | 10 | v.gelu_exact_forward(x, y); | |
| 212 | 10 | } | |
| 213 | 8 | void gelu_exact_backward(const Tensor& x, const Tensor& dY, Tensor& dX) { | |
| 214 | 8 | const auto& v = detail::dispatch(x, dY, dX); | |
| 215 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | if (!v.gelu_exact_backward) detail::throw_not_implemented("gelu_exact_backward", x.device); |
| 216 | 8 | detail::adopt_output(dX, x.device); | |
| 217 | 8 | v.gelu_exact_backward(x, dY, dX); | |
| 218 | 8 | } | |
| 219 | 10 | void quick_gelu_forward(const Tensor& x, Tensor& y) { | |
| 220 | 10 | const auto& v = detail::dispatch(x, y); | |
| 221 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
10 | if (!v.quick_gelu_forward) detail::throw_not_implemented("quick_gelu_forward", x.device); |
| 222 | 10 | detail::adopt_output(y, x.device); | |
| 223 | 10 | v.quick_gelu_forward(x, y); | |
| 224 | 10 | } | |
| 225 | 8 | void quick_gelu_backward(const Tensor& x, const Tensor& dY, Tensor& dX) { | |
| 226 | 8 | const auto& v = detail::dispatch(x, dY, dX); | |
| 227 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | if (!v.quick_gelu_backward) detail::throw_not_implemented("quick_gelu_backward", x.device); |
| 228 | 8 | detail::adopt_output(dX, x.device); | |
| 229 | 8 | v.quick_gelu_backward(x, dY, dX); | |
| 230 | 8 | } | |
| 231 | |||
| 232 | // ─── Resample ────────────────────────────────────────────────────────────── | ||
| 233 | |||
| 234 | 22 | void upsample_nearest_2x(const Tensor& X, int N, int C, int H, int W, Tensor& Y) { | |
| 235 | 22 | BROTENSOR_CHECK_SPATIAL_2D("upsample_nearest_2x", X, N, C, H, W); | |
| 236 | 22 | const auto& v = detail::dispatch(X, Y); | |
| 237 |
1/2✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
|
22 | if (!v.upsample_nearest_2x) detail::throw_not_implemented("upsample_nearest_2x", X.device); |
| 238 | 22 | detail::adopt_output(Y, X.device); | |
| 239 | 22 | v.upsample_nearest_2x(X, N, C, H, W, Y); | |
| 240 | 22 | } | |
| 241 | 19 | void upsample_bilinear_2x(const Tensor& X, int N, int C, int H, int W, Tensor& Y) { | |
| 242 | 19 | BROTENSOR_CHECK_SPATIAL_2D("upsample_bilinear_2x", X, N, C, H, W); | |
| 243 | 19 | const auto& v = detail::dispatch(X, Y); | |
| 244 |
1/2✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
|
19 | if (!v.upsample_bilinear_2x) detail::throw_not_implemented("upsample_bilinear_2x", X.device); |
| 245 | 19 | detail::adopt_output(Y, X.device); | |
| 246 | 19 | v.upsample_bilinear_2x(X, N, C, H, W, Y); | |
| 247 | 19 | } | |
| 248 | 19 | void downsample_avg_2x(const Tensor& X, int N, int C, int H, int W, Tensor& Y) { | |
| 249 | 19 | BROTENSOR_CHECK_SPATIAL_2D("downsample_avg_2x", X, N, C, H, W); | |
| 250 | 19 | const auto& v = detail::dispatch(X, Y); | |
| 251 |
1/2✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
|
19 | if (!v.downsample_avg_2x) detail::throw_not_implemented("downsample_avg_2x", X.device); |
| 252 | 19 | detail::adopt_output(Y, X.device); | |
| 253 | 19 | v.downsample_avg_2x(X, N, C, H, W, Y); | |
| 254 | 19 | } | |
| 255 | 16 | void upsample_nearest_2x_backward(const Tensor& dY, int N, int C, int H, int W, Tensor& dX) { | |
| 256 |
1/2✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
|
16 | if (N <= 0 || C <= 0 || H <= 0 || W <= 0) { |
| 257 | ✗ | detail::throw_spatial_2d_error("upsample_nearest_2x_backward", "dY", | |
| 258 | ✗ | N, C, H, W, dY.rows, dY.cols); | |
| 259 | } | ||
| 260 | 16 | BROTENSOR_CHECK_SPATIAL_2D("upsample_nearest_2x_backward", dY, N, C, 2 * H, 2 * W); | |
| 261 | 16 | const auto& v = detail::dispatch(dY, dX); | |
| 262 |
1/2✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
|
16 | if (!v.upsample_nearest_2x_backward) detail::throw_not_implemented("upsample_nearest_2x_backward", dY.device); |
| 263 | 16 | detail::adopt_output(dX, dY.device); | |
| 264 | 16 | v.upsample_nearest_2x_backward(dY, N, C, H, W, dX); | |
| 265 | 16 | } | |
| 266 | 16 | void upsample_bilinear_2x_backward(const Tensor& dY, int N, int C, int H, int W, Tensor& dX) { | |
| 267 |
1/2✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
|
16 | if (N <= 0 || C <= 0 || H <= 0 || W <= 0) { |
| 268 | ✗ | detail::throw_spatial_2d_error("upsample_bilinear_2x_backward", "dY", | |
| 269 | ✗ | N, C, H, W, dY.rows, dY.cols); | |
| 270 | } | ||
| 271 | 16 | BROTENSOR_CHECK_SPATIAL_2D("upsample_bilinear_2x_backward", dY, N, C, 2 * H, 2 * W); | |
| 272 | 16 | const auto& v = detail::dispatch(dY, dX); | |
| 273 |
1/2✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
|
16 | if (!v.upsample_bilinear_2x_backward) detail::throw_not_implemented("upsample_bilinear_2x_backward", dY.device); |
| 274 | 16 | detail::adopt_output(dX, dY.device); | |
| 275 | 16 | v.upsample_bilinear_2x_backward(dY, N, C, H, W, dX); | |
| 276 | 16 | } | |
| 277 | 16 | void downsample_avg_2x_backward(const Tensor& dY, int N, int C, int H, int W, Tensor& dX) { | |
| 278 |
1/2✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
|
16 | if (N <= 0 || C <= 0 || H <= 0 || W <= 0) { |
| 279 | ✗ | detail::throw_spatial_2d_error("downsample_avg_2x_backward", "dY", | |
| 280 | ✗ | N, C, H, W, dY.rows, dY.cols); | |
| 281 | } | ||
| 282 |
2/4✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 16 times.
|
16 | if (H % 2 == 0 && W % 2 == 0) { |
| 283 | 16 | BROTENSOR_CHECK_SPATIAL_2D("downsample_avg_2x_backward", dY, N, C, H / 2, W / 2); | |
| 284 | 16 | } | |
| 285 | 16 | const auto& v = detail::dispatch(dY, dX); | |
| 286 |
1/2✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
|
16 | if (!v.downsample_avg_2x_backward) detail::throw_not_implemented("downsample_avg_2x_backward", dY.device); |
| 287 | 16 | detail::adopt_output(dX, dY.device); | |
| 288 | 16 | v.downsample_avg_2x_backward(dY, N, C, H, W, dX); | |
| 289 | 16 | } | |
| 290 | |||
| 291 | 86 | void interp2d_forward(const Tensor& X, | |
| 292 | int N, int C, int H_in, int W_in, int H_out, int W_out, | ||
| 293 | int mode, Tensor& Y) { | ||
| 294 | 86 | BROTENSOR_CHECK_SPATIAL_2D("interp2d_forward", X, N, C, H_in, W_in); | |
| 295 | 86 | const auto& v = detail::dispatch(X, Y); | |
| 296 |
1/2✓ Branch 0 taken 86 times.
✗ Branch 1 not taken.
|
86 | if (!v.interp2d_forward) detail::throw_not_implemented("interp2d_forward", X.device); |
| 297 | 86 | detail::adopt_output(Y, X.device); | |
| 298 | 86 | v.interp2d_forward(X, N, C, H_in, W_in, H_out, W_out, mode, Y); | |
| 299 | 86 | } | |
| 300 | 17 | void interp2d_backward(const Tensor& dY, | |
| 301 | int N, int C, int H_in, int W_in, int H_out, int W_out, | ||
| 302 | int mode, Tensor& dX) { | ||
| 303 |
1/2✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
|
17 | if (N <= 0 || C <= 0 || H_in <= 0 || W_in <= 0) { |
| 304 | ✗ | detail::throw_spatial_2d_error("interp2d_backward", "dY", | |
| 305 | ✗ | N, C, H_in, W_in, dY.rows, dY.cols); | |
| 306 | } | ||
| 307 | 17 | BROTENSOR_CHECK_SPATIAL_2D("interp2d_backward", dY, N, C, H_out, W_out); | |
| 308 | 17 | const auto& v = detail::dispatch(dY, dX); | |
| 309 |
1/2✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
|
17 | if (!v.interp2d_backward) detail::throw_not_implemented("interp2d_backward", dY.device); |
| 310 | 17 | detail::adopt_output(dX, dY.device); | |
| 311 | 17 | v.interp2d_backward(dY, N, C, H_in, W_in, H_out, W_out, mode, dX); | |
| 312 | 17 | } | |
| 313 | 22 | void interp2d_align_corners_forward(const Tensor& X, | |
| 314 | int N, int C, int H_in, int W_in, | ||
| 315 | int H_out, int W_out, int mode, Tensor& Y) { | ||
| 316 | 22 | BROTENSOR_CHECK_SPATIAL_2D("interp2d_align_corners_forward", X, N, C, H_in, W_in); | |
| 317 | 22 | const auto& v = detail::dispatch(X, Y); | |
| 318 |
1/2✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
|
22 | if (!v.interp2d_align_corners_forward) |
| 319 | ✗ | detail::throw_not_implemented("interp2d_align_corners_forward", X.device); | |
| 320 | 22 | detail::adopt_output(Y, X.device); | |
| 321 | 22 | v.interp2d_align_corners_forward(X, N, C, H_in, W_in, H_out, W_out, mode, Y); | |
| 322 | 22 | } | |
| 323 | |||
| 324 | 65 | void pad2d_forward(const Tensor& X, int N, int C, int H, int W, | |
| 325 | int pad_top, int pad_bottom, int pad_left, int pad_right, | ||
| 326 | int mode, Tensor& Y) { | ||
| 327 | 65 | BROTENSOR_CHECK_SPATIAL_2D("pad2d_forward", X, N, C, H, W); | |
| 328 | 65 | const auto& v = detail::dispatch(X, Y); | |
| 329 |
1/2✓ Branch 0 taken 65 times.
✗ Branch 1 not taken.
|
65 | if (!v.pad2d_forward) detail::throw_not_implemented("pad2d_forward", X.device); |
| 330 | 65 | detail::adopt_output(Y, X.device); | |
| 331 | 65 | v.pad2d_forward(X, N, C, H, W, pad_top, pad_bottom, pad_left, pad_right, mode, Y); | |
| 332 | 65 | } | |
| 333 | 13 | void pad2d_backward(const Tensor& dY, int N, int C, int H, int W, | |
| 334 | int pad_top, int pad_bottom, int pad_left, int pad_right, | ||
| 335 | int mode, Tensor& dX) { | ||
| 336 |
1/2✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
|
13 | if (N <= 0 || C <= 0 || H <= 0 || W <= 0) { |
| 337 | ✗ | detail::throw_spatial_2d_error("pad2d_backward", "dY", | |
| 338 | ✗ | N, C, H, W, dY.rows, dY.cols); | |
| 339 | } | ||
| 340 | 13 | const int H_out = H + pad_top + pad_bottom; | |
| 341 | 13 | const int W_out = W + pad_left + pad_right; | |
| 342 |
2/4✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 13 times.
|
13 | if (H_out > 0 && W_out > 0) { |
| 343 | 13 | BROTENSOR_CHECK_SPATIAL_2D("pad2d_backward", dY, N, C, H_out, W_out); | |
| 344 | 13 | } | |
| 345 | 13 | const auto& v = detail::dispatch(dY, dX); | |
| 346 |
1/2✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
|
13 | if (!v.pad2d_backward) detail::throw_not_implemented("pad2d_backward", dY.device); |
| 347 | 13 | detail::adopt_output(dX, dY.device); | |
| 348 | 13 | v.pad2d_backward(dY, N, C, H, W, pad_top, pad_bottom, pad_left, pad_right, mode, dX); | |
| 349 | 13 | } | |
| 350 | |||
| 351 | 16 | void slice2d_forward(const Tensor& X, int N, int C, int H, int W, | |
| 352 | int h0, int w0, int H_out, int W_out, Tensor& Y) { | ||
| 353 | 16 | BROTENSOR_CHECK_SPATIAL_2D("slice2d_forward", X, N, C, H, W); | |
| 354 | 16 | const auto& v = detail::dispatch(X, Y); | |
| 355 |
1/2✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
|
16 | if (!v.slice2d_forward) detail::throw_not_implemented("slice2d_forward", X.device); |
| 356 | 16 | detail::adopt_output(Y, X.device); | |
| 357 | 16 | v.slice2d_forward(X, N, C, H, W, h0, w0, H_out, W_out, Y); | |
| 358 | 16 | } | |
| 359 | 8 | void slice2d_backward(const Tensor& dY, int N, int C, int H, int W, | |
| 360 | int h0, int w0, int H_out, int W_out, Tensor& dX) { | ||
| 361 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | if (N <= 0 || C <= 0 || H <= 0 || W <= 0) { |
| 362 | ✗ | detail::throw_spatial_2d_error("slice2d_backward", "dY", | |
| 363 | ✗ | N, C, H, W, dY.rows, dY.cols); | |
| 364 | } | ||
| 365 |
2/4✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
|
8 | if (H_out > 0 && W_out > 0) { |
| 366 | 8 | BROTENSOR_CHECK_SPATIAL_2D("slice2d_backward", dY, N, C, H_out, W_out); | |
| 367 | 8 | } | |
| 368 | 8 | const auto& v = detail::dispatch(dY, dX); | |
| 369 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | if (!v.slice2d_backward) detail::throw_not_implemented("slice2d_backward", dY.device); |
| 370 | 8 | detail::adopt_output(dX, dY.device); | |
| 371 | 8 | v.slice2d_backward(dY, N, C, H, W, h0, w0, H_out, W_out, dX); | |
| 372 | 8 | } | |
| 373 | |||
| 374 | 10 | void unfold2d_forward(const Tensor& X, int N, int C, int H, int W, | |
| 375 | int kH, int kW, int stride_h, int stride_w, | ||
| 376 | int pad_top, int pad_bottom, int pad_left, int pad_right, | ||
| 377 | int mode, Tensor& Y) { | ||
| 378 | 10 | BROTENSOR_CHECK_SPATIAL_2D("unfold2d_forward", X, N, C, H, W); | |
| 379 | 10 | const auto& v = detail::dispatch(X, Y); | |
| 380 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
10 | if (!v.unfold2d_forward) detail::throw_not_implemented("unfold2d_forward", X.device); |
| 381 | 10 | detail::adopt_output(Y, X.device); | |
| 382 | 20 | v.unfold2d_forward(X, N, C, H, W, kH, kW, stride_h, stride_w, | |
| 383 | 10 | pad_top, pad_bottom, pad_left, pad_right, mode, Y); | |
| 384 | 10 | } | |
| 385 | |||
| 386 | 10 | void l2_normalize_nchw_forward(const Tensor& X, int N, int C, int H, int W, | |
| 387 | float eps, Tensor& Y) { | ||
| 388 | 10 | BROTENSOR_CHECK_SPATIAL_2D("l2_normalize_nchw_forward", X, N, C, H, W); | |
| 389 | 10 | const auto& v = detail::dispatch(X, Y); | |
| 390 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
10 | if (!v.l2_normalize_nchw_forward) |
| 391 | ✗ | detail::throw_not_implemented("l2_normalize_nchw_forward", X.device); | |
| 392 | 10 | detail::adopt_output(Y, X.device); | |
| 393 | 10 | v.l2_normalize_nchw_forward(X, N, C, H, W, eps, Y); | |
| 394 | 10 | } | |
| 395 | |||
| 396 | 10 | void convex_upsample_forward(const Tensor& X, const Tensor& Mask, | |
| 397 | int N, int C, int H, int W, int scale, Tensor& Y) { | ||
| 398 | 10 | BROTENSOR_CHECK_SPATIAL_2D("convex_upsample_forward", X, N, C, H, W); | |
| 399 | 10 | const auto& v = detail::dispatch(X, Mask, Y); | |
| 400 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
10 | if (!v.convex_upsample_forward) |
| 401 | ✗ | detail::throw_not_implemented("convex_upsample_forward", X.device); | |
| 402 | 10 | detail::adopt_output(Y, X.device); | |
| 403 | 10 | v.convex_upsample_forward(X, Mask, N, C, H, W, scale, Y); | |
| 404 | 10 | } | |
| 405 | |||
| 406 | 63 | void top_k_rows(const Tensor& X, int k, Tensor& Vals, Tensor& Idx) { | |
| 407 | 63 | const auto& v = detail::dispatch(X, Vals, Idx); | |
| 408 |
1/2✓ Branch 0 taken 63 times.
✗ Branch 1 not taken.
|
63 | if (!v.top_k_rows) detail::throw_not_implemented("top_k_rows", X.device); |
| 409 | 63 | detail::adopt_output(Vals, X.device); | |
| 410 | 63 | detail::adopt_output(Idx, X.device); | |
| 411 | 63 | v.top_k_rows(X, k, Vals, Idx); | |
| 412 | 63 | } | |
| 413 | |||
| 414 | 46 | void adaptive_avg_pool2d_forward(const Tensor& X, int N, int C, int H, int W, | |
| 415 | int H_out, int W_out, Tensor& Y) { | ||
| 416 | 46 | BROTENSOR_CHECK_SPATIAL_2D("adaptive_avg_pool2d_forward", X, N, C, H, W); | |
| 417 | 46 | const auto& v = detail::dispatch(X, Y); | |
| 418 |
1/2✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
|
46 | if (!v.adaptive_avg_pool2d_forward) |
| 419 | ✗ | detail::throw_not_implemented("adaptive_avg_pool2d_forward", X.device); | |
| 420 | 46 | detail::adopt_output(Y, X.device); | |
| 421 | 46 | v.adaptive_avg_pool2d_forward(X, N, C, H, W, H_out, W_out, Y); | |
| 422 | 46 | } | |
| 423 | 8 | void adaptive_avg_pool2d_backward(const Tensor& dY, int N, int C, int H, int W, | |
| 424 | int H_out, int W_out, Tensor& dX) { | ||
| 425 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | if (N <= 0 || C <= 0 || H <= 0 || W <= 0) { |
| 426 | ✗ | detail::throw_spatial_2d_error("adaptive_avg_pool2d_backward", "dY", | |
| 427 | ✗ | N, C, H, W, dY.rows, dY.cols); | |
| 428 | } | ||
| 429 | 8 | BROTENSOR_CHECK_SPATIAL_2D("adaptive_avg_pool2d_backward", dY, N, C, H_out, W_out); | |
| 430 | 8 | const auto& v = detail::dispatch(dY, dX); | |
| 431 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | if (!v.adaptive_avg_pool2d_backward) |
| 432 | ✗ | detail::throw_not_implemented("adaptive_avg_pool2d_backward", dY.device); | |
| 433 | 8 | detail::adopt_output(dX, dY.device); | |
| 434 | 8 | v.adaptive_avg_pool2d_backward(dY, N, C, H, W, H_out, W_out, dX); | |
| 435 | 8 | } | |
| 436 | |||
| 437 | 23 | void max_pool2d_forward(const Tensor& X, int N, int C, int H, int W, | |
| 438 | int kH, int kW, int stride_h, int stride_w, | ||
| 439 | int pad_h, int pad_w, Tensor& Y, Tensor& Idx) { | ||
| 440 | 23 | BROTENSOR_CHECK_SPATIAL_2D("max_pool2d_forward", X, N, C, H, W); | |
| 441 | 23 | const auto& v = detail::dispatch(X, Y, Idx); | |
| 442 |
1/2✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
|
23 | if (!v.max_pool2d_forward) |
| 443 | ✗ | detail::throw_not_implemented("max_pool2d_forward", X.device); | |
| 444 | 23 | detail::adopt_output(Y, X.device); | |
| 445 | 23 | detail::adopt_output(Idx, X.device); | |
| 446 | 46 | v.max_pool2d_forward(X, N, C, H, W, kH, kW, stride_h, stride_w, | |
| 447 | 23 | pad_h, pad_w, Y, Idx); | |
| 448 | 23 | } | |
| 449 | 10 | void max_pool2d_backward(const Tensor& dY, const Tensor& Idx, | |
| 450 | int N, int C, int H, int W, int H_out, int W_out, | ||
| 451 | Tensor& dX) { | ||
| 452 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
10 | if (N <= 0 || C <= 0 || H <= 0 || W <= 0) { |
| 453 | ✗ | detail::throw_spatial_2d_error("max_pool2d_backward", "dY", | |
| 454 | ✗ | N, C, H, W, dY.rows, dY.cols); | |
| 455 | } | ||
| 456 | 10 | BROTENSOR_CHECK_SPATIAL_2D("max_pool2d_backward", dY, N, C, H_out, W_out); | |
| 457 | 10 | const auto& v = detail::dispatch(dY, Idx, dX); | |
| 458 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
10 | if (!v.max_pool2d_backward) |
| 459 | ✗ | detail::throw_not_implemented("max_pool2d_backward", dY.device); | |
| 460 | 10 | detail::adopt_output(dX, dY.device); | |
| 461 | 10 | v.max_pool2d_backward(dY, Idx, N, C, H, W, H_out, W_out, dX); | |
| 462 | 10 | } | |
| 463 | |||
| 464 | 18 | void gather_rows(const Tensor& X, const Tensor& Idx, Tensor& Y) { | |
| 465 | 18 | const auto& v = detail::dispatch(X, Idx, Y); | |
| 466 |
1/2✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
|
18 | if (!v.gather_rows) detail::throw_not_implemented("gather_rows", X.device); |
| 467 | 18 | detail::adopt_output(Y, X.device); | |
| 468 | 18 | v.gather_rows(X, Idx, Y); | |
| 469 | 18 | } | |
| 470 | 11 | void scatter_rows_add(const Tensor& dY, const Tensor& Idx, int R, Tensor& dX) { | |
| 471 | 11 | const auto& v = detail::dispatch(dY, Idx, dX); | |
| 472 |
1/2✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
|
11 | if (!v.scatter_rows_add) |
| 473 | ✗ | detail::throw_not_implemented("scatter_rows_add", dY.device); | |
| 474 | 11 | detail::adopt_output(dX, dY.device); | |
| 475 | 11 | v.scatter_rows_add(dY, Idx, R, dX); | |
| 476 | 11 | } | |
| 477 | 8 | void scatter_rows(const Tensor& Y, const Tensor& Idx, Tensor& X) { | |
| 478 | 8 | const auto& v = detail::dispatch(Y, Idx, X); | |
| 479 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | if (!v.scatter_rows) detail::throw_not_implemented("scatter_rows", Y.device); |
| 480 | 8 | v.scatter_rows(Y, Idx, X); | |
| 481 | 8 | } | |
| 482 | |||
| 483 | 90 | void conv_transpose2d_forward(const Tensor& X, const Tensor& Wt, | |
| 484 | const Tensor* bias, | ||
| 485 | int N, int C_in, int H, int W, | ||
| 486 | int C_out, int kH, int kW, | ||
| 487 | int stride_h, int stride_w, | ||
| 488 | int pad_h, int pad_w, | ||
| 489 | int output_padding_h, int output_padding_w, | ||
| 490 | int dil_h, int dil_w, int groups, | ||
| 491 | Tensor& Y) { | ||
| 492 | 90 | BROTENSOR_CHECK_SPATIAL_2D("conv_transpose2d_forward", X, N, C_in, H, W); | |
| 493 | 90 | const auto& v = detail::dispatch(X, Wt, Y); | |
| 494 |
1/2✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
|
90 | if (!v.conv_transpose2d_forward) |
| 495 | ✗ | detail::throw_not_implemented("conv_transpose2d_forward", X.device); | |
| 496 | 90 | detail::adopt_output(Y, X.device); | |
| 497 | 180 | v.conv_transpose2d_forward(X, Wt, bias, N, C_in, H, W, C_out, kH, kW, | |
| 498 | 90 | stride_h, stride_w, pad_h, pad_w, | |
| 499 | 90 | output_padding_h, output_padding_w, | |
| 500 | 90 | dil_h, dil_w, groups, Y); | |
| 501 | 90 | } | |
| 502 | 10 | void conv_transpose2d_backward_input(const Tensor& Wt, const Tensor& dY, | |
| 503 | int N, int C_in, int H, int W, | ||
| 504 | int C_out, int kH, int kW, | ||
| 505 | int stride_h, int stride_w, | ||
| 506 | int pad_h, int pad_w, | ||
| 507 | int output_padding_h, int output_padding_w, | ||
| 508 | int dil_h, int dil_w, int groups, | ||
| 509 | Tensor& dX) { | ||
| 510 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
10 | if (N <= 0 || C_in <= 0 || H <= 0 || W <= 0 || C_out <= 0) { |
| 511 | ✗ | detail::throw_spatial_2d_error("conv_transpose2d_backward_input", "dY", | |
| 512 | ✗ | N, C_in, H, W, dY.rows, dY.cols); | |
| 513 | } | ||
| 514 | 10 | const auto& v = detail::dispatch(Wt, dY, dX); | |
| 515 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
10 | if (!v.conv_transpose2d_backward_input) |
| 516 | ✗ | detail::throw_not_implemented("conv_transpose2d_backward_input", Wt.device); | |
| 517 | 10 | detail::adopt_output(dX, Wt.device); | |
| 518 | 20 | v.conv_transpose2d_backward_input(Wt, dY, N, C_in, H, W, C_out, kH, kW, | |
| 519 | 10 | stride_h, stride_w, pad_h, pad_w, | |
| 520 | 10 | output_padding_h, output_padding_w, | |
| 521 | 10 | dil_h, dil_w, groups, dX); | |
| 522 | 10 | } | |
| 523 | 9 | void conv_transpose2d_backward_weight(const Tensor& X, const Tensor& dY, | |
| 524 | int N, int C_in, int H, int W, | ||
| 525 | int C_out, int kH, int kW, | ||
| 526 | int stride_h, int stride_w, | ||
| 527 | int pad_h, int pad_w, | ||
| 528 | int output_padding_h, int output_padding_w, | ||
| 529 | int dil_h, int dil_w, int groups, | ||
| 530 | Tensor& dWt) { | ||
| 531 | 9 | BROTENSOR_CHECK_SPATIAL_2D("conv_transpose2d_backward_weight", X, N, C_in, H, W); | |
| 532 | 9 | const auto& v = detail::dispatch(X, dY, dWt); | |
| 533 |
1/2✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
|
9 | if (!v.conv_transpose2d_backward_weight) |
| 534 | ✗ | detail::throw_not_implemented("conv_transpose2d_backward_weight", X.device); | |
| 535 | 9 | detail::adopt_output(dWt, X.device); | |
| 536 | 18 | v.conv_transpose2d_backward_weight(X, dY, N, C_in, H, W, C_out, kH, kW, | |
| 537 | 9 | stride_h, stride_w, pad_h, pad_w, | |
| 538 | 9 | output_padding_h, output_padding_w, | |
| 539 | 9 | dil_h, dil_w, groups, dWt); | |
| 540 | 9 | } | |
| 541 | 7 | void conv_transpose2d_backward_bias(const Tensor& dY, int N, int C_out, | |
| 542 | int H_out, int W_out, Tensor& dB) { | ||
| 543 | 7 | BROTENSOR_CHECK_SPATIAL_2D("conv_transpose2d_backward_bias", dY, N, C_out, H_out, W_out); | |
| 544 | 7 | const auto& v = detail::dispatch(dY, dB); | |
| 545 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | if (!v.conv_transpose2d_backward_bias) |
| 546 | ✗ | detail::throw_not_implemented("conv_transpose2d_backward_bias", dY.device); | |
| 547 | 7 | detail::adopt_output(dB, dY.device); | |
| 548 | 7 | v.conv_transpose2d_backward_bias(dY, N, C_out, H_out, W_out, dB); | |
| 549 | 7 | } | |
| 550 | |||
| 551 | 18 | void window_partition_forward(const Tensor& X, int N, int C, int H, int W, | |
| 552 | int window, Tensor& Y) { | ||
| 553 | 18 | BROTENSOR_CHECK_SPATIAL_2D("window_partition_forward", X, N, C, H, W); | |
| 554 | 18 | const auto& v = detail::dispatch(X, Y); | |
| 555 |
1/2✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
|
18 | if (!v.window_partition_forward) |
| 556 | ✗ | detail::throw_not_implemented("window_partition_forward", X.device); | |
| 557 | 18 | detail::adopt_output(Y, X.device); | |
| 558 | 18 | v.window_partition_forward(X, N, C, H, W, window, Y); | |
| 559 | 18 | } | |
| 560 | 12 | void window_reverse_forward(const Tensor& X, int N, int C, int H, int W, | |
| 561 | int window, Tensor& Y) { | ||
| 562 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | if (N <= 0 || C <= 0 || H <= 0 || W <= 0) { |
| 563 | ✗ | detail::throw_spatial_2d_error("window_reverse_forward", "X", | |
| 564 | ✗ | N, C, H, W, X.rows, X.cols); | |
| 565 | } | ||
| 566 |
3/6✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 12 times.
|
12 | if (window > 0 && H % window == 0 && W % window == 0) { |
| 567 | 12 | BROTENSOR_CHECK_SPATIAL_2D("window_reverse_forward", X, | |
| 568 | N * (H / window) * (W / window), C, window, window); | ||
| 569 | 12 | } | |
| 570 | 12 | const auto& v = detail::dispatch(X, Y); | |
| 571 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | if (!v.window_reverse_forward) |
| 572 | ✗ | detail::throw_not_implemented("window_reverse_forward", X.device); | |
| 573 | 12 | detail::adopt_output(Y, X.device); | |
| 574 | 12 | v.window_reverse_forward(X, N, C, H, W, window, Y); | |
| 575 | 12 | } | |
| 576 | |||
| 577 | // ─── NCHW <-> sequence ───────────────────────────────────────────────────── | ||
| 578 | |||
| 579 | 34 | void nchw_to_sequence(const Tensor& X, int N, int C, int H, int W, Tensor& Y) { | |
| 580 | 34 | BROTENSOR_CHECK_SPATIAL_2D("nchw_to_sequence", X, N, C, H, W); | |
| 581 | 34 | const auto& v = detail::dispatch(X, Y); | |
| 582 |
1/2✓ Branch 0 taken 34 times.
✗ Branch 1 not taken.
|
34 | if (!v.nchw_to_sequence) detail::throw_not_implemented("nchw_to_sequence", X.device); |
| 583 | 34 | detail::adopt_output(Y, X.device); | |
| 584 | 34 | v.nchw_to_sequence(X, N, C, H, W, Y); | |
| 585 | 34 | } | |
| 586 | |||
| 587 | 27 | void sequence_to_nchw(const Tensor& X, int N, int C, int H, int W, Tensor& Y) { | |
| 588 |
1/2✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
|
27 | if (N <= 0 || C <= 0 || H <= 0 || W <= 0) { |
| 589 | ✗ | detail::throw_spatial_2d_error("sequence_to_nchw", "X", | |
| 590 | ✗ | N, C, H, W, X.rows, X.cols); | |
| 591 | } | ||
| 592 | 27 | BROTENSOR_CHECK_SPATIAL_1D("sequence_to_nchw", X, N * H * W, C, 1); | |
| 593 | 27 | const auto& v = detail::dispatch(X, Y); | |
| 594 |
1/2✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
|
27 | if (!v.sequence_to_nchw) detail::throw_not_implemented("sequence_to_nchw", X.device); |
| 595 | 27 | detail::adopt_output(Y, X.device); | |
| 596 | 27 | v.sequence_to_nchw(X, N, C, H, W, Y); | |
| 597 | 27 | } | |
| 598 | |||
| 599 | 38 | void spatial_merge_2x2_forward(const Tensor& X, int N, int C, int H, int W, | |
| 600 | bool channel_major, Tensor& Y) { | ||
| 601 | 38 | BROTENSOR_CHECK_SPATIAL_2D("spatial_merge_2x2_forward", X, N, C, H, W); | |
| 602 | 38 | const auto& v = detail::dispatch(X, Y); | |
| 603 |
1/2✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
|
38 | if (!v.spatial_merge_2x2_forward) |
| 604 | ✗ | detail::throw_not_implemented("spatial_merge_2x2_forward", X.device); | |
| 605 | 38 | detail::adopt_output(Y, X.device); | |
| 606 | 38 | v.spatial_merge_2x2_forward(X, N, C, H, W, channel_major, Y); | |
| 607 | 38 | } | |
| 608 | |||
| 609 | 52 | void pixel_shuffle_upsample_2x_forward(const Tensor& X, int N, int C_in, | |
| 610 | int H, int W, int C_out, Tensor& Y) { | ||
| 611 |
7/8✓ Branch 0 taken 51 times.
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 50 times.
✓ Branch 3 taken 1 time.
✓ Branch 4 taken 48 times.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 48 times.
|
52 | if (N > 0 && C_in > 0 && H > 0 && W > 0) { |
| 612 | 48 | BROTENSOR_CHECK_SPATIAL_2D("pixel_shuffle_upsample_2x_forward", X, N, C_in, H, W); | |
| 613 | 48 | } | |
| 614 | 52 | const auto& v = detail::dispatch(X, Y); | |
| 615 |
1/2✓ Branch 0 taken 52 times.
✗ Branch 1 not taken.
|
52 | if (!v.pixel_shuffle_upsample_2x_forward) |
| 616 | ✗ | detail::throw_not_implemented("pixel_shuffle_upsample_2x_forward", X.device); | |
| 617 | 52 | detail::adopt_output(Y, X.device); | |
| 618 | 52 | v.pixel_shuffle_upsample_2x_forward(X, N, C_in, H, W, C_out, Y); | |
| 619 | 52 | } | |
| 620 | |||
| 621 | 16 | void patch_unpack_forward(const Tensor& tokens, int hp, int wp, int P, | |
| 622 | int C_total, int C_keep, bool channel_major, | ||
| 623 | Tensor& Y) { | ||
| 624 | 16 | const auto& v = detail::dispatch(tokens, Y); | |
| 625 |
1/2✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
|
16 | if (!v.patch_unpack_forward) |
| 626 | ✗ | detail::throw_not_implemented("patch_unpack_forward", tokens.device); | |
| 627 | 16 | detail::adopt_output(Y, tokens.device); | |
| 628 | 16 | v.patch_unpack_forward(tokens, hp, wp, P, C_total, C_keep, channel_major, Y); | |
| 629 | 16 | } | |
| 630 | |||
| 631 | // ─── ResBlock ────────────────────────────────────────────────────────────── | ||
| 632 | |||
| 633 | 26 | void resblock_forward(const Tensor& X, | |
| 634 | const Tensor& gamma1, const Tensor& beta1, | ||
| 635 | const Tensor& W1, const Tensor* b1, | ||
| 636 | const Tensor* t_emb_shift, | ||
| 637 | const Tensor& gamma2, const Tensor& beta2, | ||
| 638 | const Tensor& W2, const Tensor* b2, | ||
| 639 | const Tensor* Wskip, const Tensor* bskip, | ||
| 640 | int N, int C_in, int C_out, int H, int W, | ||
| 641 | int num_groups, float eps, Tensor& Y) { | ||
| 642 | 26 | BROTENSOR_CHECK_SPATIAL_2D("resblock_forward", X, N, C_in, H, W); | |
| 643 | 26 | const auto& v = detail::dispatch_with_opts( | |
| 644 | 104 | X, gamma1, {&beta1, &W1, b1, t_emb_shift, &gamma2, &beta2, &W2, b2, | |
| 645 | 78 | Wskip, bskip, &Y}); | |
| 646 |
1/2✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
|
26 | if (!v.resblock_forward) detail::throw_not_implemented("resblock_forward", X.device); |
| 647 | 26 | detail::adopt_output(Y, X.device); | |
| 648 | 52 | v.resblock_forward(X, gamma1, beta1, W1, b1, t_emb_shift, | |
| 649 | 26 | gamma2, beta2, W2, b2, Wskip, bskip, | |
| 650 | 26 | N, C_in, C_out, H, W, num_groups, eps, Y); | |
| 651 | 26 | } | |
| 652 | |||
| 653 | 7 | void resblock_forward_int8w_fp16(const Tensor& X, | |
| 654 | const Tensor& gamma1, const Tensor& beta1, | ||
| 655 | const Tensor& W1_int8, const Tensor& s1, | ||
| 656 | const Tensor* b1, | ||
| 657 | const Tensor* t_emb_shift, | ||
| 658 | const Tensor& gamma2, const Tensor& beta2, | ||
| 659 | const Tensor& W2_int8, const Tensor& s2, | ||
| 660 | const Tensor* b2, | ||
| 661 | const Tensor* Wskip_int8, const Tensor* sskip, | ||
| 662 | const Tensor* bskip, | ||
| 663 | int N, int C_in, int C_out, int H, int W, | ||
| 664 | int num_groups, float eps, Tensor& Y) { | ||
| 665 | 7 | BROTENSOR_CHECK_SPATIAL_2D("resblock_forward_int8w_fp16", X, N, C_in, H, W); | |
| 666 | 7 | const auto& v = detail::dispatch_with_opts( | |
| 667 | 70 | X, gamma1, {&beta1, &W1_int8, &s1, b1, t_emb_shift, | |
| 668 | 35 | &gamma2, &beta2, &W2_int8, &s2, b2, | |
| 669 | 28 | Wskip_int8, sskip, bskip, &Y}); | |
| 670 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | if (!v.resblock_forward_int8w_fp16) |
| 671 | ✗ | detail::throw_not_implemented("resblock_forward_int8w_fp16", X.device); | |
| 672 | 7 | detail::adopt_output(Y, X.device); | |
| 673 | 14 | v.resblock_forward_int8w_fp16(X, gamma1, beta1, W1_int8, s1, b1, t_emb_shift, | |
| 674 | 7 | gamma2, beta2, W2_int8, s2, b2, | |
| 675 | 7 | Wskip_int8, sskip, bskip, | |
| 676 | 7 | N, C_in, C_out, H, W, num_groups, eps, Y); | |
| 677 | 7 | } | |
| 678 | |||
| 679 | 20 | void resblock_backward(const Tensor& X, | |
| 680 | const Tensor& gamma1, const Tensor& beta1, | ||
| 681 | const Tensor& W1, const Tensor* b1, | ||
| 682 | const Tensor* t_emb_shift, | ||
| 683 | const Tensor& gamma2, const Tensor& beta2, | ||
| 684 | const Tensor& W2, const Tensor* b2, | ||
| 685 | const Tensor* Wskip, const Tensor* bskip, | ||
| 686 | int N, int C_in, int C_out, int H, int W, | ||
| 687 | int num_groups, float eps, | ||
| 688 | const Tensor& dY, | ||
| 689 | Tensor& dX, | ||
| 690 | Tensor& dGamma1, Tensor& dBeta1, | ||
| 691 | Tensor& dW1, Tensor* db1, | ||
| 692 | Tensor* dt_emb_shift, | ||
| 693 | Tensor& dGamma2, Tensor& dBeta2, | ||
| 694 | Tensor& dW2, Tensor* db2, | ||
| 695 | Tensor* dWskip, Tensor* dbskip) { | ||
| 696 | 20 | BROTENSOR_CHECK_SPATIAL_2D("resblock_backward", X, N, C_in, H, W); | |
| 697 | 20 | BROTENSOR_CHECK_SPATIAL_2D("resblock_backward", dY, N, C_out, H, W); | |
| 698 | 20 | const auto& v = detail::dispatch_with_opts( | |
| 699 | 320 | X, gamma1, {&beta1, &W1, b1, t_emb_shift, &gamma2, &beta2, &W2, b2, | |
| 700 | 160 | Wskip, bskip, &dY, &dX, &dGamma1, &dBeta1, &dW1, db1, | |
| 701 | 140 | dt_emb_shift, &dGamma2, &dBeta2, &dW2, db2, dWskip, dbskip}); | |
| 702 |
1/2✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
|
20 | if (!v.resblock_backward) detail::throw_not_implemented("resblock_backward", X.device); |
| 703 | 20 | detail::adopt_output(dX, X.device); | |
| 704 | 20 | detail::adopt_output(dGamma1, X.device); | |
| 705 | 20 | detail::adopt_output(dBeta1, X.device); | |
| 706 | 20 | detail::adopt_output(dW1, X.device); | |
| 707 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 18 times.
|
20 | if (db1) detail::adopt_output(*db1, X.device); |
| 708 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
|
20 | if (dt_emb_shift) detail::adopt_output(*dt_emb_shift, X.device); |
| 709 | 20 | detail::adopt_output(dGamma2, X.device); | |
| 710 | 20 | detail::adopt_output(dBeta2, X.device); | |
| 711 | 20 | detail::adopt_output(dW2, X.device); | |
| 712 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 18 times.
|
20 | if (db2) detail::adopt_output(*db2, X.device); |
| 713 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 9 times.
|
20 | if (dWskip) detail::adopt_output(*dWskip, X.device); |
| 714 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 9 times.
|
20 | if (dbskip) detail::adopt_output(*dbskip, X.device); |
| 715 | 40 | v.resblock_backward(X, gamma1, beta1, W1, b1, t_emb_shift, | |
| 716 | 20 | gamma2, beta2, W2, b2, Wskip, bskip, | |
| 717 | 20 | N, C_in, C_out, H, W, num_groups, eps, | |
| 718 | 20 | dY, dX, dGamma1, dBeta1, dW1, db1, dt_emb_shift, | |
| 719 | 20 | dGamma2, dBeta2, dW2, db2, dWskip, dbskip); | |
| 720 | 20 | } | |
| 721 | |||
| 722 | // ─── BatchNorm ───────────────────────────────────────────────────────────── | ||
| 723 | |||
| 724 | 11 | void batch_norm_forward(const Tensor& X, | |
| 725 | const Tensor& gamma, const Tensor& beta, | ||
| 726 | Tensor& running_mean, Tensor& running_var, | ||
| 727 | int N, int C, int H, int W, | ||
| 728 | float eps, float momentum, | ||
| 729 | Tensor& Y, | ||
| 730 | Tensor& saved_mean, Tensor& saved_rstd) { | ||
| 731 | 11 | BROTENSOR_CHECK_SPATIAL_2D("batch_norm_forward", X, N, C, H, W); | |
| 732 | 22 | const auto& v = detail::dispatch(X, gamma, beta, running_mean, running_var, | |
| 733 | 11 | Y, saved_mean, saved_rstd); | |
| 734 |
1/2✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
|
11 | if (!v.batch_norm_forward) |
| 735 | ✗ | detail::throw_not_implemented("batch_norm_forward", X.device); | |
| 736 | 11 | detail::adopt_output(running_mean, X.device); | |
| 737 | 11 | detail::adopt_output(running_var, X.device); | |
| 738 | 11 | detail::adopt_output(Y, X.device); | |
| 739 | 11 | detail::adopt_output(saved_mean, X.device); | |
| 740 | 11 | detail::adopt_output(saved_rstd, X.device); | |
| 741 | 22 | v.batch_norm_forward(X, gamma, beta, running_mean, running_var, | |
| 742 | 11 | N, C, H, W, eps, momentum, | |
| 743 | 11 | Y, saved_mean, saved_rstd); | |
| 744 | 11 | } | |
| 745 | |||
| 746 | 17 | void batch_norm_inference(const Tensor& X, | |
| 747 | const Tensor& gamma, const Tensor& beta, | ||
| 748 | const Tensor& running_mean, | ||
| 749 | const Tensor& running_var, | ||
| 750 | int N, int C, int H, int W, | ||
| 751 | float eps, | ||
| 752 | Tensor& Y) { | ||
| 753 | 17 | BROTENSOR_CHECK_SPATIAL_2D("batch_norm_inference", X, N, C, H, W); | |
| 754 | 17 | const auto& v = detail::dispatch(X, gamma, beta, running_mean, running_var, Y); | |
| 755 |
1/2✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
|
17 | if (!v.batch_norm_inference) |
| 756 | ✗ | detail::throw_not_implemented("batch_norm_inference", X.device); | |
| 757 | 17 | detail::adopt_output(Y, X.device); | |
| 758 | 34 | v.batch_norm_inference(X, gamma, beta, running_mean, running_var, | |
| 759 | 17 | N, C, H, W, eps, Y); | |
| 760 | 17 | } | |
| 761 | |||
| 762 | 7 | void batch_norm_backward(const Tensor& X, | |
| 763 | const Tensor& gamma, | ||
| 764 | const Tensor& saved_mean, | ||
| 765 | const Tensor& saved_rstd, | ||
| 766 | const Tensor& dY, | ||
| 767 | int N, int C, int H, int W, | ||
| 768 | Tensor& dX, | ||
| 769 | Tensor& dGamma, Tensor& dBeta) { | ||
| 770 | 7 | BROTENSOR_CHECK_SPATIAL_2D("batch_norm_backward", X, N, C, H, W); | |
| 771 | 7 | BROTENSOR_CHECK_SPATIAL_2D("batch_norm_backward", dY, N, C, H, W); | |
| 772 | 14 | const auto& v = detail::dispatch(X, gamma, saved_mean, saved_rstd, dY, | |
| 773 | 7 | dX, dGamma, dBeta); | |
| 774 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | if (!v.batch_norm_backward) |
| 775 | ✗ | detail::throw_not_implemented("batch_norm_backward", X.device); | |
| 776 | 7 | detail::adopt_output(dX, X.device); | |
| 777 | 7 | detail::adopt_output(dGamma, X.device); | |
| 778 | 7 | detail::adopt_output(dBeta, X.device); | |
| 779 | 14 | v.batch_norm_backward(X, gamma, saved_mean, saved_rstd, dY, | |
| 780 | 7 | N, C, H, W, dX, dGamma, dBeta); | |
| 781 | 7 | } | |
| 782 | |||
| 783 | // ─── Image preprocessing helpers ─────────────────────────────────────────── | ||
| 784 | |||
| 785 | 8 | void image_normalize(const Tensor& X, | |
| 786 | const Tensor& mean, const Tensor& std_, | ||
| 787 | int N, int C, int H, int W, | ||
| 788 | Tensor& Y) { | ||
| 789 | 8 | BROTENSOR_CHECK_SPATIAL_2D("image_normalize", X, N, C, H, W); | |
| 790 | 8 | const auto& v = detail::dispatch(X, mean, std_, Y); | |
| 791 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | if (!v.image_normalize) |
| 792 | ✗ | detail::throw_not_implemented("image_normalize", X.device); | |
| 793 | 8 | detail::adopt_output(Y, X.device); | |
| 794 | 8 | v.image_normalize(X, mean, std_, N, C, H, W, Y); | |
| 795 | 8 | } | |
| 796 | |||
| 797 | 17 | void image_u8_to_f32_nhwc_to_nchw(const uint8_t* src, | |
| 798 | int N, int H, int W, int C, | ||
| 799 | float scale, float bias, | ||
| 800 | Tensor& Y) { | ||
| 801 | 17 | const auto& v = detail::dispatch(Y); | |
| 802 |
1/2✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
|
17 | if (!v.image_u8_to_f32_nhwc_to_nchw) |
| 803 | ✗ | detail::throw_not_implemented("image_u8_to_f32_nhwc_to_nchw", Y.device); | |
| 804 | 17 | detail::adopt_output(Y, Y.device); | |
| 805 | 17 | v.image_u8_to_f32_nhwc_to_nchw(src, N, H, W, C, scale, bias, Y); | |
| 806 | 17 | } | |
| 807 | |||
| 808 | // ─── StyleGAN3 bias_act / upfirdn2d / modulated_conv2d ───────────────────── | ||
| 809 | |||
| 810 | 65 | void bias_act_forward(const Tensor& X, const Tensor* b, | |
| 811 | int N, int C, int HW, int act, float alpha, | ||
| 812 | float gain, float clamp, Tensor& Y) { | ||
| 813 | 65 | BROTENSOR_CHECK_SPATIAL_1D("bias_act_forward", X, N, C, HW); | |
| 814 | 65 | const auto& v = detail::dispatch_with_opts(X, {b, &Y}); | |
| 815 |
1/2✓ Branch 0 taken 65 times.
✗ Branch 1 not taken.
|
65 | if (!v.bias_act_forward) detail::throw_not_implemented("bias_act_forward", X.device); |
| 816 | 65 | detail::adopt_output(Y, X.device); | |
| 817 | 65 | v.bias_act_forward(X, b, N, C, HW, act, alpha, gain, clamp, Y); | |
| 818 | 65 | } | |
| 819 | |||
| 820 | 68 | void bias_act_backward(const Tensor& dY, const Tensor& X, const Tensor* b, | |
| 821 | int N, int C, int HW, int act, float alpha, | ||
| 822 | float gain, float clamp, Tensor& dX, Tensor* dB) { | ||
| 823 | 68 | BROTENSOR_CHECK_SPATIAL_1D("bias_act_backward", dY, N, C, HW); | |
| 824 | 68 | BROTENSOR_CHECK_SPATIAL_1D("bias_act_backward", X, N, C, HW); | |
| 825 | 68 | const auto& v = detail::dispatch_with_opts(dY, X, {b, dB, &dX}); | |
| 826 |
1/2✓ Branch 0 taken 68 times.
✗ Branch 1 not taken.
|
68 | if (!v.bias_act_backward) detail::throw_not_implemented("bias_act_backward", dY.device); |
| 827 | 68 | detail::adopt_output(dX, dY.device); | |
| 828 |
2/2✓ Branch 0 taken 36 times.
✓ Branch 1 taken 32 times.
|
68 | if (dB) detail::adopt_output(*dB, dY.device); |
| 829 | 68 | v.bias_act_backward(dY, X, b, N, C, HW, act, alpha, gain, clamp, dX, dB); | |
| 830 | 68 | } | |
| 831 | |||
| 832 | 50 | void upfirdn2d_forward(const Tensor& X, const Tensor& f, | |
| 833 | int N, int C, int H, int Wd, int fH, int fW, | ||
| 834 | int up_x, int up_y, int down_x, int down_y, | ||
| 835 | int pad_x0, int pad_x1, int pad_y0, int pad_y1, | ||
| 836 | bool flip_filter, float gain, Tensor& Y) { | ||
| 837 | 50 | BROTENSOR_CHECK_SPATIAL_2D("upfirdn2d_forward", X, N, C, H, Wd); | |
| 838 | 50 | const auto& v = detail::dispatch(X, f, Y); | |
| 839 |
1/2✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
|
50 | if (!v.upfirdn2d_forward) detail::throw_not_implemented("upfirdn2d_forward", X.device); |
| 840 | 50 | detail::adopt_output(Y, X.device); | |
| 841 | 100 | v.upfirdn2d_forward(X, f, N, C, H, Wd, fH, fW, up_x, up_y, down_x, down_y, | |
| 842 | 50 | pad_x0, pad_x1, pad_y0, pad_y1, flip_filter, gain, Y); | |
| 843 | 50 | } | |
| 844 | |||
| 845 | 47 | void upfirdn2d_backward(const Tensor& dY, const Tensor& f, | |
| 846 | int N, int C, int H, int Wd, int fH, int fW, | ||
| 847 | int up_x, int up_y, int down_x, int down_y, | ||
| 848 | int pad_x0, int pad_x1, int pad_y0, int pad_y1, | ||
| 849 | bool flip_filter, float gain, Tensor& dX) { | ||
| 850 |
1/2✓ Branch 0 taken 47 times.
✗ Branch 1 not taken.
|
47 | if (N <= 0 || C <= 0 || H <= 0 || Wd <= 0) { |
| 851 | ✗ | detail::throw_spatial_2d_error("upfirdn2d_backward", "dY", | |
| 852 | ✗ | N, C, H, Wd, dY.rows, dY.cols); | |
| 853 | } | ||
| 854 | 47 | const auto& v = detail::dispatch(dY, f, dX); | |
| 855 |
1/2✓ Branch 0 taken 47 times.
✗ Branch 1 not taken.
|
47 | if (!v.upfirdn2d_backward) detail::throw_not_implemented("upfirdn2d_backward", dY.device); |
| 856 | 47 | detail::adopt_output(dX, dY.device); | |
| 857 | 94 | v.upfirdn2d_backward(dY, f, N, C, H, Wd, fH, fW, up_x, up_y, down_x, down_y, | |
| 858 | 47 | pad_x0, pad_x1, pad_y0, pad_y1, flip_filter, gain, dX); | |
| 859 | 47 | } | |
| 860 | |||
| 861 | 32 | void modulated_conv2d_forward(const Tensor& X, const Tensor& W, const Tensor& s, | |
| 862 | int N, int C_in, int H, int Wd, | ||
| 863 | int C_out, int kH, int kW, | ||
| 864 | int pad_h, int pad_w, | ||
| 865 | bool demodulate, float eps, | ||
| 866 | Tensor& dcoef, Tensor& Y) { | ||
| 867 | 32 | BROTENSOR_CHECK_SPATIAL_2D("modulated_conv2d_forward", X, N, C_in, H, Wd); | |
| 868 | 32 | const auto& v = detail::dispatch(X, W, s, dcoef, Y); | |
| 869 |
1/2✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
|
32 | if (!v.modulated_conv2d_forward) |
| 870 | ✗ | detail::throw_not_implemented("modulated_conv2d_forward", X.device); | |
| 871 | 32 | detail::adopt_output(dcoef, X.device); | |
| 872 | 32 | detail::adopt_output(Y, X.device); | |
| 873 | 64 | v.modulated_conv2d_forward(X, W, s, N, C_in, H, Wd, C_out, kH, kW, | |
| 874 | 32 | pad_h, pad_w, demodulate, eps, dcoef, Y); | |
| 875 | 32 | } | |
| 876 | |||
| 877 | 42 | void modulated_conv2d_backward(const Tensor& X, const Tensor& W, const Tensor& s, | |
| 878 | const Tensor& dcoef, const Tensor& dY, | ||
| 879 | int N, int C_in, int H, int Wd, | ||
| 880 | int C_out, int kH, int kW, | ||
| 881 | int pad_h, int pad_w, bool demodulate, float eps, | ||
| 882 | Tensor& dX, Tensor& dW, Tensor& ds) { | ||
| 883 | 42 | BROTENSOR_CHECK_SPATIAL_2D("modulated_conv2d_backward", X, N, C_in, H, Wd); | |
| 884 | 42 | BROTENSOR_CHECK_SPATIAL_2D("modulated_conv2d_backward", dY, N, C_out, H, Wd); | |
| 885 | 42 | const auto& v = detail::dispatch(X, W, s, dcoef, dY, dX, dW, ds); | |
| 886 |
1/2✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
|
42 | if (!v.modulated_conv2d_backward) |
| 887 | ✗ | detail::throw_not_implemented("modulated_conv2d_backward", X.device); | |
| 888 | 42 | detail::adopt_output(dX, X.device); | |
| 889 | 42 | detail::adopt_output(dW, X.device); | |
| 890 | 42 | detail::adopt_output(ds, X.device); | |
| 891 | 84 | v.modulated_conv2d_backward(X, W, s, dcoef, dY, N, C_in, H, Wd, C_out, kH, kW, | |
| 892 | 42 | pad_h, pad_w, demodulate, eps, dX, dW, ds); | |
| 893 | 42 | } | |
| 894 | |||
| 895 | } // namespace brotensor | ||
| 896 |