Skip to content

Commit ee1ddce

Browse files
mrshenlifacebook-github-bot
authored andcommitted
Acquire GIL when constructing/destructing ConcretePyObjectHolder (#37870)
Summary: Pull Request resolved: #37870 Test Plan: Imported from OSS Differential Revision: D21410785 fbshipit-source-id: 374d5f40fbdfec98262aa4c84ec4ccdc40fb2ac1
1 parent 594b33e commit ee1ddce

3 files changed

Lines changed: 31 additions & 46 deletions

File tree

torch/csrc/distributed/rpc/python_functions.cpp

Lines changed: 15 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -105,52 +105,29 @@ std::shared_ptr<FutureMessage> sendPythonRemoteCall(
105105
true /*forceGradRecording*/);
106106
}
107107

108-
void DeleteFutureIValue(FutureIValue* fv) {
109-
if (fv->constValue().isPyObject()) {
110-
pybind11::gil_scoped_acquire ag;
111-
delete fv;
112-
} else {
113-
delete fv;
114-
}
115-
}
116-
117108
} // namespace
118109

119110
using namespace torch::distributed::autograd;
120111

121112
std::shared_ptr<FutureIValue> toFutureIValue(
122113
const std::shared_ptr<FutureMessage>& fm,
123114
bool hasValue) {
124-
if (hasValue) {
125-
// NB: The custom deleter is necessary because the FutureIValue object
126-
// holds a py::object and it would require GIL to delete.
127-
std::shared_ptr<FutureIValue> fv(new FutureIValue(), DeleteFutureIValue);
128-
129-
fm->addCallback([fv](const FutureMessage& fm) {
130-
// Don't need to acquire GIL here, as toPyObj acquires GIL
131-
// when creating the py::object
132-
if (fm.hasError()) {
133-
fv->setError(*fm.error());
134-
} else {
135-
fv->markCompleted(
136-
jit::toIValue(toPyObj(fm.constValue()), PyObjectType::get()));
137-
}
138-
});
139-
140-
return fv;
141-
} else {
142-
auto fv = std::make_shared<FutureIValue>();
143-
144-
fm->addCallback([fv](const FutureMessage& fm) {
145-
if (fm.hasError()) {
146-
fv->setError(*fm.error());
147-
} else {
148-
fv->markCompleted(IValue());
149-
}
150-
});
115+
auto fv = std::make_shared<FutureIValue>();
116+
117+
fm->addCallback([fv, hasValue](const FutureMessage& fm) {
118+
if (fm.hasError()) {
119+
fv->setError(*fm.error());
120+
} else if (hasValue) {
121+
// Don't need to acquire GIL here, as toPyObj and toIValue acquires GIL
122+
// when creating/copying the py::object
123+
fv->markCompleted(
124+
jit::toIValue(toPyObj(fm.constValue()), PyObjectType::get()));
125+
} else {
126+
fv->markCompleted(IValue());
127+
}
128+
});
151129

152-
return fv;
153-
}
130+
return fv;
154131
}
155132

156133
std::shared_ptr<FutureIValue> pyRpcBuiltin(

torch/csrc/jit/python/pybind_utils.h

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -604,11 +604,9 @@ inline IValue toIValue(
604604
AT_ERROR("RRef is only supported with the distributed package");
605605
#endif
606606
} break;
607-
case TypeKind::PyObjectType:
608-
// convert a py::handle to the IValue that holds the py::object
609-
return c10::ivalue::ConcretePyObjectHolder::create(
610-
obj.cast<py::object>());
611-
607+
case TypeKind::PyObjectType: {
608+
return c10::ivalue::ConcretePyObjectHolder::create(obj);
609+
}
612610
case TypeKind::CapsuleType: {
613611
return IValue::make_capsule(
614612
py::cast<c10::intrusive_ptr<CustomClassHolder>>(obj));

torch/csrc/jit/python/python_ivalue.h

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,27 @@ namespace ivalue {
1111
struct C10_EXPORT ConcretePyObjectHolder final : PyObjectHolder {
1212
public:
1313
static c10::intrusive_ptr<PyObjectHolder> create(py::object py_obj) {
14-
return c10::make_intrusive<ConcretePyObjectHolder>(py_obj);
14+
return c10::make_intrusive<ConcretePyObjectHolder>(std::move(py_obj));
15+
}
16+
17+
static c10::intrusive_ptr<PyObjectHolder> create(const py::handle& handle) {
18+
py::gil_scoped_acquire ag;
19+
return c10::make_intrusive<ConcretePyObjectHolder>(
20+
handle.cast<py::object>());
1521
}
1622

1723
PyObject* getPyObject() override {
1824
return py_obj_.ptr();
1925
}
2026

21-
~ConcretePyObjectHolder() {}
27+
~ConcretePyObjectHolder() {
28+
pybind11::gil_scoped_acquire ag;
29+
py_obj_ = py::none();
30+
}
2231
// explicit construction to avoid errornous implicit conversion and
2332
// copy-initialization
24-
explicit ConcretePyObjectHolder(py::object py_obj) : py_obj_(py_obj) {}
33+
explicit ConcretePyObjectHolder(py::object py_obj)
34+
: py_obj_(std::move(py_obj)) {}
2535

2636
private:
2737
py::object py_obj_;

0 commit comments

Comments
 (0)