Sorry, I meant: I am *now* a solid +1
On Mon, Apr 10, 2023 at 1:26 PM Weston Pace <weston.p...@gmail.com> wrote: > I am not a solid +1 and I can see the usefulness. Matt and I spoke on > this externally and I think Matt has written a great summary. There were a > few more points that came up in the discussion that I think are > particularly compelling. > > * Avoiding device location is generally fatal > > In other cases when we have generic metadata it is typically ok for > libraries to ignore this and just make sure they forward it on properly. > For example, when writing parquet files or IPC files we need to be sure we > persist the generic metadata and load it from the disk. However, if you > ignore the device location, and it is not CPU, and you attempt to access > the buffer (e.g. to persist the data) you will probably crash. > > This is not true for most of the examples I gave (one could argue that > accessing a NUMA buffer from the wrong socket is a bad idea, but at least > it is not fatal). It's possible to contrive other cases that meet this > criteria (e.g. a custom allocator that can temporarily persist buffers to > disk and requires checkout before using the pointers or, arguably, the numa > node example given above) but they can probably be mapped to the device id > pattern and they aren't actively encountered today. > > * We need this internally > > As mentioned in Matt's previous email. We could make use of this field > today to avoid doing things (e.g. validating arrays) in flight / IPC when > we know the data is not on the CPU. > > * Others are actively working around this problem today > > There are libraries today that have encountered this problem and have > proposed similar workarounds. > > * The changes to the stream interface are more than just "metadata" > > I did not look closely enough and realize that these changes are more > substantial than just switching to ArrowDeviceArray. These changes > introduce a concept of queues to the stream which mirrors concepts found in > mainstream GPU libraries (e.g. CUDA's "streams") > > On Mon, Apr 10, 2023 at 12:51 PM Matt Topol <zotthewiz...@gmail.com> > wrote: > >> > There's nothing in the spec today that >> prevents users from creating `ArrowDeviceArray` and >> `ArrowDeviceArrayStream` themselves >> >> True, but third-party applications aren't going to be the only downstream >> users of this API. We also want to build on this within Arrow itself to >> enable easier usage of non-CPU memory in the higher-level interfaces (IPC, >> Flight). Right now there are the buffer and memory manager classes, but >> there are plenty of areas that still inspect the buffers instead of first >> checking the `is_cpu` flag on them first. Plus we would want to be able to >> expose the device_type and device_id information at those higher level >> interfaces too. >> >> Even if we don't standardize on the device type list from dlpack, having a >> standardized way for libraries to pass this device information alongside >> the Arrow Arrays themselves is still beneficial and I think it's better >> for >> us to define it rather than wait for others to do so. The next step after >> agreeing on this format change is going to be building helpers (similar to >> the existing C Data helpers) around this to ensure safe usage and >> conversion to C++ Arrow Array's and buffers, etc. >> >> > Would we rather come up with a mechanism for arbitrary key/value >> metadata >> (e.g. UTF-8 encoded JSON string) to accompany arrays? Something similar >> to >> record batch metadata in the IPC format? >> >> A generic key/value metadata layer at the Array level for the C-Data API >> could work in most cases *except* for the change to `get_next` for passing >> the stream/queue pointer object that the producer needs to make the data >> safe to access on. If a need for generic metadata at the array level IS >> needed in the future, the reserved 128 bytes could be easily evolved into >> a >> const char* + a release callback or whatever else we need in order to >> provide other generic metadata in the struct for the Array. >> >> My concerns with using a generic metadata layer to pass this information >> are: >> 1. There would be no strong type enforcement on the device_id/device_type >> members, which would require additional error checking on consumers for >> invalid values. >> 2. We'd need to add a release callback or something to the >> ArrowDeviceArray >> struct itself in order to clarify who owns the `const char*` for the >> metadata. >> >> > 1. Agreeing that dlpack has a good list of device ids >> * how is this list managed? how hard is it for a device to get added to >> the list? >> * how will updates to dlpack be mirrored into arrow? >> * instead of just repeating/vendoring the enum can we simply refer to it >> and treat this as an opaque integer?) >> >> I'm not opposed to just referring to the dlpack enum and treating this as >> an opaque integer if that would be preferable. I definitely agree with the >> difficulties in vendoring/repeating the dlpack enum values here and >> ensuring it stays up to date. Does anyone else have strong feelings one >> way >> or the other on this? >> >> --Matt >> >> On Mon, Apr 10, 2023 at 1:34 PM Weston Pace <weston.p...@gmail.com> >> wrote: >> >> > I suppose I'm a weak +1 in "I don't entirely believe this will be useful >> > but it doesn't seem harmful". There's nothing in the spec today that >> > prevents users from creating `ArrowDeviceArray` and >> > `ArrowDeviceArrayStream` themselves and I'm not familiar enough with the >> > systems producing / consuming these arrays to know if it makes sense for >> > Arrow to standardize on a list. E.g. picking dlpack's list of device >> ids. >> > >> > Arrays and streams could also be labeled with (just brainstorming): >> > * numa node number >> > * worker id (e.g. in distributed execution) >> > * thread id (e.g. in some kind of work-stealing producer/consumer >> > algorithm) >> > * source device MAC (e.g. in some kind of IoT environment) >> > * etc. >> > >> > Would we rather come up with a mechanism for arbitrary key/value >> metadata >> > (e.g. UTF-8 encoded JSON string) to accompany arrays? Something >> similar to >> > record batch metadata in the IPC format? >> > >> > Otherwise, it seems what is proposed is: >> > >> > 1. Agreeing that dlpack has a good list of device ids >> > * how is this list managed? how hard is it for a device to get added >> to >> > the list? >> > * how will updates to dlpack be mirrored into arrow? >> > * instead of just repeating/vendoring the enum can we simply refer to >> it >> > and treat this as an opaque integer?) >> > 2. Providing an example of how you can tag arrays with metadata >> > >> > >> > >> > On Mon, Apr 10, 2023 at 9:30 AM Matt Topol <zotthewiz...@gmail.com> >> wrote: >> > >> > > > The ArrowArray struct is not allowed to change, as it would break >> the >> > > ABI: >> > > >> > > >> > >> https://arrow.apache.org/docs/format/CDataInterface.html#updating-this-specification >> > > >> > > I was referring more to the future case where we might need to >> introduce >> > an >> > > `ArrowArrayV2` or something similar precisely because the ArrowArray >> > struct >> > > is not allowed to change to avoid breaking the ABI. The problem being >> > that >> > > it becomes difficult to communicate *per-buffer* device info if we are >> > > locked into only the existing ArrowArray struct which doesn't provide >> any >> > > way to communicate that information. That said, you did bring up a >> good >> > > point in the PR of the question of ownership of that memory. So it >> might >> > > make more sense to just embed it and if we have to evolve the ABI we >> can >> > > use the reserved bytes. >> > > >> > > > How exactly would this be communicated? Is the information actually >> > > useful? I got the impression that the CUDA programming model allows >> you >> > > to access exactly the right amount of data, regardless of HW >> parallelism. >> > > >> > > From my research and discussions, it looks like there's still the >> case of >> > > handling vectorization in GPU programming. If you know the padding of >> the >> > > buffer you know whether or not it's safe to use bytes after the >> length of >> > > the data for the purposes of having equal length buffers that you can >> > > perform vectorized operations on (similar to what you might do for CPU >> > > programming). For now I've left this out and punted on it as it would >> be >> > > per-buffer information that we aren't communicating. But I wanted to >> > > mention the concern in case anyone on the mailing list that is more >> > > knowledgeable than I (or has particular use cases in mind) has an >> opinion >> > > on this and thinks we should add this info to be communicated somehow >> > > (maybe another struct that we embed, or otherwise manage in the >> > > ArrowDeviceArray struct). >> > > >> > > > The C++ Device class already exists for this. You can get a Buffer's >> > > device pretty easily (by going through the MemoryManager, IIRC). >> > > >> > > I completely missed the Device class, good point! So when I get to >> > > implementing helpers for the C++ lib for these format changes, I'd >> likely >> > > create an implementation of that Device class / MemoryManager class >> for >> > > handling devices described by the ArrowDeviceArray's information of >> the >> > > DeviceType + Device ID. Alongside a child class from Buffer for >> managing >> > > the buffers and making sure they return false for `is_cpu`. >> > > >> > > -Matt >> > > >> > > On Sat, Apr 8, 2023 at 4:41 AM Antoine Pitrou <anto...@python.org> >> > wrote: >> > > >> > > > >> > > > Hi Matt, >> > > > >> > > > I've posted comments on the PR. Besides: >> > > > >> > > > > * The ArrowDeviceArray contains a pointer to an ArrowArray >> > > alongside >> > > > > the device information related to allocation. The reason for >> using a >> > > > > pointer is so that future modifications of the ArrowArray struct >> do >> > not >> > > > > cause the size of this struct to change (as it would still just >> be a >> > > > > pointer to the ArrowArray struct). >> > > > >> > > > The ArrowArray struct is not allowed to change, as it would break >> the >> > > ABI: >> > > > >> > > > >> > > >> > >> https://arrow.apache.org/docs/format/CDataInterface.html#updating-this-specification >> > > > >> > > > > Remaining Concerns that I can think of: >> > > > > * Alignment and padding of allocations can have a larger >> impact >> > > when >> > > > > dealing with non-cpu devices than with CPUs, and this design >> provides >> > > no >> > > > > way to communicate potential extra padding on a per-buffer basis. >> We >> > > > could >> > > > > attempt to codify a convention that allocations should have a >> > specific >> > > > > alignment and a particular padding, but that doesn't actually >> enforce >> > > > > anything nor allow communicating if for some reason those >> conventions >> > > > > weren't followed. Should we add some way of passing this info or >> punt >> > > > this >> > > > > for a future modification? >> > > > >> > > > How exactly would this be communicated? Is the information actually >> > > > useful? I got the impression that the CUDA programming model allows >> you >> > > > to access exactly the right amount of data, regardless of HW >> > parallelism. >> > > > >> > > > > This is part of a wider effort I'm attempting to address to >> > > > > improve the non-cpu memory support in the Arrow libraries, such as >> > > > enhanced >> > > > > Buffer types in the C++ library that will have the device_id and >> > > > > device_type information in addition to the `is_cpu` flag that >> > currently >> > > > > exists. >> > > > >> > > > The C++ Device class already exists for this. You can get a Buffer's >> > > > device pretty easily (by going through the MemoryManager, IIRC). >> > > > >> > > > Regards >> > > > >> > > > Antoine. >> > > > >> > > >> > >> >