Skip to content

Commit

Permalink
add minimal example that reproduces the nanobind leak error
Browse files Browse the repository at this point in the history
  • Loading branch information
tingyu66 committed Dec 7, 2022
1 parent 7c3bf12 commit 8629419
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 1 deletion.
2 changes: 1 addition & 1 deletion src/nanobind_example/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
from .nanobind_example_ext import add
from .nanobind_example_ext import add, Foo, make_foo
17 changes: 17 additions & 0 deletions src/nanobind_example_ext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,23 @@ namespace nb = nanobind;

using namespace nb::literals;

struct Foo {
int a;
float b;
};

Foo makeFoo(int _a, float _b) {
Foo foo = {_a, _b};
return foo;
}

NB_MODULE(nanobind_example_ext, m) {
m.def("add", [](int a, int b) { return a + b; }, "a"_a, "b"_a);

nb::class_<Foo>(m, "Foo")
.def_readonly("a", &Foo::a)
.def_readonly("b", &Foo::b);

m.def("make_foo", &makeFoo, nb::arg("a"), nb::arg("b"));

}
24 changes: 24 additions & 0 deletions tests/test_autograd.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import torch
import math
from nanobind_example import *

# example adapted from https://pytorch.org/tutorials/beginner/examples_autograd/two_layer_net_custom_function.html
class LegendrePolynomial3(torch.autograd.Function):
@staticmethod
def forward(ctx, input, foo):
ctx.foo = foo
ctx.save_for_backward(input)
return 0.5 * (5 * input ** 3 - 3 * input)

@staticmethod
def backward(ctx, grad_output):
input, = ctx.saved_tensors
return grad_output * 1.5 * (5 * input ** 2 - 1), None

input_tensor = torch.rand(3,3)
input_tensor.requires_grad_()
foo = make_foo(1, 0.5)

output = LegendrePolynomial3.apply(input_tensor, foo)
grad_output = torch.rand_like(output)
output.backward(grad_output)

1 comment on commit 8629419

@tingyu66
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

test_autograd.py is a minimal reproducible example for the nanobind leak error.
My guess is that passing reference to ctx messed up the reference counts from nanobind, as the error went away when removing the line ctx.foo = foo.

(nanobind_example) ➜  tests git:(master) ✗ python test_autograd.py             
nanobind: leaked 1 instances!
nanobind: leaked 1 types!
 - leaked type "nanobind_example.nanobind_example_ext.Foo"
nanobind: leaked 2 functions!
 - leaked function "<anonymous>"
 - leaked function "<anonymous>"
nanobind: this is likely caused by a reference counting issue in the binding code.

Please sign in to comment.