trenden commited on
Commit
ffdfa08
·
verified ·
1 Parent(s): e81a84f

Upload sgmse/backbones/ncsnpp_utils/op/upfirdn2d.py

Browse files
sgmse/backbones/ncsnpp_utils/op/upfirdn2d.py ADDED
@@ -0,0 +1,203 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+
3
+ import torch
4
+ from torch.nn import functional as F
5
+ from torch.autograd import Function
6
+ from torch.utils.cpp_extension import load
7
+
8
+
9
+ module_path = os.path.dirname(__file__)
10
+
11
+ if torch.cuda.is_available():
12
+ upfirdn2d_op = load(
13
+ "upfirdn2d",
14
+ sources=[
15
+ os.path.join(module_path, "upfirdn2d.cpp"),
16
+ os.path.join(module_path, "upfirdn2d_kernel.cu"),
17
+ ],
18
+ )
19
+ else:
20
+ upfirdn2d_op = None
21
+
22
+ class UpFirDn2dBackward(Function):
23
+ @staticmethod
24
+ def forward(
25
+ ctx, grad_output, kernel, grad_kernel, up, down, pad, g_pad, in_size, out_size
26
+ ):
27
+
28
+ up_x, up_y = up
29
+ down_x, down_y = down
30
+ g_pad_x0, g_pad_x1, g_pad_y0, g_pad_y1 = g_pad
31
+
32
+ grad_output = grad_output.reshape(-1, out_size[0], out_size[1], 1)
33
+
34
+ grad_input = upfirdn2d_op.upfirdn2d(
35
+ grad_output,
36
+ grad_kernel,
37
+ down_x,
38
+ down_y,
39
+ up_x,
40
+ up_y,
41
+ g_pad_x0,
42
+ g_pad_x1,
43
+ g_pad_y0,
44
+ g_pad_y1,
45
+ )
46
+ grad_input = grad_input.view(in_size[0], in_size[1], in_size[2], in_size[3])
47
+
48
+ ctx.save_for_backward(kernel)
49
+
50
+ pad_x0, pad_x1, pad_y0, pad_y1 = pad
51
+
52
+ ctx.up_x = up_x
53
+ ctx.up_y = up_y
54
+ ctx.down_x = down_x
55
+ ctx.down_y = down_y
56
+ ctx.pad_x0 = pad_x0
57
+ ctx.pad_x1 = pad_x1
58
+ ctx.pad_y0 = pad_y0
59
+ ctx.pad_y1 = pad_y1
60
+ ctx.in_size = in_size
61
+ ctx.out_size = out_size
62
+
63
+ return grad_input
64
+
65
+ @staticmethod
66
+ def backward(ctx, gradgrad_input):
67
+ kernel, = ctx.saved_tensors
68
+
69
+ gradgrad_input = gradgrad_input.reshape(-1, ctx.in_size[2], ctx.in_size[3], 1)
70
+
71
+ gradgrad_out = upfirdn2d_op.upfirdn2d(
72
+ gradgrad_input,
73
+ kernel,
74
+ ctx.up_x,
75
+ ctx.up_y,
76
+ ctx.down_x,
77
+ ctx.down_y,
78
+ ctx.pad_x0,
79
+ ctx.pad_x1,
80
+ ctx.pad_y0,
81
+ ctx.pad_y1,
82
+ )
83
+ # gradgrad_out = gradgrad_out.view(ctx.in_size[0], ctx.out_size[0], ctx.out_size[1], ctx.in_size[3])
84
+ gradgrad_out = gradgrad_out.view(
85
+ ctx.in_size[0], ctx.in_size[1], ctx.out_size[0], ctx.out_size[1]
86
+ )
87
+
88
+ return gradgrad_out, None, None, None, None, None, None, None, None
89
+
90
+
91
+ class UpFirDn2d(Function):
92
+ @staticmethod
93
+ def forward(ctx, input, kernel, up, down, pad):
94
+ up_x, up_y = up
95
+ down_x, down_y = down
96
+ pad_x0, pad_x1, pad_y0, pad_y1 = pad
97
+
98
+ kernel_h, kernel_w = kernel.shape
99
+ batch, channel, in_h, in_w = input.shape
100
+ ctx.in_size = input.shape
101
+
102
+ input = input.reshape(-1, in_h, in_w, 1)
103
+
104
+ ctx.save_for_backward(kernel, torch.flip(kernel, [0, 1]))
105
+
106
+ out_h = (in_h * up_y + pad_y0 + pad_y1 - kernel_h) // down_y + 1
107
+ out_w = (in_w * up_x + pad_x0 + pad_x1 - kernel_w) // down_x + 1
108
+ ctx.out_size = (out_h, out_w)
109
+
110
+ ctx.up = (up_x, up_y)
111
+ ctx.down = (down_x, down_y)
112
+ ctx.pad = (pad_x0, pad_x1, pad_y0, pad_y1)
113
+
114
+ g_pad_x0 = kernel_w - pad_x0 - 1
115
+ g_pad_y0 = kernel_h - pad_y0 - 1
116
+ g_pad_x1 = in_w * up_x - out_w * down_x + pad_x0 - up_x + 1
117
+ g_pad_y1 = in_h * up_y - out_h * down_y + pad_y0 - up_y + 1
118
+
119
+ ctx.g_pad = (g_pad_x0, g_pad_x1, g_pad_y0, g_pad_y1)
120
+
121
+ out = upfirdn2d_op.upfirdn2d(
122
+ input, kernel, up_x, up_y, down_x, down_y, pad_x0, pad_x1, pad_y0, pad_y1
123
+ )
124
+ # out = out.view(major, out_h, out_w, minor)
125
+ out = out.view(-1, channel, out_h, out_w)
126
+
127
+ return out
128
+
129
+ @staticmethod
130
+ def backward(ctx, grad_output):
131
+ kernel, grad_kernel = ctx.saved_tensors
132
+
133
+ grad_input = UpFirDn2dBackward.apply(
134
+ grad_output,
135
+ kernel,
136
+ grad_kernel,
137
+ ctx.up,
138
+ ctx.down,
139
+ ctx.pad,
140
+ ctx.g_pad,
141
+ ctx.in_size,
142
+ ctx.out_size,
143
+ )
144
+
145
+ return grad_input, None, None, None, None
146
+
147
+
148
+ def upfirdn2d(input, kernel, up=1, down=1, pad=(0, 0)):
149
+ if input.device.type == "cpu":
150
+ out = upfirdn2d_native(
151
+ input, kernel, up, up, down, down, pad[0], pad[1], pad[0], pad[1]
152
+ )
153
+
154
+ else:
155
+ out = UpFirDn2d.apply(
156
+ input, kernel, (up, up), (down, down), (pad[0], pad[1], pad[0], pad[1])
157
+ )
158
+
159
+ return out
160
+
161
+
162
+ def upfirdn2d_native(
163
+ input, kernel, up_x, up_y, down_x, down_y, pad_x0, pad_x1, pad_y0, pad_y1
164
+ ):
165
+ _, channel, in_h, in_w = input.shape
166
+ input = input.reshape(-1, in_h, in_w, 1)
167
+
168
+ _, in_h, in_w, minor = input.shape
169
+ kernel_h, kernel_w = kernel.shape
170
+
171
+ out = input.view(-1, in_h, 1, in_w, 1, minor)
172
+ out = F.pad(out, [0, 0, 0, up_x - 1, 0, 0, 0, up_y - 1])
173
+ out = out.view(-1, in_h * up_y, in_w * up_x, minor)
174
+
175
+ out = F.pad(
176
+ out, [0, 0, max(pad_x0, 0), max(pad_x1, 0), max(pad_y0, 0), max(pad_y1, 0)]
177
+ )
178
+ out = out[
179
+ :,
180
+ max(-pad_y0, 0) : out.shape[1] - max(-pad_y1, 0),
181
+ max(-pad_x0, 0) : out.shape[2] - max(-pad_x1, 0),
182
+ :,
183
+ ]
184
+
185
+ out = out.permute(0, 3, 1, 2)
186
+ out = out.reshape(
187
+ [-1, 1, in_h * up_y + pad_y0 + pad_y1, in_w * up_x + pad_x0 + pad_x1]
188
+ )
189
+ w = torch.flip(kernel, [0, 1]).view(1, 1, kernel_h, kernel_w)
190
+ out = F.conv2d(out, w)
191
+ out = out.reshape(
192
+ -1,
193
+ minor,
194
+ in_h * up_y + pad_y0 + pad_y1 - kernel_h + 1,
195
+ in_w * up_x + pad_x0 + pad_x1 - kernel_w + 1,
196
+ )
197
+ out = out.permute(0, 2, 3, 1)
198
+ out = out[:, ::down_y, ::down_x, :]
199
+
200
+ out_h = (in_h * up_y + pad_y0 + pad_y1 - kernel_h) // down_y + 1
201
+ out_w = (in_w * up_x + pad_x0 + pad_x1 - kernel_w) // down_x + 1
202
+
203
+ return out.view(-1, channel, out_h, out_w)