-
Notifications
You must be signed in to change notification settings - Fork 135
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Interaction of DLManagedTensor::deleter
and the GIL
#103
Comments
Thanks @wjakob ! Indeed this is worth clarifying. As far as I know, GIL is not necessary if the deleter is defined in C API. There can be cases where the deleter itself is defined by python's FFI mechanism, in such case, the GIL holding could happen inside the deleter, but nevertheless not the job of the caller of the deleter |
The C docs clearly should not know anything about the GIL. As for the Python docs, this section talks about transfer of ownership of @wjakob what exact comment/phrasing would help you here? |
How about the following?
|
Thanks, looks reasonable - except " |
Really? Maybe I am misunderstanding something. My mental picture is:
Suppose Framework X needs to run a few python operations to clean up tensor that is now unreferenced. It needs to acquire the GIL to invoke those Python API calls safely. However, the part of Framework Y that released the consumed tensor has no idea about Python or the GIL. So it's the responsibility of the implementation of the deleter (provided by framework X) to first acquire the GIL before subsequent steps. |
@wjakob I think your interpretation is correct. However, most of the frameworks implement the allocation of the object themselves in C/C++/cython, then expose to python, in which case the deleter donot need to acquire GIL. |
It is easier for the |
@leofang I think part of the confusion is that there are effectively two "deleters", and perhaps it would be good to come up with some kind of terminology in the documentation to avoid ambiguity.
So my suggestion would be to add a sentence to the documentation saying that Hypothetical example: what if void my_deleter(struct DLManagedTensor * self) {
PyGILState_STATE state = PyGILState_Ensure();
Py_DECREF((PyObject *) (self->manager_ctx));
PyGILState_Release(state);
} |
I'm not sure it's that confusing; at least to me "the deleter" is always
This sentence makes sense to me. It probably needs some context that the remark is intended for implementers of a Python library, who may not be aware that there are non-Python DLPack users. Otherwise it's more confusing than helpful for C/C++ users, who will wonder why on earth they need to bother with a lock from a language they're not using. |
There is nothing hypothetical about this. This is the current way NumPy, cupy, and probably half of the other Python providers work. So this is a very important clarification that many implementations will violate as soon as it is formalized. |
My suggestion would be that the |
Yes, it seems that it should probably be written that "the deleter MUST NOT assume that the GIL is held when it is called" (for Python but applies to any other environment). |
Noisy +1 to this. This would make things clearer for exporters of non-Python data (such as PyArrow). |
feel free to send a PR |
I honestly don't remember if that ``Py_IsInitialized`` wasn't just to tape over C++ related deficiencies, but I suspect there isn't much to be avoided there... (I.e. if we take care of the GIL for the other library, we also have to do this check for them which would normally be their job.) Closes dmlcgh-103
* DOC: Document that GIL must be grabbed (and Py_IsInitialized()) I honestly don't remember if that ``Py_IsInitialized`` wasn't just to tape over C++ related deficiencies, but I suspect there isn't much to be avoided there... (I.e. if we take care of the GIL for the other library, we also have to do this check for them which would normally be their job.) Closes gh-103 * Apply suggestions from code review Co-authored-by: Antoine Pitrou <[email protected]> * Update docs/source/python_spec.rst Co-authored-by: Antoine Pitrou <[email protected]> * Add note that this of course only applies if it uses Python objects/API --------- Co-authored-by: Antoine Pitrou <[email protected]>
Dear DLPack authors,
DLPack is widely used to enable interoperability between large C++-based frameworks that furthermore provide Python bindings. The C++ parts of such a framework are often usable through an independent C++ API (e.g. in the case of PyTorch, Tensorflow, ..), where functions can be called from multi-threaded code. In contrast, multithreading in Python is much more restricted: any use of the CPython API requires that the Global Interpreter Lock (GIL) is held.
This discrepancy has implications on projects mixing C++ and Python code. Function in such a mixed C++/Python codebase should clarify require whether the caller should ensure that the GIL is held.
This is currently unclear in the case of
DLManagedTensor::deleter
, which could be called by thePyCapsule
destructor (where the GIL is held) or from arbitrary C++ code at some later point following "consumption" of the capsule (where the GIL is not necessarily held -- this destructor call could even occur from a different thread!)I don't have any strong opinions either way, but ideally the documentation of the interfaces should say so.
Thanks,
Wenzel
The text was updated successfully, but these errors were encountered: