Skip to content

cuda.core: a pickled Device names its device by ordinal #3196

Closed

Description

@Andy-Jost

Device.__reduce__ pickles the device ordinal (return Device, (self.device_id,)). Ordinals are per process, so a Device sent to a process with a different CUDA_VISIBLE_DEVICES unpickles to a different GPU, with no error.

#3126 sends memory resources by UUID (#3097). A Device sent next to them still travels by ordinal. The IPC tests do this: they pass device to the child, and the child calls device.set_current(). With reordered visibility, the buffer arrives on the right GPU and the child makes the wrong GPU current.

Fix: pickle a Device by UUID. Unpickling returns the device with that UUID in the receiving process, whatever its ordinal is there, and raises RuntimeError when that device is not visible. Processes share a Device to work with shared memory, so the physical device is the only useful meaning. A different device would fail later, when the buffer is mapped.

Raised by @juenglin in #3126 (comment).

Activity

  1. added this to the cuda.core 1.3.0 milestone on Oct 22, 2026
  2. self-assigned this
    on Oct 22, 2026
  3. added
    bugSomething isn't working
    P1Medium priority - Should do
    cuda.coreEverything related to the cuda.core module
    on Oct 22, 2026
  4. jpascucci-nv commented on Oct 23, 2026

    @jpascucci-nv
    Contributor

    Today, if you pickle and move to a different system, doesn't that succeed? But with this, it would fail. (Maybe this use-case isn't supported for some other reason)

  5. Andy-Jost commented on Oct 23, 2026

    @Andy-Jost
    ContributorAuthor

    @jpascucci-nv Today it does not raise, but it does not do the right thing either. The pickle holds an ordinal. On the other machine, Device(n) returns whichever GPU holds ordinal n there. If that machine has fewer than n + 1 GPUs, unpickling already raises ValueError. The current form never promised a device across machines. It carried a number.

    A Device crosses a process boundary for one purpose in cuda.core: to work with IPC memory on one physical GPU. That works within one machine. The memory objects cannot travel further. The file descriptors that back DeviceMemoryResource and VirtualMemoryResource buffers move only through multiprocessing. Plain pickle of a VirtualMemoryResource buffer raises, and plain pickle of a pool-backed buffer loads only in a process that already received the pool through multiprocessing. Fabric handles, the one mechanism that crosses nodes, are not supported yet.

    With #3198, a Device unpickled on a machine that lacks that GPU raises RuntimeError. The message names the missing UUID and the visible devices. That is the correct hard error. The ordinal form picks a different GPU in silence, and that is the bug behind #3196 and #3097.

    Cross-machine Device pickling is not a supported use. A program that means "GPU n on the other machine" should send the integer and call Device(n) there. A program that means "this physical GPU" can send device.uuid, which is what the new pickle does.

    I will add a sentence to the docstring and the release note: the pickled form is for processes on the same machine.

  6. added a commit that references this issue on Oct 24, 2026
    0bdf9e9
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

P1Medium priority - Should dobugSomething isn't workingcuda.coreEverything related to the cuda.core module

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions