@@ -885,20 +885,25 @@ cdef class VirtualMemoryResource(MemoryResource):
885885 def is_ipc_enabled(self) -> bool:
886886 """ Whether buffers of this resource can be shared with other processes.
887887
888- True when ``config.handle_type`` is ``" posix_fd" `` on Linux;
889- ``handle_type`` is the only switch, there is no separate option. With
890- ``handle_type= None `` the allocations cannot be exported, Win32 KMT
891- handles are not transported by cuda.core, and fabric handles are not
892- supported yet.
888+ True when ``config.handle_type`` is ``" posix_fd" `` on Linux and the
889+ memory lives on a device; ``handle_type`` is the only switch, there is
890+ no separate option. With ``handle_type= None `` the allocations cannot
891+ be exported, Win32 KMT handles are not transported by cuda.core, and
892+ fabric handles are not supported yet. Host- located virtual memory
893+ (``location_type`` ``" host" ``, ``" host_numa" ``, or
894+ ``" host_numa_current" ``) is not shared yet.
893895 """
894- return self.config.handle_type in _IPC_HANDLE_TYPES
896+ return (
897+ self.config.handle_type in _IPC_HANDLE_TYPES
898+ and self.config.location_type not in _HOST_LOCATION_TYPES
899+ )
895900
896901 def _import_ipc_buffer(self, VirtualMemoryIPCBufferDescriptor desc not None, stream) -> VirtualMemoryBuffer:
897902 """ Import a buffer that another process exported; see :meth:`Buffer.from_ipc_descriptor`.
898903
899904 Every exported allocation is imported with this resource' s handle
900- type and checked to live where this resource allocates (its device,
901- or its host location). The allocations are then mapped in order into
905+ type and checked to live on this resource' s device. The allocations
906+ are then mapped in order into
902907 one new address reservation with the access descriptors this
903908 resource' s options produce for its device and peers, and the
904909 deallocation stream is recorded as :meth:`allocate` does. The
@@ -919,7 +924,7 @@ cdef class VirtualMemoryResource(MemoryResource):
919924 cdef VmmRangeHandle rng
920925 cdef DevicePtrHandle h_ptr
921926 cdef Buffer buf
922- cdef size_t gran, addr_align, chunk, total = 0, offset = 0
927+ cdef size_t gran, gran_min = 0, addr_align, chunk, total = 0, offset = 0
923928 cdef Py_ssize_t n, i
924929 cdef cydriver.CUdeviceptr hint
925930 cdef int handle_type, fd
@@ -955,11 +960,17 @@ cdef class VirtualMemoryResource(MemoryResource):
955960 self._fill_prop(cfg, &prop)
956961 self._fill_access(cfg, &prop, descs)
957962 gran = self._granularity(cfg, &prop)
963+ # cuMemMap requires the minimum granularity, whatever this resource's
964+ # granularity option says; the exporter may have used either.
965+ with nogil:
966+ HANDLE_RETURN(cydriver.cuMemGetAllocationGranularity(
967+ &gran_min, &prop, cydriver.CU_MEM_ALLOC_GRANULARITY_MINIMUM))
958968 for chunk_obj in desc._chunk_sizes:
959969 chunk = chunk_obj
960- if chunk == 0 or chunk % g ran != 0:
970+ if chunk == 0 or chunk % g ran_min != 0:
961971 raise ValueError(
962- f"descriptor chunk size {chunk} is not a positive multiple of the {gran}-byte granularity"
972+ f"descriptor chunk size {chunk} is not a positive multiple of the {gran_min}-byte minimum "
973+ "granularity"
963974 )
964975 if chunk > <size_t>-1 - total:
965976 raise OverflowError("the descriptor's chunk sizes do not fit in size_t")
@@ -988,9 +999,10 @@ cdef class VirtualMemoryResource(MemoryResource):
988999 os_handle, <cydriver.CUmemAllocationHandleType>handle_type, chunk, descs.data(), descs.size())
9891000 if not h_alloc:
9901001 _raise_last_error_noting(
991- f"while importing chunk {i + 1} of {n} of a VirtualMemoryResource buffer descriptor; the "
992- "shared handle may not refer to a CUDA allocation exported with "
993- f"handle_type={str(cfg.handle_type)!r}"
1002+ f"while importing chunk {i + 1} of {n} of a VirtualMemoryResource buffer descriptor; either "
1003+ "the shared handle does not refer to a CUDA allocation exported with "
1004+ f"handle_type={str(cfg.handle_type)!r}, or the device that owns the memory is not usable in "
1005+ "this process (for example, CUDA_VISIBLE_DEVICES hides it)"
9941006 )
9951007 # The exporter chose where the memory lives. This resource must map
9961008 # memory of that kind on that device, or its access descriptors
@@ -1106,9 +1118,11 @@ cdef VirtualMemoryIPCBufferDescriptor _export_ipc_descriptor(Buffer buf):
11061118 "allocation takes one file descriptor, so a process near its file descriptor limit fails here",
11071119 )
11081120 try:
1109- handles.append( IPCAllocationHandle._init(fd, None) )
1121+ handle = IPCAllocationHandle._init(fd, None)
11101122 except: # noqa: E722 rollback-then-raise: the fd is not owned yet
11111123 os.close(fd)
11121124 raise
1125+ # The handle owns the fd now; if append fails, the handle closes it once.
1126+ handles.append(handle)
11131127 sizes.append(chunk)
11141128 return VirtualMemoryIPCBufferDescriptor._from_exports(handle_type, tuple(sizes), tuple(handles), buf._size)
0 commit comments