venite's picture
initial
f670afc
# Copyright (C) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#
# This work is made available under the Nvidia Source Code License-NC.
# To view a copy of this license, check out LICENSE.md
import torch
from torch.autograd import Function
import voxlib
# Cheatsheet:
# mark_dirty() must be used to mark any input that is modified inplace by the forward function.
# mark_non_differentiable()
class PositionalEncodingFunction(Function):
@staticmethod
def forward(ctx, in_feature, pe_degrees, dim, incl_orig):
out_feature = voxlib.positional_encoding(in_feature, pe_degrees, dim, incl_orig)
ctx.save_for_backward(out_feature)
ctx.pe_degrees = pe_degrees
ctx.dim = dim
ctx.incl_orig = incl_orig
return out_feature
@staticmethod
def backward(ctx, out_feature_grad):
out_feature, = ctx.saved_tensors
# torch::Tensor positional_encoding_backward(const torch::Tensor& out_feature_grad,
# const torch::Tensor& out_feature, int ndegrees, int dim, bool incl_orig) {
in_feature_grad = voxlib.positional_encoding_backward(
out_feature_grad, out_feature, ctx.pe_degrees, ctx.dim, ctx.incl_orig)
return in_feature_grad, None, None, None
def positional_encoding(in_feature, pe_degrees, dim=-1, incl_orig=False):
return PositionalEncodingFunction.apply(in_feature, pe_degrees, dim, incl_orig)
# input: N, C
# output: N, pe_degrees*C
def positional_encoding_pt(pts, pe_degrees, dim=-1, incl_orig=False):
import numpy as np
pe_stor = []
for i in range(pe_degrees):
pe_stor.append(torch.sin(pts * np.pi * 2 ** i))
pe_stor.append(torch.cos(pts * np.pi * 2 ** i))
if incl_orig:
pe_stor.append(pts)
pe = torch.cat(pe_stor, dim=dim)
return pe
if __name__ == '__main__':
x = torch.rand(384, 512, 5, 48).cuda() * 1024
y = positional_encoding_pt(x, 4, incl_orig=True)
y2 = positional_encoding(x, 4, incl_orig=True)
print(torch.abs(y - y2))
print(torch.allclose(y, y2, rtol=1e-05, atol=1e-05))