input: grad_output: (N, h, C//h) output: (M, h), (N, h, C//h), None, None
(ctx, grad_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 | |
| 265 | attention_step2 = AttentionStep2.apply |
| 266 |
nothing calls this directly
no outgoing calls
no test coverage detected