1212#include " kernels/api.cuh"
1313#include " kernels/configs.cuh"
1414
15+ namespace shared_memory {
16+ void cu_mem_set_access_all (void * ptr, size_t size) {
17+ int device_count;
18+ CUDA_CHECK (cudaGetDeviceCount (&device_count));
19+
20+ CUmemAccessDesc access_desc[device_count];
21+ for (int idx = 0 ; idx < device_count; ++idx) {
22+ access_desc[idx].location .type = CU_MEM_LOCATION_TYPE_DEVICE ;
23+ access_desc[idx].location .id = idx;
24+ access_desc[idx].flags = CU_MEM_ACCESS_FLAGS_PROT_READWRITE ;
25+ }
26+
27+ CU_CHECK (cuMemSetAccess ((CUdeviceptr)ptr, size, access_desc, device_count));
28+ }
29+
30+ void cu_mem_free (void * ptr) {
31+ CUmemGenericAllocationHandle handle;
32+ CU_CHECK (cuMemRetainAllocationHandle (&handle, ptr));
33+
34+ size_t size = 0 ;
35+ CU_CHECK (cuMemGetAddressRange (NULL , &size, (CUdeviceptr)ptr));
36+
37+ CU_CHECK (cuMemUnmap ((CUdeviceptr)ptr, size));
38+ CU_CHECK (cuMemAddressFree ((CUdeviceptr)ptr, size));
39+ CU_CHECK (cuMemRelease (handle));
40+ }
41+
42+ size_t get_size_align_to_granularity (size_t size_raw, size_t granularity) {
43+ size_t size = (size_raw + granularity - 1 ) & ~(granularity - 1 );
44+ if (size == 0 )
45+ size = granularity;
46+ return size;
47+ }
48+
49+ SharedMemoryAllocator::SharedMemoryAllocator (bool use_fabric) : use_fabric(use_fabric) {}
50+
51+ void SharedMemoryAllocator::malloc (void ** ptr, size_t size_raw) {
52+ if (use_fabric) {
53+ CUdevice device;
54+ CU_CHECK (cuCtxGetDevice (&device));
55+
56+ CUmemAllocationProp prop = {};
57+ prop.type = CU_MEM_ALLOCATION_TYPE_PINNED ;
58+ prop.location .type = CU_MEM_LOCATION_TYPE_DEVICE ;
59+ prop.requestedHandleTypes = CU_MEM_HANDLE_TYPE_FABRIC ;
60+ prop.location .id = device;
61+
62+ size_t granularity = 0 ;
63+ CU_CHECK (cuMemGetAllocationGranularity (&granularity, &prop, CU_MEM_ALLOC_GRANULARITY_MINIMUM ));
64+
65+ size_t size = get_size_align_to_granularity (size_raw, granularity);
66+
67+ CUmemGenericAllocationHandle handle;
68+ CU_CHECK (cuMemCreate (&handle, size, &prop, 0 ));
69+
70+ CU_CHECK (cuMemAddressReserve ((CUdeviceptr*)ptr, size, granularity, 0 , 0 ));
71+ CU_CHECK (cuMemMap ((CUdeviceptr)*ptr, size, 0 , handle, 0 ));
72+ cu_mem_set_access_all (*ptr, size);
73+ } else {
74+ CUDA_CHECK (cudaMalloc (ptr, size_raw));
75+ }
76+ }
77+
78+ void SharedMemoryAllocator::free (void * ptr) {
79+ if (use_fabric) {
80+ cu_mem_free (ptr);
81+ } else {
82+ CUDA_CHECK (cudaFree (ptr));
83+ }
84+ }
85+
86+ void SharedMemoryAllocator::get_mem_handle (MemHandle* mem_handle, void * ptr) {
87+ size_t size = 0 ;
88+ CU_CHECK (cuMemGetAddressRange (NULL , &size, (CUdeviceptr)ptr));
89+
90+ mem_handle->size = size;
91+
92+ if (use_fabric) {
93+ CUmemGenericAllocationHandle handle;
94+ CU_CHECK (cuMemRetainAllocationHandle (&handle, ptr));
95+
96+ CU_CHECK (cuMemExportToShareableHandle (&mem_handle->inner .cu_mem_fabric_handle , handle, CU_MEM_HANDLE_TYPE_FABRIC , 0 ));
97+ } else {
98+ CUDA_CHECK (cudaIpcGetMemHandle (&mem_handle->inner .cuda_ipc_mem_handle , ptr));
99+ }
100+ }
101+
102+ void SharedMemoryAllocator::open_mem_handle (void ** ptr, MemHandle* mem_handle) {
103+ if (use_fabric) {
104+ size_t size = mem_handle->size ;
105+
106+ CUmemGenericAllocationHandle handle;
107+ CU_CHECK (cuMemImportFromShareableHandle (&handle, &mem_handle->inner .cu_mem_fabric_handle , CU_MEM_HANDLE_TYPE_FABRIC ));
108+
109+ CU_CHECK (cuMemAddressReserve ((CUdeviceptr*)ptr, size, 0 , 0 , 0 ));
110+ CU_CHECK (cuMemMap ((CUdeviceptr)*ptr, size, 0 , handle, 0 ));
111+ cu_mem_set_access_all (*ptr, size);
112+ } else {
113+ CUDA_CHECK (cudaIpcOpenMemHandle (ptr, mem_handle->inner .cuda_ipc_mem_handle , cudaIpcMemLazyEnablePeerAccess));
114+ }
115+ }
116+
117+ void SharedMemoryAllocator::close_mem_handle (void * ptr) {
118+ if (use_fabric) {
119+ cu_mem_free (ptr);
120+ } else {
121+ CUDA_CHECK (cudaIpcCloseMemHandle (ptr));
122+ }
123+ }
124+ } // namespace shared_memory
125+
15126namespace deep_ep {
16127
17128Buffer::Buffer (int rank,
@@ -20,15 +131,17 @@ Buffer::Buffer(int rank,
20131 int64_t num_rdma_bytes,
21132 bool low_latency_mode,
22133 bool explicitly_destroy,
23- bool enable_shrink)
134+ bool enable_shrink,
135+ bool use_fabric)
24136 : rank(rank),
25137 num_ranks (num_ranks),
26138 num_nvl_bytes(num_nvl_bytes),
27139 num_rdma_bytes(num_rdma_bytes),
28140 enable_shrink(enable_shrink),
29141 low_latency_mode(low_latency_mode),
30142 explicitly_destroy(explicitly_destroy),
31- comm_stream(at::cuda::getStreamFromPool(true )) {
143+ comm_stream(at::cuda::getStreamFromPool(true )),
144+ shared_memory_allocator(use_fabric) {
32145 // Metadata memory
33146 int64_t barrier_signal_bytes = NUM_MAX_NVL_PEERS * sizeof (int );
34147 int64_t buffer_ptr_bytes = NUM_MAX_NVL_PEERS * sizeof (void *);
@@ -66,8 +179,9 @@ Buffer::Buffer(int rank,
66179
67180 if (num_nvl_bytes > 0 ) {
68181 // Local IPC: alloc local memory and set local IPC handles
69- CUDA_CHECK (cudaMalloc (&buffer_ptrs[nvl_rank], num_nvl_bytes + barrier_signal_bytes + buffer_ptr_bytes + barrier_signal_ptr_bytes));
70- CUDA_CHECK (cudaIpcGetMemHandle (&ipc_handles[nvl_rank], buffer_ptrs[nvl_rank]));
182+ shared_memory_allocator.malloc (&buffer_ptrs[nvl_rank],
183+ num_nvl_bytes + barrier_signal_bytes + buffer_ptr_bytes + barrier_signal_ptr_bytes);
184+ shared_memory_allocator.get_mem_handle (&ipc_handles[nvl_rank], buffer_ptrs[nvl_rank]);
71185 buffer_ptrs_gpu = reinterpret_cast <void **>(static_cast <uint8_t *>(buffer_ptrs[nvl_rank]) + num_nvl_bytes + barrier_signal_bytes);
72186
73187 // Set barrier signals
@@ -136,7 +250,8 @@ int Buffer::get_local_device_id() const {
136250}
137251
138252pybind11::bytearray Buffer::get_local_ipc_handle () const {
139- return {ipc_handles[nvl_rank].reserved , CUDA_IPC_HANDLE_SIZE };
253+ const shared_memory::MemHandle& handle = ipc_handles[nvl_rank];
254+ return {reinterpret_cast <const char *>(&handle), sizeof (handle)};
140255}
141256
142257pybind11::bytearray Buffer::get_local_nvshmem_unique_id () const {
@@ -176,11 +291,11 @@ void Buffer::destroy() {
176291 if (is_available ()) {
177292 for (int i = 0 ; i < num_nvl_ranks; ++i)
178293 if (i != nvl_rank)
179- CUDA_CHECK ( cudaIpcCloseMemHandle ( buffer_ptrs[i]) );
294+ shared_memory_allocator. close_mem_handle ( buffer_ptrs[i]);
180295 }
181296
182297 // Free local buffer and error flag
183- CUDA_CHECK ( cudaFree ( buffer_ptrs[nvl_rank]) );
298+ shared_memory_allocator. free ( buffer_ptrs[nvl_rank]);
184299 }
185300
186301 // Free NVSHMEM
@@ -220,13 +335,13 @@ void Buffer::sync(const std::vector<int>& device_ids,
220335 for (int i = 0 , offset = rdma_rank * num_nvl_ranks; i < num_nvl_ranks; ++i) {
221336 EP_HOST_ASSERT (all_gathered_handles[offset + i].has_value ());
222337 auto handle_str = std::string (all_gathered_handles[offset + i].value ());
223- EP_HOST_ASSERT (handle_str.size () == CUDA_IPC_HANDLE_SIZE );
338+ EP_HOST_ASSERT (handle_str.size () == shared_memory:: HANDLE_SIZE );
224339 if (offset + i != rank) {
225- std::memcpy (ipc_handles[i]. reserved , handle_str.c_str (), CUDA_IPC_HANDLE_SIZE );
226- CUDA_CHECK ( cudaIpcOpenMemHandle ( &buffer_ptrs[i], ipc_handles[i], cudaIpcMemLazyEnablePeerAccess) );
340+ std::memcpy (& ipc_handles[i], handle_str.c_str (), shared_memory:: HANDLE_SIZE );
341+ shared_memory_allocator. open_mem_handle ( &buffer_ptrs[i], & ipc_handles[i]);
227342 barrier_signal_ptrs[i] = reinterpret_cast <int *>(static_cast <uint8_t *>(buffer_ptrs[i]) + num_nvl_bytes);
228343 } else {
229- EP_HOST_ASSERT (std::memcmp (ipc_handles[i]. reserved , handle_str.c_str (), CUDA_IPC_HANDLE_SIZE ) == 0 );
344+ EP_HOST_ASSERT (std::memcmp (& ipc_handles[i], handle_str.c_str (), shared_memory:: HANDLE_SIZE ) == 0 );
230345 }
231346 }
232347
@@ -1739,7 +1854,7 @@ PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) {
17391854 .def (" current_stream_wait" , &deep_ep::EventHandle::current_stream_wait);
17401855
17411856 pybind11::class_<deep_ep::Buffer>(m, " Buffer" )
1742- .def (pybind11::init<int , int , int64_t , int64_t , bool , bool , bool >())
1857+ .def (pybind11::init<int , int , int64_t , int64_t , bool , bool , bool , bool >())
17431858 .def (" is_available" , &deep_ep::Buffer::is_available)
17441859 .def (" get_num_rdma_ranks" , &deep_ep::Buffer::get_num_rdma_ranks)
17451860 .def (" get_rdma_rank" , &deep_ep::Buffer::get_rdma_rank)
0 commit comments