Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose new CUDA APIs for sharing the same memory between processes #1235

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
Prev Previous commit
Next Next commit
Added convenience methods for IPC memory handles and checking for IPC…
… support
  • Loading branch information
Deneas committed Jun 12, 2024
commit 0b6921883352d14920f59731c3e0098374def2d1
61 changes: 59 additions & 2 deletions Src/ILGPU/Runtime/Cuda/CudaAccelerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -488,16 +488,73 @@ protected override MemoryBuffer AllocateRawInternal(
/// <param name="ipcMemHandle">A IPC memory handle from another process.</param>
/// <param name="length">The number of elements to allocate.</param>
/// <param name="elementSize">The size of a single element in bytes.</param>
/// <param name="flags">The flags to use</param>
/// <returns>A mapped buffer of shared memory on this accelerator.</returns>
public CudaIpcMemoryBuffer MapRaw(CudaIpcMemHandle ipcMemHandle, long length, int elementSize)
/// <remarks>
/// In case of multi GPU setups like SLI it may require <see cref="CudaIpcMemFlags.LazyEnablePeerAccess"/>
/// even when using the same device.
/// </remarks>
public MemoryBuffer MapFromIpcMemHandle(CudaIpcMemHandle ipcMemHandle, long length, int elementSize, CudaIpcMemFlags flags)
{
if (length < 0)
throw new ArgumentOutOfRangeException(nameof(length));
if (elementSize < 1)
throw new ArgumentOutOfRangeException(nameof(elementSize));

Bind();
return new CudaIpcMemoryBuffer(this, ipcMemHandle, length, elementSize, CudaIpcMemFlags.None);
return new CudaIpcMemoryBuffer(this, ipcMemHandle, length, elementSize, flags);
}

/// <summary>
/// Exports memory for use in another process
/// </summary>
/// <param name="memoryBuffer">The <see cref="CudaMemoryBuffer"/> to export.</param>
/// <returns>The IPC memory handle for other processes.</returns>
/// <remarks>This will zero the memory in the buffer and
/// in case of small allocations under 1 MB even neighboring memory will be zeroed.<br />
/// A buffer can only have one IPC memory handle, but multiple processes can use the same handle.
/// </remarks>
/// <exception cref="NotSupportedException">Only <see cref="CudaMemoryBuffer"/> supports CUDA IPC.</exception>
public CudaIpcMemHandle GetIpcMemoryHandle(MemoryBuffer memoryBuffer)
{
if (memoryBuffer is not CudaMemoryBuffer)
{
throw new NotSupportedException(
string.Format(ErrorMessages.NotSupportedType,
memoryBuffer.GetType()));
}
Bind();
CudaException.ThrowIfFailed(
CurrentAPI.GetIpcMemoryHandle(out var ipcMemHandle, memoryBuffer.NativePtr)
);
return ipcMemHandle;
}

/// <summary>
/// Exports memory for use in another process
/// </summary>
/// <param name="memoryBuffer">The memory buffer with an underlying <see cref="CudaMemoryBuffer"/> to export.</param>
/// <returns>The IPC memory handle for other processes.</returns>
/// <remarks>This will zero the memory in the buffer and
/// in case of small allocations under 1 MB even neighboring memory will be zeroed.<br />
/// A buffer can only have one IPC memory handle, but multiple processes can use the same handle.
/// </remarks>
/// <exception cref="NotSupportedException">Only <see cref="CudaMemoryBuffer"/> supports CUDA IPC.</exception>
public CudaIpcMemHandle GetIpcMemoryHandle<TView>(MemoryBuffer<TView> memoryBuffer)
where TView : struct, IArrayView
{
MemoryBuffer underlyingBuffer = memoryBuffer.View.Buffer;
if (underlyingBuffer is not CudaMemoryBuffer cudaMemoryBuffer)
{
throw new NotSupportedException(
string.Format(ErrorMessages.NotSupportedType,
underlyingBuffer.GetType()));
}
Bind();
CudaException.ThrowIfFailed(
CurrentAPI.GetIpcMemoryHandle(out var ipcMemHandle, cudaMemoryBuffer.NativePtr)
);
return ipcMemHandle;
}

#endregion
Expand Down
10 changes: 10 additions & 0 deletions Src/ILGPU/Runtime/Cuda/CudaDevice.cs
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,11 @@ private void InitMiscInfo()
DeviceAttributeKind.
CU_DEVICE_ATTRIBUTE_CAN_USE_HOST_POINTER_FOR_REGISTERED_MEM,
DeviceId) != 0;

// Resolve whether this device has IPC support
HasIpcSupport = CurrentAPI.GetDeviceAttribute(
DeviceAttributeKind.CU_DEVICE_ATTRIBUTE_IPC_EVENT_SUPPORT,
DeviceId) != 0;
}

/// <summary>
Expand Down Expand Up @@ -461,6 +466,11 @@ private void InitPCIInfo()
/// </summary>
public bool SupportsUsingHostPointerForRegisteredMemory { get; private set; }

/// <summary>
/// Returns true if this device supports inter process communication for memory and events.
/// </summary>
public bool HasIpcSupport { get; private set; }

/// <summary>
/// Returns the current device driver mode.
/// </summary>
Expand Down