|
|
|
@@ -72,10 +72,24 @@ static float hwLat [3][NCCL_NUM_ALGORITHMS][NCCL_NUM_PROTOCOLS] =
|
|
|
|
|
/* CollNetDirect (Simple)*/ { 0, 0, 10.7 }, /* CollNetChain (Simple)*/ { 0, 0, 10.7 } }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* Array indexes used below */
|
|
|
|
|
#define VOLTA_COMPCAP_IDX 0
|
|
|
|
|
#define AMPERE_COMPCAP_IDX 1
|
|
|
|
|
#define HOPPER_COMPCAP_IDX 2
|
|
|
|
|
|
|
|
|
|
// LL128 max BW per channel
|
|
|
|
|
static const double ll128MaxBwPerCh = 20.0;
|
|
|
|
|
static const double llMaxBws[2][3] = { /* Volta-N1/Intel-N2/Intel-N4) */ {39.0, 39.0, 20.4}, /* Ampere-N1/AMD-N2/AMD-N4) */ {87.7, 22.5 /*avg of ring & tree*/, 19.0} };
|
|
|
|
|
static const double perChMaxTreeBws[2][3] = { /* Volta (N1/N2/N4) */ {26.5, 18.5, 10.0}, /* Ampere (N1/N2/N4) */ {24.0, 23.6, 17.8} };
|
|
|
|
|
static const double llMaxBws[3][3] = {
|
|
|
|
|
/* Volta-N1/Intel-N2/Intel-N4) */ {39.0, 39.0, 20.4},
|
|
|
|
|
/* Ampere-N1/AMD-N2/AMD-N4) */ {87.7, 22.5 /*avg of ring & tree*/, 19.0},
|
|
|
|
|
/* Hopper-N1/AMD-N2/AMD-N4) */ {87.7, 22.5 /*avg of ring & tree*/, 19.0}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const double perChMaxTreeBws[3][3] = {
|
|
|
|
|
/* Volta (N1/N2/N4) */ {26.5, 18.5, 10.0},
|
|
|
|
|
/* Ampere (N1/N2/N4) */ {24.0, 23.6, 17.8},
|
|
|
|
|
/* Hopper (N1/N2/N4) */ {24.0, 23.6, 17.8},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
ncclResult_t ncclTopoTuneModel(struct ncclComm* comm, int minCompCap, int maxCompCap, struct ncclTopoGraph* treeGraph, struct ncclTopoGraph* ringGraph, struct ncclTopoGraph* collNetGraph) {
|
|
|
|
|
int simpleDefaultThreads = (ringGraph->bwIntra*ringGraph->nChannels <= PCI_BW) ? 256 : NCCL_SIMPLE_MAX_NTHREADS;
|
|
|
|
@@ -94,14 +108,14 @@ ncclResult_t ncclTopoTuneModel(struct ncclComm* comm, int minCompCap, int maxCom
|
|
|
|
|
int nRanks = comm->nRanks;
|
|
|
|
|
if (nRanks <= 1) return ncclSuccess;
|
|
|
|
|
|
|
|
|
|
int compCap80 = minCompCap == 80 && maxCompCap == 80 ? 1 : 0;
|
|
|
|
|
int compCapIndex = (minCompCap == 80 && maxCompCap == 80) ? AMPERE_COMPCAP_IDX : ((minCompCap == 90 && maxCompCap == 90) ? HOPPER_COMPCAP_IDX : VOLTA_COMPCAP_IDX);
|
|
|
|
|
int cpuArch, cpuVendor, cpuModel;
|
|
|
|
|
NCCLCHECK(ncclTopoCpuType(comm->topo, &cpuArch, &cpuVendor, &cpuModel));
|
|
|
|
|
int index2 = nNodes <= 2 ? nNodes-1 : 2;
|
|
|
|
|
// LL: for single node, we look at GPU type; for multi-node, we look at CPU type
|
|
|
|
|
int index1 = nNodes == 1 ? compCap80 : cpuVendor == NCCL_TOPO_CPU_VENDOR_AMD ? 1 : 0;
|
|
|
|
|
int index1 = nNodes == 1 ? compCapIndex : cpuVendor == NCCL_TOPO_CPU_VENDOR_AMD ? 1 : 0;
|
|
|
|
|
double llMaxBw = llMaxBws[index1][index2];
|
|
|
|
|
double perChMaxTreeBw = perChMaxTreeBws[compCap80][index2];
|
|
|
|
|
double perChMaxTreeBw = perChMaxTreeBws[compCapIndex][index2];
|
|
|
|
|
// De-penalize Tree/Simple latency on Power systems to favor Tree than Ring
|
|
|
|
|
if (cpuArch == NCCL_TOPO_CPU_ARCH_POWER) hwLat[NCCL_HW_PCI][NCCL_ALGO_TREE][NCCL_PROTO_SIMPLE] = hwLat[NCCL_HW_PCI][NCCL_ALGO_RING][NCCL_PROTO_SIMPLE];
|
|
|
|
|
float ppn = (float)nRanks / nNodes; // if ppn < 2, then we are sending/receiving at the same GPU through the NIC, apply some bw discount
|
|
|
|
@@ -128,7 +142,7 @@ ncclResult_t ncclTopoTuneModel(struct ncclComm* comm, int minCompCap, int maxCom
|
|
|
|
|
float busBw = graphs[a]->nChannels * bw;
|
|
|
|
|
|
|
|
|
|
// Various model refinements
|
|
|
|
|
if (compCap80) busBw = std::min(busBw, 235.0f);
|
|
|
|
|
if (compCapIndex == AMPERE_COMPCAP_IDX) busBw = std::min(busBw, 235.0f);
|
|
|
|
|
if (a == NCCL_ALGO_RING && p == NCCL_PROTO_LL) { busBw = std::min(llMaxBw, busBw * ((nNodes > 1 || coll == ncclFuncAllReduce || coll == ncclFuncReduce) ? 1.0/4.0 : 1.0/3.0)); }
|
|
|
|
|
if (a == NCCL_ALGO_RING && p == NCCL_PROTO_LL128) busBw = std::min(busBw * (ppn < 2 ? 0.7 : 0.92 /*120.0/128.0*/), ll128MaxBwPerCh*graphs[a]->nChannels);
|
|
|
|
|
if (a == NCCL_ALGO_TREE) busBw = std::min(busBw*.92, graphs[a]->nChannels*perChMaxTreeBw);
|
|
|
|
@@ -136,13 +150,13 @@ ncclResult_t ncclTopoTuneModel(struct ncclComm* comm, int minCompCap, int maxCom
|
|
|
|
|
if (a == NCCL_ALGO_TREE && p == NCCL_PROTO_LL128) busBw = std::min(busBw * (nNodes == 1 ? 7.0/9.0 : 120.0/128.0), ll128MaxBwPerCh*graphs[a]->nChannels);
|
|
|
|
|
if (a == NCCL_ALGO_COLLNET_DIRECT && p != NCCL_PROTO_SIMPLE) busBw = 0; // Not used
|
|
|
|
|
if (a == NCCL_ALGO_COLLNET_CHAIN && p != NCCL_PROTO_SIMPLE) busBw = 0; // Not used
|
|
|
|
|
if (a == NCCL_ALGO_COLLNET_DIRECT && p == NCCL_PROTO_SIMPLE) {
|
|
|
|
|
if (a == NCCL_ALGO_COLLNET_DIRECT && p == NCCL_PROTO_SIMPLE) {
|
|
|
|
|
// Collnet+Direct requires all GPUs to have a local NIC to work at full speed
|
|
|
|
|
float factor = ppn / (1.0*graphs[a]->nChannels); // GPU/NIC ratio
|
|
|
|
|
factor -= (factor-1)/2;
|
|
|
|
|
factor -= (factor-1)/2;
|
|
|
|
|
busBw /= factor;
|
|
|
|
|
}
|
|
|
|
|
if (a == NCCL_ALGO_COLLNET_CHAIN && p == NCCL_PROTO_SIMPLE) busBw *= .75;
|
|
|
|
|
}
|
|
|
|
|
if (a == NCCL_ALGO_COLLNET_CHAIN && p == NCCL_PROTO_SIMPLE) busBw *= .75;
|
|
|
|
|
|
|
|
|
|
// Convert bus BW to algorithm BW
|
|
|
|
|
float ratio = (a != NCCL_ALGO_RING) ? .5 : (1.0 * nRanks) / nsteps;
|
|
|
|
@@ -212,9 +226,9 @@ ncclResult_t ncclTopoTuneModel(struct ncclComm* comm, int minCompCap, int maxCom
|
|
|
|
|
for (int c=0; c<NCCL_NUM_FUNCTIONS; c++) for (int a=0; a<NCCL_NUM_ALGORITHMS; a++) for (int p=0; p<NCCL_NUM_PROTOCOLS; p++) {
|
|
|
|
|
int pEnable = protoEnable[p];
|
|
|
|
|
if (pEnable == 2 && p == NCCL_PROTO_LL128) {
|
|
|
|
|
// Enable LL128 by default only on Volta/Ampere+NVLink. Other cases are not tested and may cause silent data corruption.
|
|
|
|
|
// Enable LL128 by default only on Volta/Ampere/Hopper+NVLink. Other cases are not tested and may cause silent data corruption.
|
|
|
|
|
pEnable = (graphs[a]->typeInter <= PATH_PXB) && graphs[a]->typeIntra <= PATH_NVL &&
|
|
|
|
|
((minCompCap == 70 && maxCompCap == 70) || (minCompCap == 80 && maxCompCap == 80)) ? 1 : 0;
|
|
|
|
|
((minCompCap == 70 && maxCompCap == 70) || (minCompCap == 80 && maxCompCap == 80) || (minCompCap == 90 && maxCompCap == 90)) ? 1 : 0;
|
|
|
|
|
}
|
|
|
|
|
if (pEnable == 0) comm->bandwidths[c][a][p] = 0;
|
|
|
|
|
// Only disable algo for Allreduce since others only have one
|
|
|
|
|