[comm] Enable multi-node custom-AR v2 on a single NVLink clique (#32339)
Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Lianmin Zheng <lianminzheng@gmail.com>
This commit is contained in:
co-authored by
Claude
Lianmin Zheng
parent
2c63a2f12b
commit
55c4853487
@@ -204,18 +204,19 @@ SGL_DEVICE void st_multimem_16B(const V& x, void* mc_addr, int64_t vec_offset) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <uint32_t kWorldSize>
|
||||||
struct AllReduceParams {
|
struct AllReduceParams {
|
||||||
const void* __restrict__ input;
|
const void* __restrict__ input;
|
||||||
void* __restrict__ output;
|
void* __restrict__ output;
|
||||||
uint32_t num_elements;
|
uint32_t num_elements;
|
||||||
uint32_t rank;
|
uint32_t rank;
|
||||||
void* const* __restrict__ graph_params;
|
void* const* __restrict__ graph_params;
|
||||||
uint8_t* pull_workspaces[kMaxWorldSize]; // must be symmetric memory
|
uint8_t* pull_workspaces[kWorldSize]; // must be symmetric memory
|
||||||
uint8_t* push_workspaces[kMaxWorldSize]; // must be symmetric memory
|
uint8_t* push_workspaces[kWorldSize]; // must be symmetric memory
|
||||||
Semaphore* pull_semaphores[kMaxWorldSize]; // must be symmetric memory
|
Semaphore* pull_semaphores[kWorldSize]; // must be symmetric memory
|
||||||
Counter* push_counter;
|
Counter* push_counter;
|
||||||
uint8_t* pull_mc_workspace; // must be a multicast address
|
uint8_t* pull_mc_workspace; // must be a multicast address
|
||||||
int64_t push_buffer_stride; // per-buffer bytes; each rank holds 2 * kMaxWorldSize buffers
|
int64_t push_buffer_stride; // per-buffer bytes; each rank holds 2 * world_size buffers
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, uint32_t kWorldSize, bool kUsePDL>
|
template <typename T, uint32_t kWorldSize, bool kUsePDL>
|
||||||
@@ -228,12 +229,12 @@ struct AllReducePushImpl {
|
|||||||
using vec_t = device::AlignedVector<T2, kVecSize>;
|
using vec_t = device::AlignedVector<T2, kVecSize>;
|
||||||
static_assert(kWorldSize <= kMaxWorldSize);
|
static_assert(kWorldSize <= kMaxWorldSize);
|
||||||
|
|
||||||
static SGL_DEVICE bool sync_enter_push(const AllReduceParams& params) {
|
static SGL_DEVICE bool sync_enter_push(const AllReduceParams<kWorldSize>& params) {
|
||||||
device::PDLWaitPrimary<kUsePDL>();
|
device::PDLWaitPrimary<kUsePDL>();
|
||||||
return (params.push_counter[blockIdx.x].get() % 2) != 0;
|
return (params.push_counter[blockIdx.x].get() % 2) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SGL_DEVICE void sync_exit_push(const AllReduceParams& params) {
|
static SGL_DEVICE void sync_exit_push(const AllReduceParams<kWorldSize>& params) {
|
||||||
device::PDLTriggerSecondary<kUsePDL>();
|
device::PDLTriggerSecondary<kUsePDL>();
|
||||||
__syncthreads();
|
__syncthreads();
|
||||||
if (threadIdx.x == 0) {
|
if (threadIdx.x == 0) {
|
||||||
@@ -305,7 +306,7 @@ struct AllReducePushImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static SGL_DEVICE void forward_1shot(const AllReduceParams& params) {
|
static SGL_DEVICE void forward_1shot(const AllReduceParams<kWorldSize>& params) {
|
||||||
// push local data to peer ranks, then reduce locally
|
// push local data to peer ranks, then reduce locally
|
||||||
const auto phase = sync_enter_push(params);
|
const auto phase = sync_enter_push(params);
|
||||||
const auto r = params.rank;
|
const auto r = params.rank;
|
||||||
@@ -343,7 +344,7 @@ struct AllReducePullImpl {
|
|||||||
static_assert(kWorldSize <= kMaxWorldSize);
|
static_assert(kWorldSize <= kMaxWorldSize);
|
||||||
|
|
||||||
template <bool kFence>
|
template <bool kFence>
|
||||||
static SGL_DEVICE uint32_t sync_enter_pull(const AllReduceParams& params) {
|
static SGL_DEVICE uint32_t sync_enter_pull(const AllReduceParams<kWorldSize>& params) {
|
||||||
uint32_t current_counter_val = 0;
|
uint32_t current_counter_val = 0;
|
||||||
if (const auto tx = threadIdx.x; tx < kWorldSize) {
|
if (const auto tx = threadIdx.x; tx < kWorldSize) {
|
||||||
device::PDLWaitPrimary<kUsePDL>();
|
device::PDLWaitPrimary<kUsePDL>();
|
||||||
@@ -372,7 +373,7 @@ struct AllReducePullImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <bool kFence>
|
template <bool kFence>
|
||||||
static SGL_DEVICE void sync_exit_pull(const AllReduceParams& params, uint32_t current) {
|
static SGL_DEVICE void sync_exit_pull(const AllReduceParams<kWorldSize>& params, uint32_t current) {
|
||||||
device::PDLTriggerSecondary<kUsePDL>();
|
device::PDLTriggerSecondary<kUsePDL>();
|
||||||
__syncthreads();
|
__syncthreads();
|
||||||
if (const auto tx = threadIdx.x; tx < kWorldSize) {
|
if (const auto tx = threadIdx.x; tx < kWorldSize) {
|
||||||
@@ -436,7 +437,7 @@ struct AllReducePullImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static SGL_DEVICE void forward_1shot(const AllReduceParams& params) {
|
static SGL_DEVICE void forward_1shot(const AllReduceParams<kWorldSize>& params) {
|
||||||
const auto total_num_vecs = device::div_ceil(params.num_elements, kElemsPerVec);
|
const auto total_num_vecs = device::div_ceil(params.num_elements, kElemsPerVec);
|
||||||
void* data[kWorldSize];
|
void* data[kWorldSize];
|
||||||
if constexpr (kMode == PullMode::Graph) {
|
if constexpr (kMode == PullMode::Graph) {
|
||||||
@@ -455,7 +456,7 @@ struct AllReducePullImpl {
|
|||||||
sync_exit_pull<false>(params, counter);
|
sync_exit_pull<false>(params, counter);
|
||||||
}
|
}
|
||||||
|
|
||||||
static SGL_DEVICE void forward_2shot(const AllReduceParams& params) {
|
static SGL_DEVICE void forward_2shot(const AllReduceParams<kWorldSize>& params) {
|
||||||
const auto total_num_vecs = device::div_ceil(params.num_elements, kElemsPerVec);
|
const auto total_num_vecs = device::div_ceil(params.num_elements, kElemsPerVec);
|
||||||
const auto avg_vecs = total_num_vecs / kWorldSize;
|
const auto avg_vecs = total_num_vecs / kWorldSize;
|
||||||
const auto rem_vecs = total_num_vecs % kWorldSize;
|
const auto rem_vecs = total_num_vecs % kWorldSize;
|
||||||
@@ -481,9 +482,9 @@ struct AllReducePullImpl {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Impl, int kShot>
|
template <typename Impl, uint32_t kWorldSize, int kShot>
|
||||||
__global__ __launch_bounds__(1024, 1) //
|
__global__ __launch_bounds__(1024, 1) //
|
||||||
void all_reduce_kernel(const __grid_constant__ AllReduceParams params) {
|
void all_reduce_kernel(const __grid_constant__ AllReduceParams<kWorldSize> params) {
|
||||||
static_assert(kShot == 1 || kShot == 2, "invalid shot");
|
static_assert(kShot == 1 || kShot == 2, "invalid shot");
|
||||||
if constexpr (kShot == 1) {
|
if constexpr (kShot == 1) {
|
||||||
return Impl::forward_1shot(params);
|
return Impl::forward_1shot(params);
|
||||||
@@ -528,9 +529,10 @@ struct AllReduceKernel {
|
|||||||
using Tensor = tvm::ffi::Tensor;
|
using Tensor = tvm::ffi::Tensor;
|
||||||
using TensorView = tvm::ffi::TensorView;
|
using TensorView = tvm::ffi::TensorView;
|
||||||
template <int kShot, PullMode kPullMode>
|
template <int kShot, PullMode kPullMode>
|
||||||
static constexpr auto kernel_pull = all_reduce_kernel<AllReducePullImpl<T, kWorldSize, kPullMode, kUsePDL>, kShot>;
|
static constexpr auto kernel_pull =
|
||||||
|
all_reduce_kernel<AllReducePullImpl<T, kWorldSize, kPullMode, kUsePDL>, kWorldSize, kShot>;
|
||||||
template <int kShot>
|
template <int kShot>
|
||||||
static constexpr auto kernel_push = all_reduce_kernel<AllReducePushImpl<T, kWorldSize, kUsePDL>, kShot>;
|
static constexpr auto kernel_push = all_reduce_kernel<AllReducePushImpl<T, kWorldSize, kUsePDL>, kWorldSize, kShot>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static Tensor run(CommunicatorRef ref, Tensor in_, std::string algo, std::variant<TensorView, bool> pull_arg) {
|
static Tensor run(CommunicatorRef ref, Tensor in_, std::string algo, std::variant<TensorView, bool> pull_arg) {
|
||||||
@@ -549,7 +551,7 @@ struct AllReduceKernel {
|
|||||||
const auto graph_ptr = use_graph ? std::get<TensorView>(pull_arg).data_ptr() : nullptr;
|
const auto graph_ptr = use_graph ? std::get<TensorView>(pull_arg).data_ptr() : nullptr;
|
||||||
const bool inplace = use_graph && algo == "2shot_pull";
|
const bool inplace = use_graph && algo == "2shot_pull";
|
||||||
Tensor out = inplace ? in_ : ffi::empty_like(in_);
|
Tensor out = inplace ? in_ : ffi::empty_like(in_);
|
||||||
AllReduceParams params{
|
AllReduceParams<kWorldSize> params{
|
||||||
.input = in_.data_ptr(),
|
.input = in_.data_ptr(),
|
||||||
.output = out.data_ptr(),
|
.output = out.data_ptr(),
|
||||||
.num_elements = num_elems,
|
.num_elements = num_elems,
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
namespace device::distributed {
|
namespace device::distributed {
|
||||||
|
|
||||||
inline constexpr uint32_t kMaxWorldSize = 8;
|
inline constexpr uint32_t kMaxWorldSize = 16;
|
||||||
|
|
||||||
struct Counter {
|
struct Counter {
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ def _pack_heuristic(*args) -> Heuristic:
|
|||||||
|
|
||||||
|
|
||||||
def _sm100_config(world_size: int, num_sm: int) -> AllReduceConfig:
|
def _sm100_config(world_size: int, num_sm: int) -> AllReduceConfig:
|
||||||
# SM100 (Blackwell, B200/B300). Tuned on B200 (148 SMs).
|
# SM100 (Blackwell, B200/B300/GB200). Tuned on B200 (148 SMs); world 16 on GB200.
|
||||||
graph_map = {
|
graph_map = {
|
||||||
2: (8.000 * MB, 32.00 * MB, 128.0 * MB),
|
2: (8.000 * MB, 32.00 * MB, 128.0 * MB),
|
||||||
3: (4.000 * MB, 4.000 * MB, 128.0 * MB),
|
3: (4.000 * MB, 4.000 * MB, 128.0 * MB),
|
||||||
@@ -122,6 +122,7 @@ def _sm100_config(world_size: int, num_sm: int) -> AllReduceConfig:
|
|||||||
6: (1.000 * MB, 1.000 * MB, 128.0 * MB),
|
6: (1.000 * MB, 1.000 * MB, 128.0 * MB),
|
||||||
7: (0.625 * MB, 0.625 * MB, 128.0 * MB),
|
7: (0.625 * MB, 0.625 * MB, 128.0 * MB),
|
||||||
8: (0.500 * MB, 0.500 * MB, 128.0 * MB, Range(8 * MB, 128 * MB)),
|
8: (0.500 * MB, 0.500 * MB, 128.0 * MB, Range(8 * MB, 128 * MB)),
|
||||||
|
16: (0.250 * MB, 0.250 * MB, 128.0 * MB, Range(256 * KB, 128 * MB)),
|
||||||
}
|
}
|
||||||
eager_map = {
|
eager_map = {
|
||||||
2: (16.00 * MB, 128.0 * MB, 128.0 * MB),
|
2: (16.00 * MB, 128.0 * MB, 128.0 * MB),
|
||||||
@@ -131,8 +132,9 @@ def _sm100_config(world_size: int, num_sm: int) -> AllReduceConfig:
|
|||||||
6: (1.250 * MB, 1.250 * MB, 64.00 * MB, Range(0, 64 * MB)),
|
6: (1.250 * MB, 1.250 * MB, 64.00 * MB, Range(0, 64 * MB)),
|
||||||
7: (1.000 * MB, 1.000 * MB, 64.00 * MB, Range(0, 64 * MB)),
|
7: (1.000 * MB, 1.000 * MB, 64.00 * MB, Range(0, 64 * MB)),
|
||||||
8: (0.750 * MB, 0.750 * MB, 128.0 * MB, Range(0, 128 * MB)),
|
8: (0.750 * MB, 0.750 * MB, 128.0 * MB, Range(0, 128 * MB)),
|
||||||
|
16: (0.250 * MB, 0.250 * MB, 128.0 * MB, Range(256 * KB, 128 * MB)),
|
||||||
}
|
}
|
||||||
mc_blocks_map = {5: 64, 6: 48, 7: 48, 8: 32}
|
mc_blocks_map = {5: 64, 6: 48, 7: 48, 8: 32, 16: 32}
|
||||||
return AllReduceConfig(
|
return AllReduceConfig(
|
||||||
graph=_pack_heuristic(*graph_map[world_size]),
|
graph=_pack_heuristic(*graph_map[world_size]),
|
||||||
eager=_pack_heuristic(*eager_map[world_size]),
|
eager=_pack_heuristic(*eager_map[world_size]),
|
||||||
|
|||||||
@@ -352,8 +352,8 @@ def dispatch_custom_allreduce(
|
|||||||
|
|
||||||
On CUDA, the JIT-compiled v2 implementation is used by default.
|
On CUDA, the JIT-compiled v2 implementation is used by default.
|
||||||
Set SGLANG_OPT_USE_CUSTOM_ALL_REDUCE_V2=0 to fall back to the legacy CustomAllreduce.
|
Set SGLANG_OPT_USE_CUSTOM_ALL_REDUCE_V2=0 to fall back to the legacy CustomAllreduce.
|
||||||
Note: ServerArgs._handle_environment_variables forces this env to "0" when
|
Multi-node v2 is admitted only for a single NVLink clique (see
|
||||||
nnodes > 1 since custom AR is intra-node only.
|
can_use_custom_all_reduce_v2); other cross-node groups fall back to NCCL.
|
||||||
"""
|
"""
|
||||||
if _is_cuda and envs.SGLANG_OPT_USE_CUSTOM_ALL_REDUCE_V2.get():
|
if _is_cuda and envs.SGLANG_OPT_USE_CUSTOM_ALL_REDUCE_V2.get():
|
||||||
from .custom_all_reduce_v2 import (
|
from .custom_all_reduce_v2 import (
|
||||||
|
|||||||
@@ -391,6 +391,53 @@ def is_full_nvlink(physical_device_ids: List[int], world_size: int) -> bool:
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
# NVML_GPU_FABRIC_STATE_COMPLETED: the GPU has joined its NVLink fabric clique.
|
||||||
|
_NVML_GPU_FABRIC_STATE_COMPLETED = 3
|
||||||
|
|
||||||
|
|
||||||
|
def _gpu_fabric_clique(device: torch.device):
|
||||||
|
"""(cluster_uuid, clique_id) of the local GPU's NVLink fabric clique, or None if
|
||||||
|
the GPU has not joined a fabric (single-node box / fabric init incomplete)."""
|
||||||
|
cuda_visible_devices = os.environ.get("CUDA_VISIBLE_DEVICES", None)
|
||||||
|
if cuda_visible_devices:
|
||||||
|
device_ids = list(map(int, cuda_visible_devices.split(",")))
|
||||||
|
else:
|
||||||
|
device_ids = list(range(torch.cuda.device_count()))
|
||||||
|
handle = pynvml.nvmlDeviceGetHandleByIndex(device_ids[device.index])
|
||||||
|
fabric = pynvml.c_nvmlGpuFabricInfo_v3_t()
|
||||||
|
fabric.version = pynvml.nvmlGpuFabricInfo_v3
|
||||||
|
pynvml.nvmlDeviceGetGpuFabricInfoV(handle, ctypes.byref(fabric))
|
||||||
|
if fabric.state != _NVML_GPU_FABRIC_STATE_COMPLETED:
|
||||||
|
return None
|
||||||
|
return (bytes(fabric.clusterUuid), int(fabric.cliqueId))
|
||||||
|
|
||||||
|
|
||||||
|
@with_nvml_context
|
||||||
|
def is_one_nvlink_clique(
|
||||||
|
group: torch.distributed.ProcessGroup, device: torch.device
|
||||||
|
) -> bool:
|
||||||
|
"""True iff every rank's GPU is in the same NVLink fabric clique (one NVL72 /
|
||||||
|
MNNVL domain). Such a clique shares a single NVLink address space even across
|
||||||
|
nodes, so custom-AR v2's symm-mem storage + fabric peer VAs are valid group-wide."""
|
||||||
|
if _is_hip:
|
||||||
|
return False
|
||||||
|
try:
|
||||||
|
clique = _gpu_fabric_clique(device)
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(
|
||||||
|
"GPU fabric clique query failed (%r); custom-AR stays intra-node.", e
|
||||||
|
)
|
||||||
|
clique = None
|
||||||
|
# Always all-gather (every rank calls it once) so a failed query on any rank
|
||||||
|
# resolves to a clean False rather than a collective mismatch.
|
||||||
|
world_size = dist.get_world_size(group=group)
|
||||||
|
gathered: List[object] = [None] * world_size
|
||||||
|
dist.all_gather_object(gathered, clique, group=group)
|
||||||
|
if any(c is None for c in gathered):
|
||||||
|
return False
|
||||||
|
return len(set(gathered)) == 1
|
||||||
|
|
||||||
|
|
||||||
def is_weak_contiguous(inp: torch.Tensor):
|
def is_weak_contiguous(inp: torch.Tensor):
|
||||||
return inp.is_contiguous() or (
|
return inp.is_contiguous() or (
|
||||||
inp.storage().nbytes() - inp.storage_offset() * inp.element_size()
|
inp.storage().nbytes() - inp.storage_offset() * inp.element_size()
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ from sglang.kernels.ops.communication.all_reduce import (
|
|||||||
IPCManager,
|
IPCManager,
|
||||||
custom_all_reduce,
|
custom_all_reduce,
|
||||||
)
|
)
|
||||||
|
from sglang.srt.distributed.parallel_state import in_the_same_node_as
|
||||||
from sglang.srt.environ import envs
|
from sglang.srt.environ import envs
|
||||||
from sglang.srt.model_executor.runner_backend_utils.tc_piecewise_cuda_graph import (
|
from sglang.srt.model_executor.runner_backend_utils.tc_piecewise_cuda_graph import (
|
||||||
is_in_tc_piecewise_cuda_graph,
|
is_in_tc_piecewise_cuda_graph,
|
||||||
@@ -39,6 +40,7 @@ from sglang.srt.model_executor.runner_backend_utils.tc_piecewise_cuda_graph impo
|
|||||||
from .configs.custom_all_reduce_v2 import get_all_reduce_config
|
from .configs.custom_all_reduce_v2 import get_all_reduce_config
|
||||||
from .custom_all_reduce_utils import (
|
from .custom_all_reduce_utils import (
|
||||||
can_use_custom_all_reduce_with_nvlink,
|
can_use_custom_all_reduce_with_nvlink,
|
||||||
|
is_one_nvlink_clique,
|
||||||
is_weak_contiguous,
|
is_weak_contiguous,
|
||||||
)
|
)
|
||||||
from .vmm_utils import (
|
from .vmm_utils import (
|
||||||
@@ -139,7 +141,7 @@ class CustomAllReduceV2:
|
|||||||
self.tms_cudagraph = envs.SGLANG_MEMORY_SAVER_CUDA_GRAPH.get()
|
self.tms_cudagraph = envs.SGLANG_MEMORY_SAVER_CUDA_GRAPH.get()
|
||||||
|
|
||||||
# device-side pointer table: one row of world_size pointers per
|
# device-side pointer table: one row of world_size pointers per
|
||||||
# graph-captured all-reduce input (at most 8 MB at world_size = 8)
|
# graph-captured all-reduce input
|
||||||
self.graph_params = torch.zeros(
|
self.graph_params = torch.zeros(
|
||||||
(_MAX_GRAPH_INPUTS, self.world_size),
|
(_MAX_GRAPH_INPUTS, self.world_size),
|
||||||
dtype=torch.uint64,
|
dtype=torch.uint64,
|
||||||
@@ -407,14 +409,29 @@ class CustomAllReduceV2:
|
|||||||
self.close()
|
self.close()
|
||||||
|
|
||||||
|
|
||||||
|
def _is_vmm_backed_allocator(device: torch.device) -> bool:
|
||||||
|
"""True iff the caching allocator is VMM-backed (expandable_segments). Uniform
|
||||||
|
launch, so the local probe reflects every rank."""
|
||||||
|
probe = torch.empty(1, dtype=torch.uint8, device=device)
|
||||||
|
return is_vmm_pointer(probe.data_ptr())
|
||||||
|
|
||||||
|
|
||||||
def can_use_custom_all_reduce_v2(
|
def can_use_custom_all_reduce_v2(
|
||||||
group: ProcessGroup,
|
group: ProcessGroup,
|
||||||
device: torch.device,
|
device: torch.device,
|
||||||
) -> bool:
|
) -> bool:
|
||||||
|
supported = list(range(2, 17))
|
||||||
|
if dist.get_world_size(group=group) not in supported:
|
||||||
|
return False
|
||||||
|
# Multi-node needs a single NVLink clique (one NVL72 / MNNVL domain) whose
|
||||||
|
# allocator is VMM-backed: graph inputs cross nodes via FABRIC / POSIX-fd VMM
|
||||||
|
# handles, not cudaIpc (intra-node only). Else use the intra-node nvlink check.
|
||||||
|
if not all(in_the_same_node_as(group, source_rank=0)):
|
||||||
|
return is_one_nvlink_clique(group, device) and _is_vmm_backed_allocator(device)
|
||||||
full_nvlink = can_use_custom_all_reduce_with_nvlink(
|
full_nvlink = can_use_custom_all_reduce_with_nvlink(
|
||||||
group=group,
|
group=group,
|
||||||
device=device,
|
device=device,
|
||||||
supported_world_size=list(range(2, 9)),
|
supported_world_size=supported,
|
||||||
cls_name="CustomAllReduceV2",
|
cls_name="CustomAllReduceV2",
|
||||||
)
|
)
|
||||||
return full_nvlink is True
|
return full_nvlink is True
|
||||||
|
|||||||
@@ -7317,16 +7317,6 @@ class ServerArgs:
|
|||||||
envs.SGLANG_ENABLE_DETERMINISTIC_INFERENCE.set(
|
envs.SGLANG_ENABLE_DETERMINISTIC_INFERENCE.set(
|
||||||
"1" if self.enable_deterministic_inference else "0"
|
"1" if self.enable_deterministic_inference else "0"
|
||||||
)
|
)
|
||||||
# Custom all-reduce v2 uses IPC handles and is intra-node only. Force-disable
|
|
||||||
# on multi-node so the dispatch falls back to the legacy CustomAllreduce path.
|
|
||||||
if self.nnodes > 1 and envs.SGLANG_OPT_USE_CUSTOM_ALL_REDUCE_V2.get():
|
|
||||||
if envs.SGLANG_OPT_USE_CUSTOM_ALL_REDUCE_V2.is_set():
|
|
||||||
logger.warning(
|
|
||||||
"Disabling SGLANG_OPT_USE_CUSTOM_ALL_REDUCE_V2 because nnodes=%d "
|
|
||||||
"(custom all-reduce v2 is intra-node only).",
|
|
||||||
self.nnodes,
|
|
||||||
)
|
|
||||||
envs.SGLANG_OPT_USE_CUSTOM_ALL_REDUCE_V2.set("0")
|
|
||||||
if self.debug_cuda_graph:
|
if self.debug_cuda_graph:
|
||||||
if not (is_cuda() or is_hip()):
|
if not (is_cuda() or is_hip()):
|
||||||
logger.warning(
|
logger.warning(
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ DTYPE_ITEMSIZE = DTYPE.itemsize
|
|||||||
MESSAGE_SIZES_KB = [2**x for x in range(2, 17)]
|
MESSAGE_SIZES_KB = [2**x for x in range(2, 17)]
|
||||||
MESSAGE_SIZES_KB += [192, 384, 640, 768, 896, 1536, 3072]
|
MESSAGE_SIZES_KB += [192, 384, 640, 768, 896, 1536, 3072]
|
||||||
MESSAGE_SIZES_KB.sort()
|
MESSAGE_SIZES_KB.sort()
|
||||||
WORLD_SIZES = list(range(2, 9))
|
WORLD_SIZES = list(range(2, 9)) + [16]
|
||||||
MAX_BYTES = max(MESSAGE_SIZES_KB) * 1024
|
MAX_BYTES = max(MESSAGE_SIZES_KB) * 1024
|
||||||
# trtllm allreduce_fusion only supports these world sizes.
|
# trtllm allreduce_fusion only supports these world sizes.
|
||||||
FI_SUPPORTED_WORLD_SIZES = (2, 4, 8)
|
FI_SUPPORTED_WORLD_SIZES = (2, 4, 8)
|
||||||
|
|||||||
@@ -235,12 +235,13 @@ def test_custom_all_reduce(
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
# Only sweep the common world sizes (2, 4, 8) by default: testing every
|
# Only sweep the common world sizes (2, 4, 8, 16) by default: testing every
|
||||||
# count in 2..8 serially overruns the per-file CI time budget, and 3/5/6/7
|
# count in 2..16 serially overruns the per-file CI time budget, and numbers
|
||||||
# are rare in practice. Use --num-gpu to exercise them explicitly.
|
# in the middle are rare in practice. Use --num-gpu to exercise them
|
||||||
|
# explicitly.
|
||||||
multigpu_pytest_main(
|
multigpu_pytest_main(
|
||||||
__name__,
|
__name__,
|
||||||
__file__,
|
__file__,
|
||||||
num_gpus=(2, 4, 8),
|
num_gpus=(2, 4, 8, 16),
|
||||||
pre_launch_fn=_precompile_kernels,
|
pre_launch_fn=_precompile_kernels,
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user