CUDA: Support CUDA Virtual Devices#25228
Conversation
|
Could you please rebase your changes on the TOT master? |
Can't this already be achieved by using RPC without any additional code changes? Connecting to a |
dc6c012 to
f57debf
Compare
|
|
||
| static void ggml_backend_cuda_comm_init_nccl(ggml_backend_cuda_comm_context * ret) { | ||
| #ifdef GGML_USE_NCCL | ||
| const size_t n = ret->dev_ids.size(); |
There was a problem hiding this comment.
IIUC, these dev_ids are virtual devices, ncclCommInitAll will fail if you pass [0,1] on a single device.
I think it might be better to disable the NCCL path for the virtual device case.
| } | ||
|
|
||
| static void ggml_backend_cuda_comm_init_internal(ggml_backend_cuda_comm_context * ret) { | ||
| ret->ar_pipeline = ggml_cuda_ar_pipeline_init(ret->dev_ids.data(), ret->dev_ids.size()); |
There was a problem hiding this comment.
Does the internal allReduce implementation work fine with virtual devices?
Overview
Adds support for exposing a configurable number of virtual CUDA devices on top of the physical GPUs actually present, controlled by a new
GGML_CUDA_DEVICESenvironment variable. This allows developing and exercising multi-GPU code paths on machines with a single GPU.When
GGML_CUDA_DEVICESis unset, behavior is identical to before.-sm layer,-sm row, and-sm tensorare all supported under virtual CUDA devices. For-sm tensor, the internal CUDA AllReduce or the meta-backend fallbacks are supported since NCCL seems to require distinct physical GPUs.Additional information
The core idea is a single indirection: every (virtual) device id is mapped to a backing physical device id, and all raw CUDA calls that take a device ordinal use the physical id, while ggml-level bookkeeping (pools, buffers, device registry) stays per-virtual-device.
Design choices
ggml_cuda_init()parsesGGML_CUDA_DEVICES, builds the round-robin virtual to physical map, and computes how many virtual devices share each GPU.ggml_cuda_set_device()resolves to the physical device, and a newggml_cuda_get_physical_device()exposes the mapping.ggml_cuda_device_infogainsphysical_device_countand, per device,physical_deviceandphysical_share_count.-v<i>suffix to each virtual device'spci_bus_idso they stay unique.op_mul_mat_device(context member, set byggml_cuda_op_mul_matdispatcher) is used to identify the main device in mul mat execution instead ofggml_cuda_get_device(), which returns the physical device and was otherwise causing out-of-bounds writes.total/physical_share_countfor both free and total memory, so per-device VRAM sums to the physical total and model distribution doesn't overcommit a shared GPU.Testing
Validated on three Blackwell systems, using four models (Llama-3.2-1B-Instruct, Llama-3.1-8B-Instruct, Qwen2.5-32B-Instruct, Llama-3.3-70B-Instruct) with greedy decoding (temp 0) and a fixed seed, so as to compare virtual-device output against physical-GPU reference.
test-backend-opsunder2 vdev (virtual device) / 1 phys (physical device)configuration. TestedMUL_MAT/MUL_MAT_IDon baseline,2 vdev / 1 physand4 vdev / 2 physconfigurations.2 vdev / 2 phys,2 vdev / 1 phys,3 vdev / 2 phys,4 vdev / 2 phys,4 vdev / 1 physfor-sm layer,-sm row, and-sm tensor(non-NCCL paths):-sm layer/-sm row: output identical to the real-GPU baseline (flash-attn on/off on 1B/8B; on for 32B/70B)-sm tensor: valid coherent output, deterministic across configurations (n vdev/1 physwheren = 2, 3, 4), and independent of the virtual to physical mapping (n vdev/1 physproduces the same asn vdev/2 phys,n = 2, 4). Both all-reduce fallbacks exercised (GGML_CUDA_ALLREDUCE=internal/none).Requirements