Skip to content

ENH: Implement DLPack version 1#26501

Merged
mattip merged 6 commits intonumpy:mainfrom
seberg:dlpack-v1
Jun 5, 2024
Merged

ENH: Implement DLPack version 1#26501
mattip merged 6 commits intonumpy:mainfrom
seberg:dlpack-v1

Conversation

@seberg
Copy link
Member

@seberg seberg commented May 22, 2024

This implements DLPack version 1 to close gh-26411.

Note that I had first tried to use C++ templating to avoid the duplication, but in the end the additional complexity of it didn't really seem worthwhile compared to duplicating the few functions.

Although a lot is just moved around, this is an unfortunately large diff. The new and old code paths should be (mostly) tested, but the nature of dlpack is that it is hard to test interaction with others (e.g. gpu failure paths).

I decided to always pass device/copy as None to simplify the call sites.

It does fix a few smaller issues as well.

@seberg seberg added the 56 - Needs Release Note. Needs an entry in doc/release/upcoming_changes label May 22, 2024
@seberg
Copy link
Member Author

seberg commented May 22, 2024

I had started with "could backport this", but I am not sure as it isn't trivial. Anyway, i still needs release notes and all that changes would be whether it we write 2.1 or 2.2 in a few places.

{
/* an exception may be in-flight, we must save it in case we create another one */
PyObject *type, *value, *traceback;
PyErr_Fetch(&type, &value, &traceback);
Copy link
Member Author

Choose a reason for hiding this comment

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

This was always unnecessary, just missed that it was also here when removing it in the version above...

}

// ensure alignment
int offset = sizeof(DLManagedTensor) % sizeof(void *);
Copy link
Member Author

Choose a reason for hiding this comment

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

This offset calculation was just wrong. It simply didn't matter because the struct size is a multiple of this anyway in practice.

* can then be removed again.
*/
PyObject *res = create_dlpack_capsule(
self, major_version >= 1, &result_device);
Copy link
Member Author

Choose a reason for hiding this comment

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

Maybe to explain, the result_device is checked for validity already during argument parsing, so it's OK to just adopt it.
No matter what device we have, if NumPy supports it, we can re-export it as CPU.

@mattip
Copy link
Member

mattip commented May 23, 2024

I think the failing test is fixed in #26503

Copy link
Member

@mattip mattip left a comment

Choose a reason for hiding this comment

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

This could use a release note.

It seems the major change is supporting both DLManagedTensor and DLManagedTensorVersioned, but then I am confused since the DLManagedTensorVersioned struct already existed. Could you explain what is going on to help reviewers?

*
* Note that as of Nov 2021, multiply libraries (CuPy, PyTorch, TensorFlow,
* TVM, perhaps others) do not adhere to this 256 byte alignment requirement
* TVM, perhaps others) do not adhere to this 256 byte aligment requirement
Copy link
Member

Choose a reason for hiding this comment

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

Typo, alignment is correct

Copy link
Member Author

Choose a reason for hiding this comment

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

I changed it, but since it is vendored, I don't think it matters.

@seberg
Copy link
Member Author

seberg commented May 23, 2024

ut then I am confused since the DLManagedTensorVersioned struct already existed.

I supsect someone copied over a version of the header that already included it just to add bool support: Nothing was actually done about it (or could it have been at the time).

@mattip mattip removed the 56 - Needs Release Note. Needs an entry in doc/release/upcoming_changes label May 29, 2024
Copy link
Member

@mattip mattip left a comment

Choose a reason for hiding this comment

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

Seems to work. It is a bit difficult to review because of the refactoring, but I think it all makes sense. I do wonder a bit about the GIL being needed in the various deleter functions since the they can be called by non-python code.

// Taken from:
// https://github.com/dmlc/dlpack/blob/ca4d00ad3e2e0f410eeab3264d21b8a39397f362/include/dlpack/dlpack.h
// https://github.com/dmlc/dlpack/blob/bbd2f4d32427e548797929af08cfe2a9cbb3cf12/include/dlpack/dlpack.h
// but added typedef to DLManagedTensorVersioned
Copy link
Member

Choose a reason for hiding this comment

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

Should we upstream that change?

Copy link
Member Author

Choose a reason for hiding this comment

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

Probably, I mentioned it in an issue there.

(DLManagedTensorVersioned *)PyCapsule_GetPointer(
self, NPY_DLPACK_VERSIONED_CAPSULE_NAME);
if (managed == NULL) {
PyErr_WriteUnraisable(self);
Copy link
Member

Choose a reason for hiding this comment

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

Doesn't this need the GIL?

Copy link
Member Author

Choose a reason for hiding this comment

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

No, a capsule is a Python object, so it can't be deleted without the GIL. It is just the DLManagedTensor deleter that needs to grab the GIL.

"Give a warning on reload and big warning in sub-interpreters."},
{"from_dlpack", (PyCFunction)from_dlpack,
METH_O, NULL},
METH_FASTCALL | METH_KEYWORDS, NULL},
Copy link
Member

Choose a reason for hiding this comment

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

Using fastcall - nice.


with pytest.raises(RuntimeError):
x.__dlpack__(stream=1)

Copy link
Member

Choose a reason for hiding this comment

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

Did you mean to test copy here?

Copy link
Member Author

Choose a reason for hiding this comment

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

Strange, yeah, seems like I copied it, but then didn't adapt it

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed, copy= parsing is too forgiving, IMO, but I opened an issue on that. It doesn't matter here.

@seberg
Copy link
Member Author

seberg commented May 30, 2024

Forgot to set the IS_COPIED flag; if we copy (which we could refuse probably) then need to set it. No way to test it within NumPy though without adding another unpacker for the capsule, it's easy enough.

@mattip mattip merged commit 29409dc into numpy:main Jun 5, 2024
@mattip
Copy link
Member

mattip commented Jun 5, 2024

Thanks @seberg

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ENH: Update DLpack version

2 participants