| 205 | |
| 206 | |
| 207 | class AttentionStep2(Function): |
| 208 | @staticmethod |
| 209 | def forward(ctx, attn, v, index0, index1): |
| 210 | """ |
| 211 | input: attn: (M, h), v: (N, h, C//h), index0: (M), index1: (M) |
| 212 | output: output: [N, h, C//h] |
| 213 | """ |
| 214 | assert attn.is_contiguous() and v.is_contiguous() and index0.is_contiguous() and index1.is_contiguous() |
| 215 | |
| 216 | M, h = attn.shape |
| 217 | N_q = index0.max().item() + 1 |
| 218 | N_v, h, C_div_h = v.shape |
| 219 | C = int(C_div_h * h) |
| 220 | |
| 221 | output = torch.cuda.FloatTensor(N_q, h, C//h).zero_() |
| 222 | pointops_cuda.attention_step2_forward_cuda(N_q, M, h, C, attn, v, index0, index1, output) |
| 223 | ctx.M = M |
| 224 | |
| 225 | # print("attn[:5,:5]: ", attn[:5, :5]) |
| 226 | |
| 227 | ctx.save_for_backward(attn, v, index0, index1) |
| 228 | return output |
| 229 | |
| 230 | @staticmethod |
| 231 | def backward(ctx, grad_output): |
| 232 | """ |
| 233 | input: grad_output: (N, h, C//h) |
| 234 | output: (M, h), (N, h, C//h), None, None |
| 235 | """ |
| 236 | M = ctx.M |
| 237 | attn, v, index0, index1 = ctx.saved_tensors |
| 238 | N_v = v.shape[0] |
| 239 | N_q, h, C_div_h = grad_output.shape |
| 240 | C = h * C_div_h |
| 241 | |
| 242 | grad_output = grad_output.contiguous() |
| 243 | # print("grad_output.is_contiguous(): ", grad_output.is_contiguous()) |
| 244 | assert attn.is_contiguous() and v.is_contiguous() and index0.is_contiguous() and index1.is_contiguous() and grad_output.is_contiguous() |
| 245 | |
| 246 | # print("back: attn[:5,:5]: ", attn[:5, :5]) |
| 247 | |
| 248 | # print("attn.shape: {} v.shape: {}, index0.shape: {}, index1.shape: {}".format(attn.shape, v.shape, index0.shape, index1.shape)) |
| 249 | |
| 250 | grad_attn = torch.cuda.FloatTensor(M, h).zero_() |
| 251 | grad_v = torch.cuda.FloatTensor(N_v, h, C//h).zero_() |
| 252 | |
| 253 | # torch.cuda.synchronize() |
| 254 | # start = time.time() |
| 255 | |
| 256 | pointops_cuda.attention_step2_backward_cuda(N_q, M, h, C, grad_output, index0, index1, attn, v, grad_attn, grad_v) |
| 257 | |
| 258 | # torch.cuda.synchronize() |
| 259 | # end = time.time() |
| 260 | # print("time v8: {}".format(end - start)) |
| 261 | # # input() |
| 262 | |
| 263 | return grad_attn, grad_v, None, None |
| 264 |
nothing calls this directly
no outgoing calls
no test coverage detected