2019-11-19 14:57:39 -08:00
/*************************************************************************
2022-01-07 06:39:55 -08:00
* Copyright (c) 2016-2022, NVIDIA CORPORATION. All rights reserved.
2022-04-18 11:14:51 -07:00
* Modifications Copyright (c) 2019-2022 Advanced Micro Devices, Inc. All rights reserved.
2019-11-19 14:57:39 -08:00
*
* See LICENSE.txt for license information
************************************************************************/
#include "core.h"
2023-09-26 05:47:28 -07:00
#include "device.h"
2019-11-19 14:57:39 -08:00
#include "comm.h"
#include "topo.h"
NCCL_PARAM ( Nthreads , "NTHREADS" , - 2 );
NCCL_PARAM ( Ll128Nthreads , "LL128_NTHREADS" , - 2 );
2022-11-03 17:42:38 +00:00
static int getNthreads ( const char * name , int env , int min , int max , int def , int WarpSize ) {
2019-11-19 14:57:39 -08:00
int nt = env ;
if ( nt > 0 ) {
2022-11-03 17:42:38 +00:00
if ( nt % WarpSize != 0 ) {
WARN ( "Invalid %s %d (must be a multiple of %d)" , name , nt , WarpSize );
2019-11-19 14:57:39 -08:00
nt = max ;
} else if ( nt > max ) {
WARN ( "Invalid %s %d (maximum %d)." , name , nt , max );
nt = max ;
} else if ( nt < min ) {
WARN ( "Invalid %s %d (minimum %d)." , name , nt , min );
nt = min ;
}
} else {
nt = def ;
}
return nt ;
}
ncclResult_t parseList ( const char * str , const char * elems [], int nelems , int * list ) {
int def , set ;
if ( str [ 0 ] == '^' ) {
def = 1 ; set = 0 ; str ++ ;
} else {
def = 0 ; set = 1 ;
}
for ( int i = 0 ; i < nelems ; i ++ ) list [ i ] = def ;
char * tokStr = strdup ( str );
char * tmpStr ;
char * token = strtok_r ( tokStr , "," , & tmpStr );
while ( token ) {
for ( int i = 0 ; i < nelems ; i ++ )
if ( strcasecmp ( token , elems [ i ]) == 0 ) list [ i ] = set ;
token = strtok_r ( NULL , "," , & tmpStr );
}
free ( tokStr );
return ncclSuccess ;
}
// Latencies in us, Bandwidths in GB/s
// Tree { LL, LL128, Simple } , Ring { LL, LL128, Simple }
2023-06-21 20:54:24 -07:00
static const float baseLat [ NCCL_NUM_ALGORITHMS ][ NCCL_NUM_PROTOCOLS ] = {
{ 12.0 , 12.0 , 17.0 }, { 12.0 , 12.0 , 17.0 }, // Tree, Ring
{ 12.0 , 12.0 , 17.0 }, { 12.0 , 12.0 , 17.0 }, // Collnet Direct, Chain
{ 0 , 0 , 0 }, { 0 , 0 , 0 }}; // NVLS, NVLS Tree
2019-11-19 14:57:39 -08:00
// NVLink, PCI, Network
#define NCCL_HW_NVLINK 0
#define NCCL_HW_PCI 1
#define NCCL_HW_NET 2
2022-03-31 17:09:21 -07:00
struct tuningModel {
float hwLat [ 3 ][ NCCL_NUM_ALGORITHMS ][ NCCL_NUM_PROTOCOLS ];
float bwRatio [ 2 ][ NCCL_NUM_ALGORITHMS ][ NCCL_NUM_PROTOCOLS ];
float treeCorrectionFactor [ NCCL_NUM_PROTOCOLS ][ 27 ];
float ringCorrectionFactor [ NCCL_NUM_PROTOCOLS ][ 27 ];
};
static struct tuningModel tuning_model_0 {
. hwLat = {
/* NVLINK */
2023-06-21 20:54:24 -07:00
{ /* Tree (LL/LL128/Simple)*/ { 0.8 , 1.4 , 2.5 }, /* Ring (LL/LL128/Simple)*/ { 0.8 , 2.2 , 3.6 }, /* CollNetDirect (Simple)*/ { 0.0 , 0.0 , 0.8 }, /* CollNetChain (Simple)*/ { 0.0 , 0.0 , 1.4 }, /* NVLS */ { 0 , 0 , 0 }, /* NVLS Tree */ { 0 , 0 , 0 } },
2022-03-31 17:09:21 -07:00
/* PCI */
2023-06-21 20:54:24 -07:00
{ /* Tree (LL/LL128/Simple)*/ { 2.2 , 2.2 , 5.7 }, /* Ring (LL/LL128/Simple)*/ { 2.2 , 2.2 , 5.7 }, /* CollNetDirect (Simple)*/ { 0.0 , 0.0 , 5.7 }, /* CollNetChain (Simple)*/ { 0.0 , 0.0 , 5.7 }, /* NVLS */ { 0 , 0 , 0 }, /* NVLS Tree */ { 0 , 0 , 0 } },
2022-03-31 17:09:21 -07:00
/* NET */
2023-06-21 20:54:24 -07:00
{ /* Tree (LL/LL128/Simple)*/ { 11.8 , 18.2 , 20.8 }, /* Ring (LL/LL128/Simple)*/ { 9.5 , 19.8 , 15.1 }, /* CollNetDirect (Simple)*/ { 0.0 , 0.0 , 11.8 }, /* CollNetChain (Simple)*/ { 0.0 , 0.0 , 18.2 }, /* NVLS */ { 0 , 0 , 0 }, /* NVLS Tree */ { 0 , 0 , 0 } },
2022-03-31 17:09:21 -07:00
},
. bwRatio = {
/* 2 nodes */
2023-06-21 20:54:24 -07:00
{ /* Tree (LL/LL128/Simple)*/ { 0.04 , 0.22 , 0.91 }, /* Ring (LL/LL128/Simple)*/ { 0.04 , 0.34 , 1.00 }, /* CollNetDirect (Simple)*/ { 0.00 , 0.00 , 1.00 }, /* CollNetChain (Simple)*/ { 0.00 , 0.00 , 1.00 }, /* NVLS */ { 0 , 0 , 0 }, /* NVLS Tree */ { 0 , 0 , 0 } },
2022-03-31 17:09:21 -07:00
/* more than 2 nodes */
2023-06-21 20:54:24 -07:00
{ /* Tree (LL/LL128/Simple)*/ { 0.04 , 0.22 , 0.95 }, /* Ring (LL/LL128/Simple)*/ { 0.04 , 0.34 , 1.00 }, /* CollNetDirect (Simple)*/ { 0.00 , 0.00 , 1.00 }, /* CollNetChain (Simple)*/ { 0.00 , 0.00 , 1.00 }, /* NVLS */ { 0 , 0 , 0 }, /* NVLS Tree */ { 0 , 0 , 0 } },
2022-03-31 17:09:21 -07:00
},
. treeCorrectionFactor = {
2022-11-04 22:54:29 +00:00
{ 0.1 , 0.2 , 0.1 , 0.1 , 0.9 , 0.3 , 0.4 , 0.1 , 0.2 , 0.4 , 0.2 , 0.1 , 0.3 , 0.3 , 0.2 , 0.2 , 0.2 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , },
{ 0.1 , 0.3 , 1.0 , 0.1 , 0.5 , 1.0 , 0.9 , 1.0 , 1.0 , 1.0 , 0.3 , 0.1 , 0.4 , 0.5 , 0.5 , 0.4 , 0.4 , 0.3 , 0.3 , 0.2 , 0.2 , 0.2 , 0.2 , 0.2 , 0.2 , 0.2 , 0.2 , },
{ 0.2 , 1.0 , 0.1 , 0.1 , 0.7 , 0.2 , 0.4 , 0.1 , 0.1 , 0.3 , 0.4 , 0.3 , 0.6 , 0.8 , 1.0 , 1.0 , 1.0 , 1.0 , 0.9 , 0.8 , 0.8 , 0.8 , 0.8 , 0.8 , 0.9 , 0.9 , 0.9 , },
2022-03-31 17:09:21 -07:00
},
. ringCorrectionFactor = {
2022-11-04 22:54:29 +00:00
{ 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.2 , 0.4 , 0.2 , 0.3 , 0.5 , 0.3 , 0.1 , 0.5 , 0.5 , 0.3 , 0.2 , 0.2 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , },
{ 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.3 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 0.8 , 0.7 , 0.5 , 0.4 , 0.4 , 0.3 , 0.3 , 0.3 , 0.3 , 0.3 , 0.3 , },
{ 1.0 , 0.8 , 0.2 , 1.0 , 1.0 , 0.3 , 1.0 , 0.1 , 0.1 , 0.2 , 0.2 , 0.1 , 0.5 , 1.0 , 0.8 , 0.8 , 1.0 , 0.9 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , },
2022-03-31 17:09:21 -07:00
},
};
static struct tuningModel tuning_model_1 {
. hwLat =
{ /* NVLINK */
2023-06-21 20:54:24 -07:00
{ /* Tree (LL/LL128/Simple)*/ { 1.5 , 1.5 , 4.5 }, /* Ring (LL/LL128/Simple)*/ { 1.5 , 1.5 , 4.5 }, /* CollNetDirect (Simple)*/ { 0.0 , 0.0 , 4.5 }, /* CollNetChain (Simple)*/ { 0.0 , 0.0 , 4.5 }, /* NVLS */ { 0 , 0 , 0 }, /* NVLS Tree */ { 0 , 0 , 0 } },
2022-03-31 17:09:21 -07:00
/* PCI */
2023-06-21 20:54:24 -07:00
{ /* Tree (LL/LL128/Simple)*/ { 2.2 , 2.2 , 5.7 }, /* Ring (LL/LL128/Simple)*/ { 2.2 , 2.2 , 5.7 }, /* CollNetDirect (Simple)*/ { 0.0 , 0.0 , 5.7 }, /* CollNetChain (Simple)*/ { 0.0 , 0.0 , 5.7 }, /* NVLS */ { 0 , 0 , 0 }, /* NVLS Tree */ { 0 , 0 , 0 } },
2022-03-31 17:09:21 -07:00
/* NET */
2023-06-21 20:54:24 -07:00
{ /* Tree (LL/LL128/Simple)*/ { 33.0 , 33.0 , 15.8 }, /* Ring (LL/LL128/Simple)*/ { 5.1 , 5.1 , 68.8 }, /* CollNetDirect (Simple)*/ { 0.0 , 0.0 , 15.8 }, /* CollNetChain (Simple)*/ { 0.0 , 0.0 , 15.8 }, /* NVLS */ { 0 , 0 , 0 }, /* NVLS Tree */ { 0 , 0 , 0 } },
2022-03-31 17:09:21 -07:00
},
. bwRatio =
{ /* 2 nodes */
2023-06-21 20:54:24 -07:00
{ /* Tree (LL/LL128/Simple)*/ { 0.12 , 1.00 , 0.99 }, /* Ring (LL/LL128/Simple)*/ { 0.12 , 1.00 , 1.00 }, /* CollNetDirect (Simple)*/ { 0.00 , 0.00 , 1.00 }, /* CollNetChain (Simple)*/ { 0.00 , 0.00 , 1.00 }, /* NVLS */ { 0 , 0 , 0 }, /* NVLS Tree */ { 0 , 0 , 0 } },
2022-03-31 17:09:21 -07:00
/* more than 2 nodes */
2023-06-21 20:54:24 -07:00
{ /* Tree (LL/LL128/Simple)*/ { 0.15 , 1.00 , 0.42 }, /* Ring (LL/LL128/Simple)*/ { 0.20 , 1.00 , 1.00 }, /* CollNetDirect (Simple)*/ { 0.00 , 0.00 , 1.00 }, /* CollNetChain (Simple)*/ { 0.00 , 0.00 , 1.00 }, /* NVLS */ { 0 , 0 , 0 }, /* NVLS Tree */ { 0 , 0 , 0 } },
2022-03-31 17:09:21 -07:00
},
. treeCorrectionFactor = {
{ 0.5 , 0.4 , 0.7 , 0.6 , 1.0 , 1.0 , 0.5 , 0.4 , 0.1 , 0.5 , 0.4 , 0.6 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 0.8 , 0.6 , 0.5 , 0.4 , 0.4 , 0.3 , 0.2 , 0.1 , 0.1 , 0.1 , },
{ 0.5 , 0.4 , 0.7 , 0.6 , 1.0 , 1.0 , 0.5 , 0.4 , 0.1 , 0.5 , 0.4 , 0.6 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 0.8 , 0.6 , 0.5 , 0.4 , 0.4 , 0.3 , 0.2 , 0.1 , 0.1 , 0.1 , },
{ 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.3 , 0.4 , 0.5 , 0.1 , 0.6 , 1.0 , 1.0 , 1.0 , 0.6 , 0.5 , 0.7 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 0.7 , 0.5 , 0.3 , 0.3 , },
},
. ringCorrectionFactor = {
{ 1.0 , 0.5 , 1.0 , 1.0 , 0.6 , 0.7 , 1.0 , 1.0 , 0.2 , 1.0 , 0.9 , 0.7 , 1.0 , 1.0 , 1.0 , 0.9 , 0.9 , 0.8 , 0.8 , 0.7 , 0.6 , 0.5 , 0.5 , 0.3 , 0.2 , 0.1 , 0.1 , },
{ 1.0 , 0.5 , 1.0 , 1.0 , 0.6 , 0.7 , 1.0 , 1.0 , 0.2 , 1.0 , 0.9 , 0.7 , 1.0 , 1.0 , 1.0 , 0.9 , 0.9 , 0.8 , 0.8 , 0.7 , 0.6 , 0.5 , 0.5 , 0.3 , 0.2 , 0.1 , 0.1 , },
{ 0.3 , 1.0 , 0.3 , 0.1 , 0.1 , 0.1 , 0.3 , 0.7 , 1.0 , 0.2 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.2 , 0.3 , 0.5 , 0.9 , 1.0 , 1.0 , 1.0 , 1.0 , },
},
};
static struct tuningModel tuning_model_2 {
. hwLat = {
/* NVLINK */
2023-06-21 20:54:24 -07:00
{ /* Tree (LL/LL128/Simple)*/ { 1.5 , 1.5 , 4.5 }, /* Ring (LL/LL128/Simple)*/ { 1.5 , 1.5 , 4.5 }, /* CollNetDirect (Simple)*/ { 0.0 , 0.0 , 4.5 }, /* CollNetChain (Simple)*/ { 0.0 , 0.0 , 4.5 }, /* NVLS */ { 0 , 0 , 0 }, /* NVLS Tree */ { 0 , 0 , 0 } },
2022-03-31 17:09:21 -07:00
/* PCI */
2023-06-21 20:54:24 -07:00
{ /* Tree (LL/LL128/Simple)*/ { 2.2 , 2.2 , 5.7 }, /* Ring (LL/LL128/Simple)*/ { 2.2 , 2.2 , 5.7 }, /* CollNetDirect (Simple)*/ { 0.0 , 0.0 , 5.7 }, /* CollNetChain (Simple)*/ { 0.0 , 0.0 , 5.7 }, /* NVLS */ { 0 , 0 , 0 }, /* NVLS Tree */ { 0 , 0 , 0 } },
2022-03-31 17:09:21 -07:00
/* NET */
2023-06-21 20:54:24 -07:00
{ /* Tree (LL/LL128/Simple)*/ { 27.9 , 27.9 , 15.8 }, /* Ring (LL/LL128/Simple)*/ { 12.1 , 12.1 , 68.8 }, /* CollNetDirect (Simple)*/ { 0.0 , 0.0 , 15.8 }, /* CollNetChain (Simple)*/ { 0.0 , 0.0 , 15.8 }, /* NVLS */ { 0 , 0 , 0 }, /* NVLS Tree */ { 0 , 0 , 0 } },
2022-03-31 17:09:21 -07:00
},
. bwRatio = {
/* 2 nodes */
2023-06-21 20:54:24 -07:00
{ /* Tree (LL/LL128/Simple)*/ { 0.07 , 1.00 , 0.99 }, /* Ring (LL/LL128/Simple)*/ { 0.08 , 1.00 , 1.00 }, /* CollNetDirect (Simple)*/ { 0.00 , 0.00 , 1.00 }, /* CollNetChain (Simple)*/ { 0.00 , 0.00 , 1.00 }, /* NVLS */ { 0 , 0 , 0 }, /* NVLS Tree */ { 0 , 0 , 0 } },
2022-03-31 17:09:21 -07:00
/* more than 2 nodes */
2023-06-21 20:54:24 -07:00
{ /* Tree (LL/LL128/Simple)*/ { 0.07 , 1.00 , 0.42 }, /* Ring (LL/LL128/Simple)*/ { 0.08 , 1.00 , 1.00 }, /* CollNetDirect (Simple)*/ { 0.00 , 0.00 , 1.00 }, /* CollNetChain (Simple)*/ { 0.00 , 0.00 , 1.00 }, /* NVLS */ { 0 , 0 , 0 }, /* NVLS Tree */ { 0 , 0 , 0 } },
2022-03-31 17:09:21 -07:00
},
. treeCorrectionFactor = {
{ 0.1 , 0.4 , 0.3 , 0.3 , 0.2 , 0.4 , 0.5 , 0.1 , 0.1 , 0.6 , 0.7 , 0.7 , 0.8 , 1.0 , 0.9 , 0.7 , 0.6 , 0.5 , 0.4 , 0.3 , 0.2 , 0.2 , 0.2 , 0.2 , 0.2 , 0.2 , 0.2 , },
{ 0.1 , 0.4 , 0.3 , 0.3 , 0.2 , 0.4 , 0.5 , 0.1 , 0.1 , 0.6 , 0.7 , 0.7 , 0.8 , 1.0 , 0.9 , 0.7 , 0.6 , 0.5 , 0.4 , 0.3 , 0.2 , 0.2 , 0.2 , 0.2 , 0.2 , 0.2 , 0.2 , },
{ 1.0 , 0.1 , 0.1 , 0.1 , 0.1 , 0.2 , 0.3 , 0.5 , 0.1 , 0.6 , 0.9 , 0.8 , 0.7 , 0.9 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 0.7 , 0.9 , 0.9 , 1.0 , 1.0 , 1.0 , },
},
. ringCorrectionFactor = {
{ 0.1 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 0.4 , 1.0 , 1.0 , 1.0 , 1.0 , 0.7 , 0.6 , 0.5 , 0.4 , 0.3 , 0.2 , 0.2 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , },
{ 0.1 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 0.4 , 1.0 , 1.0 , 1.0 , 1.0 , 0.7 , 0.6 , 0.5 , 0.4 , 0.3 , 0.2 , 0.2 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , },
{ 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 1.0 , 0.2 , 0.2 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.2 , 0.4 , 0.5 , 0.6 , 0.9 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , },
},
};
2022-04-04 10:19:57 -07:00
static struct tuningModel tuning_model_3 {
. hwLat = {
/* NVLINK */
2023-06-21 20:54:24 -07:00
{ /* Tree (LL/LL128/Simple)*/ { 0.8 , 0.0 , 2.5 }, /* Ring (LL/LL128/Simple)*/ { 0.8 , 0.0 , 3.6 }, /* CollNetDirect (Simple)*/ { 0.0 , 0.0 , 0.8 }, /* CollNetChain (Simple)*/ { 0.0 , 0.0 , 0.0 }, /* NVLS */ { 0 , 0 , 0 }, /* NVLS Tree */ { 0 , 0 , 0 } },
2022-04-04 10:19:57 -07:00
/* PCI */
2023-06-21 20:54:24 -07:00
{ /* Tree (LL/LL128/Simple)*/ { 2.2 , 2.2 , 5.7 }, /* Ring (LL/LL128/Simple)*/ { 2.2 , 2.2 , 5.7 }, /* CollNetDirect (Simple)*/ { 0.0 , 0.0 , 5.7 }, /* CollNetChain (Simple)*/ { 0.0 , 0.0 , 5.7 }, /* NVLS */ { 0 , 0 , 0 }, /* NVLS Tree */ { 0 , 0 , 0 } },
2022-04-04 10:19:57 -07:00
/* NET */
2023-06-21 20:54:24 -07:00
{ /* Tree (LL/LL128/Simple)*/ { 12.5 , 0.0 , 22.4 }, /* Ring (LL/LL128/Simple)*/ { 9.5 , 0.0 , 19.8 }, /* CollNetDirect (Simple)*/ { 0.0 , 0.0 , 12.5 }, /* CollNetChain (Simple)*/ { 0.0 , 0.0 , 0.0 }, /* NVLS */ { 0 , 0 , 0 }, /* NVLS Tree */ { 0 , 0 , 0 } },
2022-04-04 10:19:57 -07:00
},
. bwRatio = {
/* 2 nodes */
2023-06-21 20:54:24 -07:00
{ /* Tree (LL/LL128/Simple)*/ { 0.20 , 0.00 , 1.75 }, /* Ring (LL/LL128/Simple)*/ { 0.20 , 0.00 , 1.00 }, /* CollNetDirect (Simple)*/ { 0.00 , 0.00 , 1.00 }, /* CollNetChain (Simple)*/ { 0.00 , 0.00 , 1.00 }, /* NVLS */ { 0 , 0 , 0 }, /* NVLS Tree */ { 0 , 0 , 0 } },
2022-04-04 10:19:57 -07:00
/* more than 2 nodes */
2023-06-21 20:54:24 -07:00
{ /* Tree (LL/LL128/Simple)*/ { 0.20 , 0.00 , 0.96 }, /* Ring (LL/LL128/Simple)*/ { 0.20 , 0.00 , 1.00 }, /* CollNetDirect (Simple)*/ { 0.00 , 0.00 , 1.00 }, /* CollNetChain (Simple)*/ { 0.00 , 0.00 , 1.00 }, /* NVLS */ { 0 , 0 , 0 }, /* NVLS Tree */ { 0 , 0 , 0 } },
2022-04-04 10:19:57 -07:00
},
. treeCorrectionFactor = {
2022-11-04 22:54:29 +00:00
{ 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 1.0 , 1.0 , 0.2 , 1.0 , 0.9 , 1.0 , 0.6 , 0.4 , 0.6 , 0.4 , 0.3 , 0.3 , 0.3 , 0.3 , 0.3 , 0.2 , 0.2 , 0.2 , 0.2 , 0.2 , 0.2 , },
{ 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , },
{ 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 0.1 , 0.1 , 0.1 , 0.2 , 1.0 , 0.8 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 0.8 , 0.7 , 0.8 , 0.9 , 0.7 , 0.7 , },
2022-04-04 10:19:57 -07:00
},
. ringCorrectionFactor = {
2022-11-04 22:54:29 +00:00
{ 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.3 , 0.1 , 0.2 , 0.1 , 0.4 , 0.4 , 0.2 , 0.2 , 0.3 , 0.7 , 0.5 , 0.4 , 0.3 , 0.3 , 0.3 , 0.3 , 0.2 , 0.2 , 0.2 , 0.2 , 0.2 , 0.2 , },
{ 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , },
{ 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.5 , 1.0 , 0.1 , 0.3 , 0.1 , 0.1 , 0.1 , 0.2 , 0.2 , 0.2 , 0.3 , 0.4 , 0.7 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , },
2022-04-04 10:19:57 -07:00
},
};
2022-04-18 16:04:04 -07:00
static struct tuningModel tuning_model_4 {
. hwLat = {
/* NVLINK */
2023-06-21 20:54:24 -07:00
{ /* Tree (LL/LL128/Simple)*/ { 0.8 , 1.4 , 2.5 }, /* Ring (LL/LL128/Simple)*/ { 0.8 , 2.2 , 3.6 }, /* CollNetDirect (Simple)*/ { 0.8 , 1.4 , 2.5 }, /* CollNetChain (Simple)*/ { 0.8 , 1.4 , 2.5 }, /* NVLS */ { 0 , 0 , 0 }, /* NVLS Tree */ { 0 , 0 , 0 } },
2022-04-18 16:04:04 -07:00
/* PCI */
2023-06-21 20:54:24 -07:00
{ /* Tree (LL/LL128/Simple)*/ { 2.2 , 2.2 , 5.7 }, /* Ring (LL/LL128/Simple)*/ { 2.2 , 2.2 , 5.7 }, /* CollNetDirect (Simple)*/ { 0.0 , 0.0 , 5.7 }, /* CollNetChain (Simple)*/ { 0.0 , 0.0 , 5.7 }, /* NVLS */ { 0 , 0 , 0 }, /* NVLS Tree */ { 0 , 0 , 0 } },
2022-04-18 16:04:04 -07:00
/* NET */
2023-06-21 20:54:24 -07:00
{ /* Tree (LL/LL128/Simple)*/ { 32.2 , 34.4 , 47.6 }, /* Ring (LL/LL128/Simple)*/ { 35.4 , 87.8 , 209.2 }, /* CollNetDirect (Simple)*/ { 0.0 , 0.0 , 47.6 }, /* CollNetChain (Simple)*/ { 0.0 , 0.0 , 47.6 }, /* NVLS */ { 0 , 0 , 0 }, /* NVLS Tree */ { 0 , 0 , 0 } },
2022-04-18 16:04:04 -07:00
},
. bwRatio = {
/* 2 nodes */
2023-06-21 20:54:24 -07:00
{ /* Tree (LL/LL128/Simple)*/ { 0.16 , 1.09 , 1.61 }, /* Ring (LL/LL128/Simple)*/ { 0.15 , 0.41 , 1.00 }, /* CollNetDirect (Simple)*/ { 0.00 , 0.00 , 1.00 }, /* CollNetChain (Simple)*/ { 0.00 , 0.00 , 1.00 }, /* NVLS */ { 0 , 0 , 0 }, /* NVLS Tree */ { 0 , 0 , 0 } },
2022-04-18 16:04:04 -07:00
/* more than 2 nodes */
2023-06-21 20:54:24 -07:00
{ /* Tree (LL/LL128/Simple)*/ { 0.16 , 1.09 , 1.08 }, /* Ring (LL/LL128/Simple)*/ { 0.15 , 0.41 , 1.00 }, /* CollNetDirect (Simple)*/ { 0.00 , 0.00 , 1.00 }, /* CollNetChain (Simple)*/ { 0.00 , 0.00 , 1.00 }, /* NVLS */ { 0 , 0 , 0 }, /* NVLS Tree */ { 0 , 0 , 0 } },
2022-04-18 16:04:04 -07:00
},
. treeCorrectionFactor = {
2022-09-27 09:39:09 -07:00
{ 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 1.0 , 0.1 , 0.1 , 0.2 , 0.4 , 0.6 , 0.5 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , },
{ 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.2 , 0.1 , 0.1 , 0.2 , 1.0 , 0.5 , 0.2 , 0.2 , 0.2 , 0.2 , 0.2 , 0.2 , 0.2 , 0.2 , 0.2 , 0.2 , 0.2 , 0.2 , },
{ 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 0.8 , 0.4 , 0.3 , 0.3 , 0.1 , 0.1 , 1.0 , 1.0 , 0.7 , 0.5 , 0.6 , 0.5 , 0.6 , 0.6 , 0.5 , 0.6 , 0.6 , 0.6 , 0.7 , },
2022-04-18 16:04:04 -07:00
},
. ringCorrectionFactor = {
2022-09-27 09:39:09 -07:00
{ 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.2 , 0.2 , 0.1 , 0.3 , 0.1 , 0.1 , 0.1 , 0.2 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , },
{ 0.4 , 0.5 , 0.5 , 0.4 , 0.4 , 0.4 , 0.4 , 0.2 , 0.2 , 0.1 , 0.3 , 1.0 , 1.0 , 0.7 , 0.8 , 0.5 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 0.9 , 0.8 , 0.5 , 0.4 , 0.3 , 0.3 , },
{ 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 1.0 , 1.0 , 0.8 , 0.5 , 0.1 , 0.7 , 0.2 , 0.4 , 0.4 , 0.6 , 0.7 , 0.9 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , },
2022-04-18 16:04:04 -07:00
},
};
2024-01-16 13:44:32 -05:00
static struct tuningModel tuning_model_5 {
. hwLat = {
/* NVLINK */
{ /* Tree (LL/LL128/Simple)*/ { 0.8 , 0.0 , 2.5 }, /* Ring (LL/LL128/Simple)*/ { 0.8 , 0.0 , 3.6 }, /* CollNetDirect (Simple)*/ { 0.0 , 0.0 , 0.8 }, /* CollNetChain (Simple)*/ { 0.0 , 0.0 , 0.0 }, /* NVLS */ { 0 , 0 , 0 }, /* NVLS Tree */ { 0 , 0 , 0 } },
/* PCI */
{ /* Tree (LL/LL128/Simple)*/ { 2.2 , 2.2 , 5.7 }, /* Ring (LL/LL128/Simple)*/ { 2.2 , 2.2 , 5.7 }, /* CollNetDirect (Simple)*/ { 0.0 , 0.0 , 5.7 }, /* CollNetChain (Simple)*/ { 0.0 , 0.0 , 5.7 }, /* NVLS */ { 0 , 0 , 0 }, /* NVLS Tree */ { 0 , 0 , 0 } },
/* NET */
{ /* Tree (LL/LL128/Simple)*/ { 12.5 , 0.0 , 22.4 }, /* Ring (LL/LL128/Simple)*/ { 9.5 , 0.0 , 19.8 }, /* CollNetDirect (Simple)*/ { 0.0 , 0.0 , 12.5 }, /* CollNetChain (Simple)*/ { 0.0 , 0.0 , 0.0 }, /* NVLS */ { 0 , 0 , 0 }, /* NVLS Tree */ { 0 , 0 , 0 } },
},
. bwRatio = {
/* 2 nodes */
{ /* Tree (LL/LL128/Simple)*/ { 0.41 , 0.00 , 1.00 }, /* Ring (LL/LL128/Simple)*/ { 0.41 , 0.00 , 1.00 }, /* CollNetDirect (Simple)*/ { 0.00 , 0.00 , 1.00 }, /* CollNetChain (Simple)*/ { 0.00 , 0.00 , 1.00 }, /* NVLS */ { 0 , 0 , 0 }, /* NVLS Tree */ { 0 , 0 , 0 } },
/* more than 2 nodes */
{ /* Tree (LL/LL128/Simple)*/ { 0.41 , 0.00 , 0.86 }, /* Ring (LL/LL128/Simple)*/ { 0.41 , 0.00 , 1.00 }, /* CollNetDirect (Simple)*/ { 0.00 , 0.00 , 1.00 }, /* CollNetChain (Simple)*/ { 0.00 , 0.00 , 1.00 }, /* NVLS */ { 0 , 0 , 0 }, /* NVLS Tree */ { 0 , 0 , 0 } },
},
. treeCorrectionFactor = {
{ 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 1.0 , 1.0 , 0.8 , 0.1 , 0.4 , 0.5 , 1.0 , 0.6 , 0.4 , 0.6 , 0.1 , 0.3 , 0.4 , 0.4 , 0.3 , 0.2 , 0.2 , 0.2 , 0.2 , 0.2 , 0.2 , 0.2 , },
{ 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , },
{ 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 1.0 , 1.0 , 1.0 , 0.4 , 1.0 , 1.0 , 1.0 , 0.2 , 0.7 , 1.0 , 1.0 , 1.0 , 0.8 , 0.7 , 0.7 , 0.8 , 0.8 , 0.8 , 0.9 , },
},
. ringCorrectionFactor = {
{ 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 1.0 , 0.1 , 0.2 , 0.2 , 0.1 , 0.5 , 0.8 , 1.0 , 0.2 , 0.4 , 0.5 , 0.4 , 0.4 , 0.3 , 0.2 , 0.2 , 0.2 , 0.2 , 0.2 , 0.2 , },
{ 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , },
{ 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 0.7 , 0.1 , 0.1 , 0.1 , 0.1 , 0.1 , 1.0 , 1.0 , 1.0 , 0.9 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , },
},
};
2022-03-31 17:09:21 -07:00
static struct tuningModel rcclTuningModel [] = {
tuning_model_0 ,
tuning_model_1 ,
tuning_model_2 ,
2022-04-04 10:19:57 -07:00
tuning_model_3 ,
2022-04-18 16:04:04 -07:00
tuning_model_4 ,
2024-01-16 13:44:32 -05:00
tuning_model_5 ,
2019-11-19 14:57:39 -08:00
};
2022-09-27 02:31:13 -07:00
/* Array indexes used below */
#define VOLTA_COMPCAP_IDX 0
#define AMPERE_COMPCAP_IDX 1
#define HOPPER_COMPCAP_IDX 2
2021-07-08 14:12:04 -07:00
// LL128 max BW per channel
2022-09-27 02:31:13 -07:00
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 }
};
2023-06-13 00:19:57 -07:00
static const double perChMaxRingLL128Bws [ 3 ][ 3 ] = {
/* Volta (N1/N2/N4) */ { 20.0 , 20.0 , 20.0 },
/* Ampere (N1/N2/N4) */ { 20.0 , 20.0 , 20.0 },
/* Hopper (N1/N2/N4) */ { 36.7 , 36.7 , 36.7 },
};
static const double perChMaxTreeLL128Bws [ 3 ][ 3 ] = {
/* Volta (N1/N2/N4) */ { 20.0 , 20.0 , 20.0 },
/* Ampere (N1/N2/N4) */ { 20.0 , 20.0 , 20.0 },
/* Hopper (N1/N2/N4) */ { 36.7 , 36.7 , 29.0 },
};
2022-09-27 02:31:13 -07:00
static const double perChMaxTreeBws [ 3 ][ 3 ] = {
2023-06-13 00:19:57 -07:00
/* Volta (N1/N2/N4) */ { 26.5 , 18.5 , 10.0 },
2022-09-27 02:31:13 -07:00
/* Ampere (N1/N2/N4) */ { 24.0 , 23.6 , 17.8 },
2023-06-13 00:19:57 -07:00
/* Hopper (N1/N2/N4) */ { 38.7 , 41.4 , 36.0 },
2022-09-27 02:31:13 -07:00
};
2019-11-19 14:57:39 -08:00
2023-04-03 05:32:07 -07:00
// Network post overhead in ns (1000 = 1 us)
NCCL_PARAM ( NetOverhead , "NET_OVERHEAD" , - 2 );
static float getNetOverhead ( struct ncclComm * comm ) {
if ( ncclParamNetOverhead () != - 2 ) return ncclParamNetOverhead () * .001 ;
int cpuArch , cpuVendor , cpuModel ;
NCCLCHECK ( ncclTopoCpuType ( comm -> topo , & cpuArch , & cpuVendor , & cpuModel ));
if ( cpuArch == NCCL_TOPO_CPU_ARCH_X86 && cpuVendor == NCCL_TOPO_CPU_VENDOR_INTEL ) return 1.0 ;
if ( cpuArch == NCCL_TOPO_CPU_ARCH_X86 && cpuVendor == NCCL_TOPO_CPU_VENDOR_AMD ) return 2.0 ;
else return 1.0 ;
}
ncclResult_t ncclTopoTuneModel ( struct ncclComm * comm , int minCompCap , int maxCompCap , struct ncclTopoGraph ** graphs ) {
int simpleDefaultThreads = ( graphs [ NCCL_ALGO_RING ] -> bwIntra * graphs [ NCCL_ALGO_RING ] -> nChannels <= PCI_BW ) ? 256 : NCCL_SIMPLE_MAX_NTHREADS ;
2020-01-16 16:02:42 -08:00
comm -> maxThreads [ NCCL_ALGO_RING ][ NCCL_PROTO_SIMPLE ] =
2020-12-01 11:33:47 -05:00
#if defined(__HIP_PLATFORM_HCC__) || defined(__HCC__) || defined(__HIPCC__)
2022-11-03 17:42:38 +00:00
getNthreads ( "NCCL_NTHREADS" , ncclParamNthreads (), 4 * comm -> WarpSize , NCCL_MAX_NTHREADS , simpleDefaultThreads , comm -> WarpSize );
2022-10-20 15:40:03 +00:00
comm -> maxThreads [ NCCL_ALGO_TREE ][ NCCL_PROTO_SIMPLE ] = comm -> maxThreads [ NCCL_ALGO_COLLNET_DIRECT ][ NCCL_PROTO_SIMPLE ] =
2022-11-03 17:42:38 +00:00
getNthreads ( "NCCL_NTHREADS" , ncclParamNthreads (), 4 * comm -> WarpSize , NCCL_MAX_NTHREADS , NCCL_MAX_NTHREADS , comm -> WarpSize );
2022-10-20 15:40:03 +00:00
comm -> maxThreads [ NCCL_ALGO_RING ][ NCCL_PROTO_LL ] = comm -> maxThreads [ NCCL_ALGO_TREE ][ NCCL_PROTO_LL ] = comm -> maxThreads [ NCCL_ALGO_COLLNET_DIRECT ][ NCCL_PROTO_LL ] =
2022-11-03 17:42:38 +00:00
getNthreads ( "NCCL_NTHREADS" , ncclParamNthreads (), 4 * comm -> WarpSize , NCCL_MAX_NTHREADS , NCCL_MAX_NTHREADS , comm -> WarpSize );
2022-10-20 15:40:03 +00:00
comm -> maxThreads [ NCCL_ALGO_RING ][ NCCL_PROTO_LL128 ] = comm -> maxThreads [ NCCL_ALGO_TREE ][ NCCL_PROTO_LL128 ] =
2022-11-03 17:42:38 +00:00
getNthreads ( "NCCL_LL128_NTHREADS" , ncclParamLl128Nthreads (), 4 * comm -> WarpSize , NCCL_LL128_MAX_NTHREADS , NCCL_LL128_MAX_NTHREADS , comm -> WarpSize );
2020-12-01 11:33:47 -05:00
#else
2020-09-04 14:35:05 -07:00
getNthreads ( "NCCL_NTHREADS" , ncclParamNthreads (), 2 * WARP_SIZE , NCCL_SIMPLE_MAX_NTHREADS , simpleDefaultThreads );
2021-04-12 16:00:11 -07:00
comm -> maxThreads [ NCCL_ALGO_TREE ][ NCCL_PROTO_SIMPLE ] =
2020-09-04 14:35:05 -07:00
getNthreads ( "NCCL_NTHREADS" , ncclParamNthreads (), 2 * WARP_SIZE , NCCL_SIMPLE_MAX_NTHREADS , NCCL_SIMPLE_MAX_NTHREADS );
2022-08-18 02:53:17 -07:00
comm -> maxThreads [ NCCL_ALGO_COLLNET_DIRECT ][ NCCL_PROTO_SIMPLE ] =
2023-02-27 02:48:21 -08:00
comm -> maxThreads [ NCCL_ALGO_COLLNET_CHAIN ][ NCCL_PROTO_SIMPLE ] =
2023-04-03 05:32:07 -07:00
comm -> maxThreads [ NCCL_ALGO_NVLS ][ NCCL_PROTO_SIMPLE ] =
comm -> maxThreads [ NCCL_ALGO_NVLS_TREE ][ NCCL_PROTO_SIMPLE ] = NCCL_MAX_NTHREADS ;
2022-08-18 02:53:17 -07:00
comm -> maxThreads [ NCCL_ALGO_RING ][ NCCL_PROTO_LL ] = comm -> maxThreads [ NCCL_ALGO_TREE ][ NCCL_PROTO_LL ] =
2020-09-04 14:35:05 -07:00
getNthreads ( "NCCL_NTHREADS" , ncclParamNthreads (), 2 * WARP_SIZE , NCCL_LL_MAX_NTHREADS , NCCL_LL_MAX_NTHREADS );
2022-08-18 02:53:17 -07:00
comm -> maxThreads [ NCCL_ALGO_RING ][ NCCL_PROTO_LL128 ] = comm -> maxThreads [ NCCL_ALGO_TREE ][ NCCL_PROTO_LL128 ] =
2020-01-16 16:02:42 -08:00
getNthreads ( "NCCL_LL128_NTHREADS" , ncclParamLl128Nthreads (), NCCL_LL128_MAX_NTHREADS / 4 , NCCL_LL128_MAX_NTHREADS , NCCL_LL128_MAX_NTHREADS );
2022-10-20 15:40:03 +00:00
#endif
2019-11-19 14:57:39 -08:00
2020-09-04 14:35:05 -07:00
int nNodes = comm -> nNodes ;
int nRanks = comm -> nRanks ;
if ( nRanks <= 1 ) return ncclSuccess ;
2019-11-19 14:57:39 -08:00
2023-02-27 02:48:21 -08:00
int compCapIndex = minCompCap >= 90 ? HOPPER_COMPCAP_IDX : minCompCap >= 80 ? AMPERE_COMPCAP_IDX : VOLTA_COMPCAP_IDX ;
2020-09-04 14:35:05 -07:00
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
2022-09-27 02:31:13 -07:00
int index1 = nNodes == 1 ? compCapIndex : cpuVendor == NCCL_TOPO_CPU_VENDOR_AMD ? 1 : 0 ;
2020-09-04 14:35:05 -07:00
double llMaxBw = llMaxBws [ index1 ][ index2 ];
2022-09-27 02:31:13 -07:00
double perChMaxTreeBw = perChMaxTreeBws [ compCapIndex ][ index2 ];
2023-06-13 00:19:57 -07:00
double perChMaxRingLL128Bw = perChMaxRingLL128Bws [ compCapIndex ][ index2 ];
double perChMaxTreeLL128Bw = perChMaxTreeLL128Bws [ compCapIndex ][ index2 ];
2021-07-08 14:12:04 -07:00
// De-penalize Tree/Simple latency on Power systems to favor Tree than Ring
2022-03-31 17:09:21 -07:00
//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];
2020-09-04 14:35:05 -07:00
float ppn = ( float ) nRanks / nNodes ; // if ppn < 2, then we are sending/receiving at the same GPU through the NIC, apply some bw discount
2020-01-16 16:02:42 -08:00
int intraHw [ NCCL_NUM_ALGORITHMS ], hw [ NCCL_NUM_ALGORITHMS ];
for ( int a = 0 ; a < NCCL_NUM_ALGORITHMS ; a ++ ) intraHw [ a ] = graphs [ a ] -> typeIntra == LINK_NVL ? NCCL_HW_NVLINK : NCCL_HW_PCI ;
2020-09-04 14:35:05 -07:00
for ( int a = 0 ; a < NCCL_NUM_ALGORITHMS ; a ++ ) hw [ a ] = nNodes == 1 ? intraHw [ a ] : NCCL_HW_NET ;
2019-11-19 14:57:39 -08:00
for ( int coll = 0 ; coll < NCCL_NUM_FUNCTIONS ; coll ++ ) {
2020-09-04 14:35:05 -07:00
int nsteps = coll == ncclFuncAllReduce ? 2 * ( nRanks - 1 ) :
coll == ncclFuncReduceScatter || coll == ncclFuncAllGather ? nRanks - 1 :
nRanks ;
2022-01-07 06:39:55 -08:00
int nInterSteps = coll == ncclFuncAllReduce ? ( nNodes > 1 ? 2 * nNodes : 0 ) :
2020-09-04 14:35:05 -07:00
coll == ncclFuncReduceScatter || coll == ncclFuncAllGather ? nNodes - 1 :
nNodes ;
2019-11-19 14:57:39 -08:00
for ( int a = 0 ; a < NCCL_NUM_ALGORITHMS ; a ++ ) {
2023-02-27 02:48:21 -08:00
if ( coll == ncclFuncBroadcast && a != NCCL_ALGO_RING ) continue ;
if ( coll == ncclFuncReduce && a != NCCL_ALGO_RING ) continue ;
2023-09-26 05:47:28 -07:00
if ( coll == ncclFuncReduceScatter && a != NCCL_ALGO_RING && a != NCCL_ALGO_NVLS ) continue ;
if ( coll == ncclFuncAllGather && a != NCCL_ALGO_RING && a != NCCL_ALGO_NVLS ) continue ;
2019-11-19 14:57:39 -08:00
for ( int p = 0 ; p < NCCL_NUM_PROTOCOLS ; p ++ ) {
2024-01-26 09:05:53 -05:00
if ( a == NCCL_ALGO_TREE && p == NCCL_PROTO_SIMPLE && IsArchMatch ( comm -> topo -> nodes [ GPU ]. nodes [ 0 ]. gpu . gcn , "gfx94" ) && comm -> topo -> nodes [ GPU ]. count == comm -> topo -> nRanks ) continue ;
2023-04-03 05:32:07 -07:00
if (( a == NCCL_ALGO_NVLS || a == NCCL_ALGO_NVLS_TREE ) && p != NCCL_PROTO_SIMPLE ) continue ;
2022-08-18 02:53:17 -07:00
int collnet = ( a == NCCL_ALGO_COLLNET_DIRECT || a == NCCL_ALGO_COLLNET_CHAIN ) ? 1 : 0 ;
float bw = nNodes <= 2 || collnet ? graphs [ a ] -> bwIntra : graphs [ a ] -> bwInter ;
2022-10-20 15:40:03 +00:00
float busBw = comm -> topo -> baseBw != 0.0 ? comm -> topo -> baseBw : graphs [ a ] -> nChannels * bw ;
2022-11-04 22:54:29 +00:00
//INFO(NCCL_INIT, "algo %s proto %s busBw %f baseBw %f bw %f nChannels %d bwIntra %f bwInter %f", ncclAlgoStr[a], ncclProtoStr[p], busBw, comm->topo->baseBw, bw, graphs[a]->nChannels, graphs[a]->bwIntra, graphs[a]->bwInter);
2019-11-19 14:57:39 -08:00
2023-09-26 05:47:28 -07:00
if ( a == NCCL_ALGO_NVLS ) bw = std :: min ( graphs [ a ] -> bwIntra , graphs [ a ] -> bwInter );
if ( a == NCCL_ALGO_NVLS_TREE ) bw = std :: min ( graphs [ a ] -> bwIntra , nNodes <= 2 ? graphs [ a ] -> bwInter : graphs [ a ] -> bwInter / 2 );
2024-01-24 15:25:33 -08:00
2019-11-19 14:57:39 -08:00
// Various model refinements
2020-12-01 11:33:47 -05:00
#if defined(__HIP_PLATFORM_HCC__) || defined(__HCC__) || defined(__HIPCC__)
2022-03-31 17:09:21 -07:00
if ( nNodes <= 2 )
busBw *= rcclTuningModel [ comm -> topo -> tuning ]. bwRatio [ 0 ][ a ][ p ];
else
busBw *= rcclTuningModel [ comm -> topo -> tuning ]. bwRatio [ 1 ][ a ][ p ];
2020-12-01 11:33:47 -05:00
#else
2020-09-04 14:35:05 -07:00
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 )); }
2023-06-13 00:19:57 -07:00
if ( a == NCCL_ALGO_RING && p == NCCL_PROTO_LL128 ) busBw = std :: min ( busBw * ( ppn < 2 ? 0.7 : 0.92 /*120.0/128.0*/ ), graphs [ a ] -> nChannels * perChMaxRingLL128Bw );
2020-09-04 14:35:05 -07:00
if ( a == NCCL_ALGO_TREE ) busBw = std :: min ( busBw * .92 , graphs [ a ] -> nChannels * perChMaxTreeBw );
if ( a == NCCL_ALGO_TREE && p == NCCL_PROTO_LL ) busBw = std :: min ( busBw * 1.0 / 3.8 , llMaxBw );
2023-06-13 00:19:57 -07:00
if ( a == NCCL_ALGO_TREE && p == NCCL_PROTO_LL128 ) busBw = std :: min ( busBw * ( nNodes == 1 ? 7.0 / 9.0 : 120.0 / 128.0 ), graphs [ a ] -> nChannels * perChMaxTreeLL128Bw );
if ( a == NCCL_ALGO_TREE && graphs [ a ] -> pattern == NCCL_TOPO_PATTERN_TREE ) busBw *= .85 ;
2022-08-18 02:53:17 -07:00
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
2022-09-27 02:31:13 -07:00
if ( a == NCCL_ALGO_COLLNET_DIRECT && p == NCCL_PROTO_SIMPLE ) {
2022-08-18 02:53:17 -07:00
// 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
2022-09-27 02:31:13 -07:00
factor -= ( factor - 1 ) / 2 ;
2022-08-18 02:53:17 -07:00
busBw /= factor ;
2022-09-27 02:31:13 -07:00
}
2021-07-28 13:27:06 -07:00
#endif
2023-04-03 05:32:07 -07:00
if ( a == NCCL_ALGO_COLLNET_DIRECT && p == NCCL_PROTO_SIMPLE && minCompCap >= 90 ) busBw *= .85 ;
2019-11-19 14:57:39 -08:00
// Convert bus BW to algorithm BW
2023-02-27 02:48:21 -08:00
float ratio ;
if ( a == NCCL_ALGO_RING ) ratio = ( 1.0 * nRanks ) / nsteps ;
2023-09-26 05:47:28 -07:00
else if ( a == NCCL_ALGO_NVLS || a == NCCL_ALGO_NVLS_TREE ) ratio = 5.0 / 6.0 ;
2023-02-27 02:48:21 -08:00
else ratio = .5 ;
2019-11-19 14:57:39 -08:00
comm -> bandwidths [ coll ][ a ][ p ] = busBw * ratio ;
2023-09-26 05:47:28 -07:00
/* Ring bandwidth backup */
if ( a == NCCL_ALGO_RING )
comm -> ringbdw [ coll ][ p ] = comm -> bandwidths [ coll ][ NCCL_ALGO_RING ][ p ];
2019-11-19 14:57:39 -08:00
comm -> latencies [ coll ][ a ][ p ] = baseLat [ a ][ p ];
2022-03-31 17:09:21 -07:00
float intraLat = rcclTuningModel [ comm -> topo -> tuning ]. hwLat [ intraHw [ a ]][ a ][ p ];
2022-10-20 15:40:03 +00:00
float interLat = graphs [ a ] -> latencyInter ? graphs [ a ] -> latencyInter : rcclTuningModel [ comm -> topo -> tuning ]. hwLat [ NCCL_HW_NET ][ a ][ p ];
2021-09-13 08:39:01 -07:00
//if (nNodes > 1 && p == NCCL_PROTO_LL) intraLat *= 1.8;
2023-04-03 05:32:07 -07:00
if ( p == NCCL_PROTO_SIMPLE ) interLat += graphs [ a ] -> latencyInter ;
2022-01-07 06:39:55 -08:00
2019-11-19 14:57:39 -08:00
if ( a == NCCL_ALGO_RING ) {
2022-03-31 17:09:21 -07:00
float lat = rcclTuningModel [ comm -> topo -> tuning ]. hwLat [ hw [ a ]][ a ][ p ];
2020-09-04 14:35:05 -07:00
if (( coll == ncclFuncReduce || coll == ncclFuncBroadcast )) {
2023-04-03 05:32:07 -07:00
if ( graphs [ a ] -> sameChannels ) {
2019-11-19 14:57:39 -08:00
comm -> latencies [ coll ][ a ][ p ] += lat ;
} else {
2022-03-31 17:09:21 -07:00
if ( p == NCCL_PROTO_SIMPLE ) lat = rcclTuningModel [ comm -> topo -> tuning ]. hwLat [ hw [ a ]][ NCCL_ALGO_TREE ][ p ]; // Add some chunk latency, waiting for proper chunk modeling
2019-11-19 14:57:39 -08:00
comm -> latencies [ coll ][ a ][ p ] += nsteps * lat ;
}
} else {
2023-04-03 05:32:07 -07:00
// Inter-node rings still have to launch nsteps * net overhead.
float netOverhead = 0.0 ;
if ( nNodes > 1 ) {
netOverhead = getNetOverhead ( comm );
if ( p == NCCL_PROTO_SIMPLE ) netOverhead *= 3 ;
}
intraLat = std :: max ( intraLat , netOverhead );
2020-05-12 14:40:18 -07:00
comm -> latencies [ coll ][ a ][ p ] += ( nsteps - nInterSteps ) * intraLat + nInterSteps * interLat ;
2019-11-19 14:57:39 -08:00
}
2020-01-16 16:02:42 -08:00
} else if ( a == NCCL_ALGO_TREE ) {
2019-11-19 14:57:39 -08:00
comm -> latencies [ coll ][ a ][ p ] +=
2020-09-04 14:35:05 -07:00
2 * (( nRanks / nNodes - 1 ) * intraLat + log2i ( nNodes ) * interLat );
2022-08-18 02:53:17 -07:00
} else if ( a == NCCL_ALGO_COLLNET_DIRECT ) {
2020-01-16 16:02:42 -08:00
comm -> latencies [ coll ][ a ][ p ] +=
2023-09-26 05:47:28 -07:00
2 * ( std :: min ( 1 , ( nRanks / nNodes - 1 )) * intraLat + ( nRanks / nNodes - 1 ) * 0.4 ) + interLat ; // Add 0.4 us arity serialization latency
2022-08-18 02:53:17 -07:00
} else if ( a == NCCL_ALGO_COLLNET_CHAIN ) {
2023-04-03 05:32:07 -07:00
comm -> latencies [ coll ][ a ][ p ] += 2 * ( nRanks / nNodes - 1 ) * intraLat + interLat ;
} else if ( a == NCCL_ALGO_NVLS ) {
2023-06-21 20:54:24 -07:00
if ( nNodes > 1 ) comm -> latencies [ coll ][ a ][ p ] += rcclTuningModel [ comm -> topo -> tuning ]. hwLat [ NCCL_HW_NET ][ a ][ p ];
2023-04-03 05:32:07 -07:00
} else if ( a == NCCL_ALGO_NVLS_TREE ) {
2023-06-21 20:54:24 -07:00
comm -> latencies [ coll ][ a ][ p ] += 2 * ( nNodes - 1 ) * rcclTuningModel [ comm -> topo -> tuning ]. hwLat [ NCCL_HW_NET ][ a ][ p ];
2019-11-19 14:57:39 -08:00
}
}
}
}
// Protocols/Algorithms enable/disable, and user overrides.
// All are enabled except ll128 which is enabled by default only in certain cases.
int protoEnable [ NCCL_NUM_PROTOCOLS ] = { 1 , 2 , 1 };
2023-04-03 05:32:07 -07:00
int algoEnable [ NCCL_NUM_ALGORITHMS ] = { 1 , 1 , 1 , 1 , 1 , 1 };
2019-11-19 14:57:39 -08:00
2023-09-26 05:47:28 -07:00
const char * protoStr = ncclGetEnv ( "NCCL_PROTO" );
2020-05-12 14:40:18 -07:00
if ( protoStr ) {
INFO ( NCCL_ENV , "NCCL_PROTO set by environment to %s" , protoStr );
NCCLCHECK ( parseList ( protoStr , ncclProtoStr , NCCL_NUM_PROTOCOLS , protoEnable ));
}
2023-09-26 05:47:28 -07:00
const char * algoStr = ncclGetEnv ( "NCCL_ALGO" );
2020-05-12 14:40:18 -07:00
if ( algoStr ) {
INFO ( NCCL_ENV , "NCCL_ALGO set by environment to %s" , algoStr );
NCCLCHECK ( parseList ( algoStr , ncclAlgoStr , NCCL_NUM_ALGORITHMS , algoEnable ));
}
2023-02-27 02:48:21 -08:00
2023-04-03 05:32:07 -07:00
if ( comm -> nNodes == 1 ) algoEnable [ NCCL_ALGO_NVLS_TREE ] = 0 ;
2023-02-27 02:48:21 -08:00
2020-09-04 14:35:05 -07:00
// Disable CollNet if it is not supported
if ( comm -> collNetSupport == 0 ) {
2022-08-18 02:53:17 -07:00
algoEnable [ NCCL_ALGO_COLLNET_DIRECT ] = 0 ;
algoEnable [ NCCL_ALGO_COLLNET_CHAIN ] = 0 ;
2023-04-03 05:32:07 -07:00
if ( comm -> nNodes > 1 ) algoEnable [ NCCL_ALGO_NVLS ] = 0 ;
2020-09-04 14:35:05 -07:00
// If user has hard set NCCL_ALGO=COLLNET, ignore it
2023-04-03 05:32:07 -07:00
if ( algoEnable [ NCCL_ALGO_RING ] == 0 && algoEnable [ NCCL_ALGO_TREE ] == 0 &&
algoEnable [ NCCL_ALGO_NVLS ] == 0 && algoEnable [ NCCL_ALGO_NVLS_TREE ] == 0 ) {
2020-09-04 14:35:05 -07:00
algoEnable [ NCCL_ALGO_RING ] = algoEnable [ NCCL_ALGO_TREE ] = 1 ;
if ( comm -> rank == 0 ) WARN ( "CollNet is not supported or fails to initialize, ignoring NCCL_ALGO=COLLNET" );
}
2022-08-18 02:53:17 -07:00
} else {
// Disable CollNet+Direct if not on an NVSwitch system
int nvsCount = 0 ;
NCCLCHECK ( ncclTopoGetNvsCount ( comm -> topo , & nvsCount ));
if ( nvsCount == 0 ) algoEnable [ NCCL_ALGO_COLLNET_DIRECT ] = 0 ;
2020-09-04 14:35:05 -07:00
}
2019-11-19 14:57:39 -08:00
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 ++ ) {
2023-08-04 07:53:07 -07:00
// Disable LL protocol on gfx11xx
2023-08-21 16:28:39 -07:00
int pEnable = protoEnable [ p ];
2019-11-19 14:57:39 -08:00
if ( pEnable == 2 && p == NCCL_PROTO_LL128 ) {
2022-09-08 14:45:27 -07:00
#if defined(__HIP_PLATFORM_HCC__) || defined(__HCC__) || defined(__HIPCC__)
2023-07-27 20:25:18 -07:00
#if defined(ENABLE_LL128)
2022-09-08 14:45:27 -07:00
// Enable LL128 by default only on gfx90a with available tuning table
pEnable = ( graphs [ a ] -> typeInter <= PATH_PXB ) && graphs [ a ] -> typeIntra <= PATH_NVL &&
2023-09-12 15:34:40 -04:00
( IsArchMatch ( comm -> topo -> nodes [ GPU ]. nodes [ 0 ]. gpu . gcn , "gfx90a" ) && comm -> topo -> ll128Enabled ) ? 1 : 0 ;
2023-07-27 20:25:18 -07:00
#else
pEnable = 0 ;
#endif
2022-09-08 14:45:27 -07:00
#else
2022-09-27 02:31:13 -07:00
// Enable LL128 by default only on Volta/Ampere/Hopper+NVLink. Other cases are not tested and may cause silent data corruption.
2022-10-25 00:55:55 -07:00
pEnable = 1 ;
2023-02-27 02:48:21 -08:00
pEnable &= ( graphs [ a ] -> typeInter <= PATH_PXB || ( minCompCap >= 90 && graphs [ a ] -> typeInter <= PATH_PXN ));
2023-06-13 00:19:57 -07:00
pEnable &= ( graphs [ a ] -> typeIntra <= PATH_NVB );
2022-10-25 00:55:55 -07:00
pEnable &= ( minCompCap == maxCompCap );
switch ( minCompCap ) {
case 70 : pEnable &= 1 ; break ;
case 80 : pEnable &= 1 ; break ;
case 90 : pEnable &= ! ( CUDART_VERSION == 11080 && c == ncclFuncAllReduce && a == NCCL_ALGO_RING && comm -> nRanks == 2 ); break ;
default : pEnable &= 0 ; break ;
}
2022-09-08 14:45:27 -07:00
#endif
2019-11-19 14:57:39 -08:00
}
2020-05-12 14:40:18 -07:00
if ( pEnable == 0 ) comm -> bandwidths [ c ][ a ][ p ] = 0 ;
2023-02-27 02:48:21 -08:00
if ( algoEnable [ a ] == 0 ) comm -> bandwidths [ c ][ a ][ p ] = 0 ;
2019-11-19 14:57:39 -08:00
}
2023-09-26 05:47:28 -07:00
for ( int c = 0 ; c < NCCL_NUM_FUNCTIONS ; c ++ ) {
bool available = false ;
for ( int a = 0 ; a < NCCL_NUM_ALGORITHMS ; a ++ )
for ( int p = 0 ; p < NCCL_NUM_PROTOCOLS ; p ++ )
if ( comm -> bandwidths [ c ][ a ][ p ] != 0 ) {
available = true ;
goto check_avail ;
}
check_avail :
if ( available == false ) {
/* at least set ring algo available */
for ( int p = 0 ; p < NCCL_NUM_PROTOCOLS ; p ++ )
comm -> bandwidths [ c ][ NCCL_ALGO_RING ][ p ] = comm -> ringbdw [ c ][ p ];
}
}
2019-11-19 14:57:39 -08:00
if ( comm -> rank == 0 ) {
char line [ 1024 ];
2023-04-03 05:32:07 -07:00
for ( int block = 0 ; block < 2 ; block ++ ) {
sprintf ( line , " Algorithm |" );
for ( int ba = 0 ; ba < NCCL_NUM_ALGORITHMS / 2 ; ba ++ ) {
int a = block * NCCL_NUM_ALGORITHMS / 2 + ba ;
sprintf ( line + strlen ( line ), " %14s %14s %14s |" , "" , ncclAlgoStr [ a ], "" );
2020-01-16 16:02:42 -08:00
}
2023-04-03 05:32:07 -07:00
INFO ( NCCL_TUNING , "%s" , line );
sprintf ( line , " Protocol |" );
for ( int ba = 0 ; ba < NCCL_NUM_ALGORITHMS / 2 ; ba ++ ) {
for ( int p = 0 ; p < NCCL_NUM_PROTOCOLS ; p ++ ) {
sprintf ( line + strlen ( line ), " %14s |" , ncclProtoStr [ p ]);
}
2019-11-19 14:57:39 -08:00
}
2023-04-03 05:32:07 -07:00
INFO ( NCCL_TUNING , "%s" , line );
sprintf ( line , " Max NThreads |" );
for ( int ba = 0 ; ba < NCCL_NUM_ALGORITHMS / 2 ; ba ++ ) {
int a = block * NCCL_NUM_ALGORITHMS / 2 + ba ;
2019-11-19 14:57:39 -08:00
for ( int p = 0 ; p < NCCL_NUM_PROTOCOLS ; p ++ ) {
2023-04-03 05:32:07 -07:00
sprintf ( line + strlen ( line ), " %14d |" , comm -> maxThreads [ a ][ p ]);
2019-11-19 14:57:39 -08:00
}
}
INFO ( NCCL_TUNING , "%s" , line );
2023-04-03 05:32:07 -07:00
for ( int c = 0 ; c < NCCL_NUM_FUNCTIONS ; c ++ ) {
sprintf ( line , "%13s |" , ncclFuncStr [ c ]);
for ( int ba = 0 ; ba < NCCL_NUM_ALGORITHMS / 2 ; ba ++ ) {
int a = block * NCCL_NUM_ALGORITHMS / 2 + ba ;
for ( int p = 0 ; p < NCCL_NUM_PROTOCOLS ; p ++ ) {
sprintf ( line + strlen ( line ), "%8.1f/%6.1f |" , comm -> latencies [ c ][ a ][ p ], comm -> bandwidths [ c ][ a ][ p ]);
}
}
INFO ( NCCL_TUNING , "%s" , line );
}
2019-11-19 14:57:39 -08:00
}
}
// Set per-thread amount of work before we increase nThreads and nChannels
for ( int a = 0 ; a < NCCL_NUM_ALGORITHMS ; a ++ ) {
comm -> threadThresholds [ a ][ NCCL_PROTO_LL ] = NCCL_LL_THREAD_THRESHOLD ;
comm -> threadThresholds [ a ][ NCCL_PROTO_LL128 ] = NCCL_LL128_THREAD_THRESHOLD ;
comm -> threadThresholds [ a ][ NCCL_PROTO_SIMPLE ] = NCCL_SIMPLE_THREAD_THRESHOLD ;
}
2020-09-04 14:35:05 -07:00
comm -> threadThresholds [ NCCL_ALGO_RING ][ NCCL_PROTO_LL ] *= nRanks ;
2022-10-20 15:40:03 +00:00
comm -> threadThresholds [ NCCL_ALGO_COLLNET_DIRECT ][ NCCL_PROTO_SIMPLE ] = 256 ;
comm -> threadThresholds [ NCCL_ALGO_COLLNET_CHAIN ][ NCCL_PROTO_SIMPLE ] = 256 ;
2019-11-19 14:57:39 -08:00
// Override defaults with user env
2023-09-26 05:47:28 -07:00
const char * str = ncclGetEnv ( "NCCL_THREAD_THRESHOLDS" );
2019-11-19 14:57:39 -08:00
if ( str ) {
2020-05-12 14:40:18 -07:00
INFO ( NCCL_ENV , "NCCL_THREAD_THRESHOLDS set by environment to %s" , str );
2023-02-27 02:48:21 -08:00
ssize_t t [ 2 ][ NCCL_NUM_PROTOCOLS ] = {{ - 2 , - 2 , - 2 }, { - 2 , - 2 , - 2 }};
2019-11-19 14:57:39 -08:00
sscanf ( str , "%ld %ld %ld %ld %ld %ld" , t [ 0 ], t [ 0 ] + 1 , t [ 0 ] + 2 , t [ 1 ], t [ 1 ] + 1 , t [ 1 ] + 2 );
2023-02-27 02:48:21 -08:00
for ( int a = 0 ; a < 2 ; a ++ ) {
2019-11-19 14:57:39 -08:00
for ( int p = 0 ; p < NCCL_NUM_PROTOCOLS ; p ++ ) {
if ( t [ a ][ p ] >= 0 ) comm -> threadThresholds [ a ][ p ] = t [ a ][ p ];
}
}
}
2022-08-18 02:53:17 -07:00
INFO ( NCCL_INIT , "threadThresholds %ld/%ld/%ld | %ld/%ld/%ld | %ld | %ld" ,
2019-11-19 14:57:39 -08:00
comm -> threadThresholds [ NCCL_ALGO_TREE ][ NCCL_PROTO_LL ],
comm -> threadThresholds [ NCCL_ALGO_TREE ][ NCCL_PROTO_LL128 ],
comm -> threadThresholds [ NCCL_ALGO_TREE ][ NCCL_PROTO_SIMPLE ],
comm -> threadThresholds [ NCCL_ALGO_RING ][ NCCL_PROTO_LL ],
comm -> threadThresholds [ NCCL_ALGO_RING ][ NCCL_PROTO_LL128 ],
2020-01-16 16:02:42 -08:00
comm -> threadThresholds [ NCCL_ALGO_RING ][ NCCL_PROTO_SIMPLE ],
2022-08-18 02:53:17 -07:00
comm -> threadThresholds [ NCCL_ALGO_COLLNET_DIRECT ][ NCCL_PROTO_SIMPLE ],
comm -> threadThresholds [ NCCL_ALGO_COLLNET_CHAIN ][ NCCL_PROTO_SIMPLE ]);
2020-01-16 16:02:42 -08:00
return ncclSuccess ;
}
// Trees are not perfectly sticking to the model for medium sizes. Applying a static correction
2020-09-04 14:35:05 -07:00
// factor is not ideal but works quite well. Powers of two, 64 B to 256MB.
static float treeCorrectionFactor [ NCCL_NUM_PROTOCOLS ][ 23 ] = {
{ 1.0 , 1.0 , 1.0 , 1.0 , .9 , .8 , .7 , .7 , .7 , .7 , .6 , .5 , .4 , .4 , .5 , .6 , .7 , .8 , .9 , 1.0 , 1.0 , 1.0 , 1.0 },
2021-07-08 14:12:04 -07:00
{ 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , .9 , .8 , .8 , .8 , .7 , .6 , .6 , .6 , .6 , .6 , .6 , .8 , .9 , .9 , .9 , .9 , 1.0 , 1.0 },
2020-09-04 14:35:05 -07:00
{ .9 , .9 , .9 , .9 , .9 , .9 , .9 , .8 , .7 , .6 , .6 , .5 , .5 , .5 , .5 , .6 , .7 , .8 , .7 , .7 , .8 , .9 , .9 }
2020-01-16 16:02:42 -08:00
};
2023-09-26 05:47:28 -07:00
ncclResult_t ncclTopoGetAlgoTime ( struct ncclInfo * info , int algorithm , int protocol , int numPipeOps , float * time , bool * backup ) {
float bw = info -> comm -> bandwidths [ info -> coll ][ algorithm ][ protocol ];
2020-05-12 14:40:18 -07:00
float lat = info -> comm -> latencies [ info -> coll ][ algorithm ][ protocol ];
2023-09-26 05:47:28 -07:00
if ( backup ) {
* backup = false ;
if ( algorithm == NCCL_ALGO_RING && bw == 0.0f ) {
/* try back up RING algorithm */
bw = info -> comm -> ringbdw [ info -> coll ][ protocol ];
* backup = true ;
}
}
2020-01-16 16:02:42 -08:00
if ( bw == 0 ) {
* time = - 1.0 ; return ncclSuccess ;
}
int logSize = log2i ( info -> nBytes >> 6 );
2020-12-01 11:33:47 -05:00
#if defined(__HIP_PLATFORM_HCC__) || defined(__HCC__) || defined(__HIPCC__)
2021-10-12 08:23:20 -07:00
if ( algorithm == NCCL_ALGO_TREE ) {
2022-03-31 17:09:21 -07:00
if ( logSize < 27 ) bw *= rcclTuningModel [ info -> comm -> topo -> tuning ]. treeCorrectionFactor [ protocol ][ logSize ];
else bw *= rcclTuningModel [ info -> comm -> topo -> tuning ]. treeCorrectionFactor [ protocol ][ 26 ];
2021-10-12 08:23:20 -07:00
}
2022-03-31 17:09:21 -07:00
else if ( algorithm == NCCL_ALGO_RING && info -> comm -> nNodes > 1 ) {
if ( logSize < 27 ) bw *= rcclTuningModel [ info -> comm -> topo -> tuning ]. ringCorrectionFactor [ protocol ][ logSize ];
else bw *= rcclTuningModel [ info -> comm -> topo -> tuning ]. ringCorrectionFactor [ protocol ][ 26 ];
2021-10-12 08:23:20 -07:00
}
2020-12-01 11:33:47 -05:00
#else
2020-09-04 14:35:05 -07:00
if ( algorithm == NCCL_ALGO_TREE && logSize < 23 ) bw *= treeCorrectionFactor [ protocol ][ logSize ];
if ( info -> nChannels != 0 ) bw = bw / info -> comm -> nChannels * info -> nChannels ;
2020-05-12 14:40:18 -07:00
if ( algorithm == NCCL_ALGO_RING && protocol == NCCL_PROTO_SIMPLE && info -> comm -> nNodes > 1
2023-04-03 05:32:07 -07:00
&& info -> coll == ncclFuncAllReduce && info -> nBytes / ( info -> comm -> nChannels * info -> comm -> nRanks ) >= 64 ) {
lat *= info -> comm -> minCompCap < 80 ? 1.9 : 1.4 ; // Plateau effect of ring
2023-02-27 02:48:21 -08:00
}
2022-07-03 20:52:52 -07:00
#endif
2021-07-08 14:12:04 -07:00
// Tree pipelining saves latency in aggregation cases
int latCount = algorithm == NCCL_ALGO_RING ? numPipeOps : DIVUP ( numPipeOps , NCCL_MAX_WORK_ELEMENTS );
* time = lat * latCount + ( info -> nBytes ) / ( 1000 * bw );
2019-11-19 14:57:39 -08:00
return ncclSuccess ;
}