2.24.3-1
Network user buffer support for collectives * Leverage user buffer registration to achieve zero-copy inter-node communications for Ring, NVLS and Collnet Add RAS subsystem * Create a RAS thread keeping track of all NCCL communicators. * Add a ncclras tool contacting the RAS thread and getting a report. Add fp8 support * Add support for e5m2 and e4m3 8-bit floating point operations. * Use Tree/PAT algorithms when possible for better numerical stability. Add NIC fusion * Add a NET API to ask the network plugin to fuse a set of interfaces together. * Fuse multiple NICs under the same PCI switch as a single, larger NIC. Socket connection failure retry * Retry in case of socket connection failure (unreachable host) * Avoid "Software caused connection abort" errors on retries QP connection failure retry * Retry in case of IB QP connection failure during ibv_modify_qp. NET API improvements * Allow plugins to force a flush in case data and completion ordering is not guaranteed. * Indicate when completion is not needed (e.g. for the LL128 protocol), allowing plugins to skip generating a completion. * Allow for full offload of allgather operations when using one GPU per node. NCCL_ALGO/NCCL_PROTO strict enforcement * Extend NCCL_ALGO/NCCL_PROTO syntax to be able to specify ALGO/PROTO filters for each collective operation. * Strictly enforce the ALGO/PROTO filters, no longer fall back on the ring algorithm when the filtering leaves no option and error out instead. Enable CUMEM host allocations * Use cumem functions for host memory allocation by default. Improved profiler plugin API * Avoid dependencies with NCCL includes. * Add information on whether the buffer is registered or not Adjust PAT tuning * Improve transition between PAT and ring at scale. Fix hangs when running with different CPU architectures * Detect when we use a mix of GPU architectures * Ensure Algo/Proto decisions are made based on that unified state. Fix FD leak in UDS * Fix a leak when mapping buffers intra-node with cumem IPCs. Fix crash when mixing buffer registration and graph buffer registration. * Separate local and graph registration to avoid crashes when we free buffers. Fix user buffer registration with dmabuf * Make ncclSend/ncclRecv communication with buffer registration functional on network plugins relying on dmabuf for buffer registration. Fix crash in IB code caused by uninitialized fields. Fix non-blocking ncclSend/ncclRecv * Fix case where ncclSend/ncclRecv would return ncclSuccess in non-blocking mode even though the operation was not enqueued onto the stream. * Issue #1495 Various compiler tweaks and fixes * PR #758 Fix typo in ncclTopoPrintGraph * Issue #1468
This commit is contained in:
@@ -10,6 +10,7 @@
|
||||
#include "nccl.h"
|
||||
#include "nccl_common.h"
|
||||
#include "device.h"
|
||||
#define NCCL_MAX_NET_SIZE (1024*1024*1024L) // Rather than send INT_MAX which is 2G-1, send a power of two.
|
||||
|
||||
// CHUNKSIZE must be a multiple of SLICESIZE
|
||||
#define ALLREDUCE_SLICESTEPS (NCCL_STEPS/4)
|
||||
@@ -23,6 +24,7 @@
|
||||
#define REDUCE_SLICESTEPS 1
|
||||
#define REDUCE_CHUNKSTEPS 1
|
||||
#define NCCL_MAX_SLICE_PER_CHUNK 2 // max value for CHUNKSTEPS/SLICESTEPS, must accord with above
|
||||
#define NCCL_MAX_NET_SIZE (1024*1024*1024L) // Rather than send INT_MAX which is 2G-1, send a power of two.
|
||||
|
||||
const char* ncclFuncToString(ncclFunc_t op);
|
||||
const char* ncclDevRedOpToString(ncclDevRedOp_t op);
|
||||
@@ -34,11 +36,11 @@ inline int ncclTypeSize(ncclDataType_t type) {
|
||||
switch (type) {
|
||||
case ncclInt8:
|
||||
case ncclUint8:
|
||||
case ncclFloat8e4m3:
|
||||
case ncclFloat8e5m2:
|
||||
return 1;
|
||||
case ncclFloat16:
|
||||
#if defined(__CUDA_BF16_TYPES_EXIST__)
|
||||
case ncclBfloat16:
|
||||
#endif
|
||||
return 2;
|
||||
case ncclInt32:
|
||||
case ncclUint32:
|
||||
@@ -67,6 +69,319 @@ struct ncclConnFifo {
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
class RingAlgorithm {
|
||||
protected:
|
||||
int refCount;
|
||||
int nRanks;
|
||||
int nStepsPerLoop;
|
||||
int chunkSteps;
|
||||
int sliceSteps;
|
||||
ssize_t sliceSize;
|
||||
ssize_t loopSize;
|
||||
ssize_t channelSize;
|
||||
uint8_t *sendbuff;
|
||||
uint8_t *recvbuff;
|
||||
void *sendMhandle;
|
||||
void *recvMhandle;
|
||||
void *srecvMhandle;
|
||||
public:
|
||||
// this ring class is used by proxy thread to retrieve the send and recv buffer, size as well as corresponding
|
||||
// mem handle based on the current step of the proxy args. The derived ring algo class is AR, AG, and BC which
|
||||
// would be allocated during enqueue stage and copied to proxy side through shared memory. For each copy, we will
|
||||
// increase the refCount by incRefCount() since the same ring algo object can be referenced multiple times for send
|
||||
// and recv progress. After all steps are done, we decrease the refCount and only delete the ring object when
|
||||
// refCount == 0.
|
||||
virtual void getNextSendAddr(int curStep, uint8_t **sendbuffOut, size_t *sizeOut, void **mhandleOut) = 0;
|
||||
virtual void getNextRecvAddr(int curStep, uint8_t **recvbuffOut, size_t *sizeOut, void **mhandleOut) = 0;
|
||||
int incRefCount() {
|
||||
return __atomic_add_fetch(&refCount, 1, __ATOMIC_RELAXED);
|
||||
}
|
||||
int decRefCount() {
|
||||
return __atomic_sub_fetch(&refCount, 1, __ATOMIC_RELEASE);
|
||||
}
|
||||
RingAlgorithm() { refCount = 0; }
|
||||
virtual ~RingAlgorithm() {};
|
||||
};
|
||||
|
||||
class RingARAlgorithm : public RingAlgorithm {
|
||||
private:
|
||||
int ringIndex;
|
||||
int elemSize;
|
||||
ssize_t chunkSize;
|
||||
int slicePerChunk;
|
||||
public:
|
||||
void getNextSendAddr(int curStep, uint8_t **sendbuffOut, size_t *sizeOut, void **mhandleOut) {
|
||||
int curLoop = curStep / nStepsPerLoop;
|
||||
int curLoopStage = (curStep % nStepsPerLoop) / chunkSteps;
|
||||
int chunkStage = curLoopStage % nRanks;
|
||||
int sliceStage = (curStep % chunkSteps) / sliceSteps;
|
||||
ssize_t elemOffset = curLoop * loopSize;
|
||||
ssize_t remSize = channelSize - elemOffset;
|
||||
ssize_t chunkOffset;
|
||||
ssize_t sliceOffset;
|
||||
ssize_t curSliceSize;
|
||||
ssize_t curChunkSize;
|
||||
ssize_t size;
|
||||
ssize_t nelem;
|
||||
int chunkId;
|
||||
|
||||
if (remSize < loopSize) {
|
||||
curChunkSize = alignUp(divUp(remSize / elemSize, nRanks), 16 / elemSize) * elemSize;
|
||||
} else {
|
||||
curChunkSize = chunkSize;
|
||||
}
|
||||
chunkId = (ringIndex + nRanks - 1 - chunkStage) % nRanks;
|
||||
chunkOffset = chunkId * curChunkSize;
|
||||
nelem = std::min(remSize - chunkOffset, curChunkSize);
|
||||
curSliceSize = std::max(divUp(nelem / elemSize, 16 * slicePerChunk) * 16, sliceSize / elemSize / 32) * elemSize;
|
||||
sliceOffset = sliceStage * curSliceSize;
|
||||
|
||||
if (nelem <= sliceOffset) {
|
||||
*sendbuffOut = sendbuff;
|
||||
*mhandleOut = sendMhandle;
|
||||
} else {
|
||||
if (curLoopStage == 0) {
|
||||
*sendbuffOut = sendbuff + elemOffset + chunkOffset + sliceOffset;
|
||||
*mhandleOut = sendMhandle;
|
||||
} else {
|
||||
*sendbuffOut = recvbuff + elemOffset + chunkOffset + sliceOffset;
|
||||
*mhandleOut = srecvMhandle;
|
||||
}
|
||||
}
|
||||
size = std::min(curSliceSize, nelem - sliceOffset);
|
||||
*sizeOut = size < 0 ? 0 : size;
|
||||
return;
|
||||
}
|
||||
|
||||
void getNextRecvAddr(int curStep, uint8_t **recvbuffOut, size_t *sizeOut, void **mhandleOut) {
|
||||
int curLoop = curStep / nStepsPerLoop;
|
||||
int curLoopStage = ((curStep + chunkSteps) % nStepsPerLoop) / chunkSteps;
|
||||
int chunkStage = curLoopStage % nRanks;
|
||||
int sliceStage = (curStep % chunkSteps) / sliceSteps;
|
||||
ssize_t elemOffset = curLoop * loopSize;
|
||||
ssize_t remSize = channelSize - elemOffset;
|
||||
ssize_t chunkOffset;
|
||||
ssize_t sliceOffset;
|
||||
ssize_t curSliceSize;
|
||||
ssize_t curChunkSize;
|
||||
ssize_t size;
|
||||
ssize_t nelem;
|
||||
int chunkId;
|
||||
|
||||
if (remSize < loopSize) {
|
||||
curChunkSize = alignUp(divUp(remSize / elemSize, nRanks), 16 / elemSize) * elemSize;
|
||||
} else {
|
||||
curChunkSize = chunkSize;
|
||||
}
|
||||
|
||||
if (curLoopStage == 0) {
|
||||
chunkId = (ringIndex + 1) % nRanks;
|
||||
} else {
|
||||
chunkId = (ringIndex + nRanks - 1 - chunkStage) % nRanks;
|
||||
}
|
||||
|
||||
chunkOffset = chunkId * curChunkSize;
|
||||
nelem = std::min(remSize - chunkOffset, curChunkSize);
|
||||
curSliceSize = std::max(divUp(nelem / elemSize, 16 * slicePerChunk) * 16, sliceSize / elemSize / 32) * elemSize;
|
||||
sliceOffset = sliceStage * curSliceSize;
|
||||
if (nelem <= sliceOffset) {
|
||||
*recvbuffOut = recvbuff;
|
||||
} else {
|
||||
*recvbuffOut = recvbuff + elemOffset + chunkOffset + sliceOffset;
|
||||
}
|
||||
if (sizeOut) {
|
||||
size = std::min(curSliceSize, nelem - sliceOffset);
|
||||
*sizeOut = size < 0 ? 0 : size;
|
||||
}
|
||||
*mhandleOut = recvMhandle;
|
||||
return;
|
||||
}
|
||||
|
||||
RingARAlgorithm(const void *sendbuff, void *recvbuff, int nRanks, int ringIndex, int chunkSteps, int sliceSteps, size_t chunkSize, size_t sliceSize, size_t gridOffset, size_t channelSize, int elemSize, void *sendMhandle, void *recvMhandle, void *srecvMhandle) {
|
||||
this->ringIndex = ringIndex;
|
||||
this->nRanks = nRanks;
|
||||
this->nStepsPerLoop = 2 * (nRanks - 1) * chunkSteps;
|
||||
this->chunkSteps = chunkSteps;
|
||||
this->sliceSteps = sliceSteps;
|
||||
this->chunkSize = chunkSize;
|
||||
this->sliceSize = sliceSize;
|
||||
this->loopSize = nRanks * chunkSize;
|
||||
this->sendbuff = (uint8_t*)sendbuff + gridOffset;
|
||||
this->recvbuff = (uint8_t*)recvbuff + gridOffset;
|
||||
this->channelSize = channelSize;
|
||||
this->elemSize = elemSize;
|
||||
this->sendMhandle = sendMhandle;
|
||||
this->recvMhandle = recvMhandle;
|
||||
this->srecvMhandle = srecvMhandle;
|
||||
this->slicePerChunk = chunkSteps / sliceSteps;
|
||||
}
|
||||
~RingARAlgorithm() {}
|
||||
};
|
||||
|
||||
class RingAGAlgorithm : public RingAlgorithm {
|
||||
private:
|
||||
int *ringRanks;
|
||||
int elemSize;
|
||||
ssize_t sendSize;
|
||||
int slicePerChunk;
|
||||
public:
|
||||
void getNextSendAddr(int curStep, uint8_t **sendbuffOut, size_t *sizeOut, void **mhandleOut) {
|
||||
int curLoop = curStep / nStepsPerLoop;
|
||||
int chunkStage = (curStep % nStepsPerLoop) / chunkSteps;
|
||||
int sliceStage = (curStep % chunkSteps) / sliceSteps;
|
||||
ssize_t sliceOffset;
|
||||
ssize_t curSliceSize;
|
||||
ssize_t offset;
|
||||
ssize_t elemOffset = curLoop * loopSize;
|
||||
ssize_t chunkSize = std::min(loopSize, channelSize - elemOffset);
|
||||
ssize_t size;
|
||||
int rankDest;
|
||||
uint8_t *buff;
|
||||
void *mhandle;
|
||||
|
||||
curSliceSize = std::max(divUp(chunkSize / elemSize, 16 * slicePerChunk) * 16, sliceSize / elemSize / 32) * elemSize;
|
||||
sliceOffset = sliceStage * curSliceSize;
|
||||
if (chunkStage == 0) {
|
||||
rankDest = ringRanks[0];
|
||||
offset = elemOffset + sliceOffset;
|
||||
buff = sendbuff + offset;
|
||||
mhandle = sendMhandle;
|
||||
} else {
|
||||
rankDest = ringRanks[nRanks - chunkStage];
|
||||
offset = elemOffset + rankDest * sendSize + sliceOffset;
|
||||
buff = recvbuff + offset;
|
||||
mhandle = srecvMhandle;
|
||||
}
|
||||
*sendbuffOut = buff;
|
||||
size = std::min(curSliceSize, channelSize - elemOffset - sliceOffset);
|
||||
*sizeOut = size < 0 ? 0 : size;
|
||||
*mhandleOut = mhandle;
|
||||
return;
|
||||
}
|
||||
|
||||
void getNextRecvAddr(int curStep, uint8_t **recvbuffOut, size_t *sizeOut, void **mhandleOut) {
|
||||
int curLoop = curStep / nStepsPerLoop;
|
||||
int chunkStage = ((curStep + chunkSteps) % nStepsPerLoop) / chunkSteps;
|
||||
int sliceStage = (curStep % chunkSteps) / sliceSteps;
|
||||
ssize_t sliceOffset;
|
||||
ssize_t curSliceSize;
|
||||
ssize_t offset;
|
||||
ssize_t elemOffset = curLoop * loopSize;
|
||||
ssize_t chunkSize = std::min(loopSize, channelSize - elemOffset);
|
||||
ssize_t size;
|
||||
int rankDest;
|
||||
|
||||
curSliceSize = std::max(divUp(chunkSize / elemSize, 16 * slicePerChunk) * 16, sliceSize / elemSize / 32) * elemSize;
|
||||
sliceOffset = sliceStage * curSliceSize;
|
||||
if (chunkStage == 0) {
|
||||
rankDest = ringRanks[1];
|
||||
} else {
|
||||
rankDest = ringRanks[nRanks - chunkStage];
|
||||
}
|
||||
offset = elemOffset + rankDest * sendSize + sliceOffset;
|
||||
*recvbuffOut = recvbuff + offset;
|
||||
if (sizeOut) {
|
||||
size = std::min(sliceSize, channelSize - elemOffset - sliceOffset);
|
||||
*sizeOut = size < 0 ? 0 : size;
|
||||
}
|
||||
*mhandleOut = recvMhandle;
|
||||
}
|
||||
|
||||
RingAGAlgorithm(const void *sendbuff, void *recvbuff, int nRanks, int *ringRanks, int chunkSteps, int sliceSteps, size_t chunkSize, size_t sliceSize, size_t gridOffset, size_t channelSize, int elemSize, size_t sendSize, void *sendMhandle, void *recvMhandle, void *srecvMhandle) {
|
||||
this->ringRanks = ringRanks;
|
||||
this->nRanks = nRanks;
|
||||
this->nStepsPerLoop = (nRanks - 1) * chunkSteps;
|
||||
this->chunkSteps = chunkSteps;
|
||||
this->sliceSteps = sliceSteps;
|
||||
this->elemSize = elemSize;
|
||||
this->sliceSize = sliceSize;
|
||||
this->loopSize = chunkSize;
|
||||
this->sendSize = sendSize;
|
||||
this->channelSize = channelSize;
|
||||
this->sendbuff = (uint8_t*)sendbuff + gridOffset;
|
||||
this->recvbuff = (uint8_t*)recvbuff + gridOffset;
|
||||
this->sendMhandle = sendMhandle;
|
||||
this->recvMhandle = recvMhandle;
|
||||
this->srecvMhandle = srecvMhandle;
|
||||
this->slicePerChunk = chunkSteps / sliceSteps;
|
||||
}
|
||||
~RingAGAlgorithm() {}
|
||||
};
|
||||
|
||||
class RingBCAlgorithm : public RingAlgorithm {
|
||||
private:
|
||||
int root;
|
||||
int rank;
|
||||
int nextRank;
|
||||
public:
|
||||
void getNextSendAddr(int curStep, uint8_t **sendbuffOut, size_t *sizeOut, void **mhandleOut) {
|
||||
int curLoop = curStep / nStepsPerLoop;
|
||||
int sliceStage = (curStep % chunkSteps) / sliceSteps;
|
||||
ssize_t sliceOffset = sliceStage * sliceSize;
|
||||
ssize_t offset;
|
||||
ssize_t elemOffset = curLoop * loopSize;
|
||||
ssize_t size;
|
||||
uint8_t *buff;
|
||||
void *mhandle;
|
||||
|
||||
offset = elemOffset + sliceOffset;
|
||||
if (offset >= channelSize) {
|
||||
buff = sendbuff;
|
||||
mhandle = sendMhandle;
|
||||
} else if (rank == root) {
|
||||
buff = sendbuff + offset;
|
||||
mhandle = sendMhandle;
|
||||
} else {
|
||||
buff = recvbuff + offset;
|
||||
mhandle = srecvMhandle;
|
||||
}
|
||||
*sendbuffOut = buff;
|
||||
size = std::min(sliceSize, channelSize - offset);
|
||||
*sizeOut = size < 0 ? 0 : size;
|
||||
*mhandleOut = mhandle;
|
||||
return;
|
||||
}
|
||||
|
||||
void getNextRecvAddr(int curStep, uint8_t **recvbuffOut, size_t *sizeOut, void **mhandleOut) {
|
||||
int curLoop = curStep / nStepsPerLoop;
|
||||
int sliceStage = (curStep % chunkSteps) / sliceSteps;
|
||||
ssize_t sliceOffset = sliceStage * sliceSize;
|
||||
ssize_t offset;
|
||||
ssize_t elemOffset = curLoop * loopSize;
|
||||
ssize_t size;
|
||||
offset = elemOffset + sliceOffset;
|
||||
if (offset >= channelSize) {
|
||||
*recvbuffOut = recvbuff;
|
||||
} else {
|
||||
*recvbuffOut = recvbuff + offset;
|
||||
}
|
||||
if (sizeOut) {
|
||||
size = std::min(sliceSize, channelSize - offset);
|
||||
*sizeOut = size < 0 ? 0 : size;
|
||||
}
|
||||
*mhandleOut = recvMhandle;
|
||||
return;
|
||||
}
|
||||
|
||||
RingBCAlgorithm(const void* sendbuff, void* recvbuff, int rank, int root, int nRanks, int *ringRanks, int chunkSteps, int sliceSteps, size_t chunkSize, size_t sliceSize, size_t gridOffset, size_t channelSize, void *sendMhandle, void *recvMhandle, void *srecvMhandle) {
|
||||
this->root = root;
|
||||
this->rank = rank;
|
||||
this->nextRank = ringRanks[1];
|
||||
this->nStepsPerLoop = chunkSteps;
|
||||
this->chunkSteps = chunkSteps;
|
||||
this->sliceSteps = sliceSteps;
|
||||
this->sliceSize = sliceSize;
|
||||
this->loopSize = chunkSize;
|
||||
this->channelSize = channelSize;
|
||||
this->sendbuff = (uint8_t*)sendbuff + gridOffset;
|
||||
this->recvbuff = (uint8_t*)recvbuff + gridOffset;
|
||||
this->sendMhandle = sendMhandle;
|
||||
this->recvMhandle = recvMhandle;
|
||||
this->srecvMhandle = srecvMhandle;
|
||||
}
|
||||
~RingBCAlgorithm() {}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class PatRSAlgorithm{
|
||||
size_t offset;
|
||||
@@ -532,10 +847,10 @@ restart:
|
||||
int sendDataRank = (rank + nranks + s) % nranks;
|
||||
outIx = sendDataRank * count + offset;
|
||||
recvDim = s ? firstBitSet(s, nrPow2) : -1;
|
||||
s -= (1<<recvDim);
|
||||
if (recvDim == -1) {
|
||||
recvOffset = -1;
|
||||
} else {
|
||||
s -= (1<<recvDim);
|
||||
int foffset = (a*2*scale*aggDelta) >> (recvDim+1);
|
||||
recvOffset = (foffset%postFreq)*nelem;
|
||||
recvStepOffset = foffset / postFreq;
|
||||
|
||||
+18
-4
@@ -197,12 +197,15 @@ struct ncclTaskColl {
|
||||
int32_t algorithm:8, protocol:8;
|
||||
uint32_t isCollnet:1, isNvls:1;
|
||||
uint32_t devFuncId:30;
|
||||
enum ncclRegBufferType regBufType;
|
||||
int regBufType;
|
||||
// number of elements in planner->ipcMemQueue associated with this collective
|
||||
int nCleanupQueueElts;
|
||||
|
||||
void* sendMhandle;
|
||||
void* recvMhandle;
|
||||
void** sendNetHandles;
|
||||
void** recvNetHandles;
|
||||
void** srecvNetHandles;
|
||||
// index for IPC record lookup
|
||||
uintptr_t sendbuffOffset;
|
||||
uintptr_t recvbuffOffset;
|
||||
@@ -236,6 +239,7 @@ struct ncclKernelPlan {
|
||||
struct ncclKernelPlan* next;
|
||||
|
||||
bool persistent; // aka captured in a graph
|
||||
bool isHostCbEnq;
|
||||
enum ncclDevWorkStorageType workStorageType;
|
||||
bool kernelSpecialized;
|
||||
void *kernelFn;
|
||||
@@ -365,6 +369,7 @@ struct ncclKernelPlanner {
|
||||
|
||||
struct ncclIntruQueue<struct ncclTaskColl, &ncclTaskColl::next> collTaskQueue;
|
||||
struct ncclIntruQueue<struct ncclWorkList, &ncclWorkList::next> collWorkQueue;
|
||||
struct ncclIntruQueue<struct ncclWorkList, &ncclWorkList::next> tmpCollWorkQueue;
|
||||
struct ncclIntruQueue<struct ncclCommCallback, &ncclCommCallback::next> collCleanupQueue;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
@@ -463,6 +468,8 @@ struct ncclComm {
|
||||
|
||||
// Counter for tracking CUDA launches (P2P and collectives included)
|
||||
uint64_t opCount;
|
||||
// Collective operation counter
|
||||
uint64_t collOpCount;
|
||||
|
||||
// Channels for collectives
|
||||
int nChannels; // connection nChannels
|
||||
@@ -486,7 +493,6 @@ struct ncclComm {
|
||||
ssize_t threadThresholds[NCCL_NUM_ALGORITHMS][NCCL_NUM_PROTOCOLS];
|
||||
float latencies[NCCL_NUM_FUNCTIONS][NCCL_NUM_ALGORITHMS][NCCL_NUM_PROTOCOLS];
|
||||
float bandwidths[NCCL_NUM_FUNCTIONS][NCCL_NUM_ALGORITHMS][NCCL_NUM_PROTOCOLS];
|
||||
float ringbdw[NCCL_NUM_FUNCTIONS][NCCL_NUM_PROTOCOLS];
|
||||
int maxThreads[NCCL_NUM_ALGORITHMS][NCCL_NUM_PROTOCOLS];
|
||||
|
||||
/* This attribute can indicate the states of communicators and return code of
|
||||
@@ -532,7 +538,7 @@ struct ncclComm {
|
||||
int proxyRefCountOld; /* store proxy post-atomic-sub refcount */
|
||||
// Whether this communicator uses collNet
|
||||
int collNetSupport;
|
||||
bool collNetRegSupport;
|
||||
bool isOneRPN;
|
||||
uint8_t collNetSupportMatrix[4/*sum,prod,max,min*/][ncclNumTypes];
|
||||
bool intraNodeP2pSupport;
|
||||
int* collNetHeads;
|
||||
@@ -560,6 +566,7 @@ struct ncclComm {
|
||||
// Subset of those in groupNext list. Holds 0x1 if not needing preconnect.
|
||||
struct ncclComm* preconnectNext;
|
||||
int persistentRefs; // number of persistent plan-lists capturing this comm
|
||||
int noncapturedRefs; // number of non-captured hostStreamPlanCallback on the stream
|
||||
struct P2pSchedulePair { int sendRank; int recvRank; } *p2pSchedule;
|
||||
|
||||
struct ncclKernelPlanner planner;
|
||||
@@ -599,9 +606,16 @@ struct ncclComm {
|
||||
|
||||
// buffer registration cache
|
||||
struct ncclRegCache regCache;
|
||||
int isAllNvlink;
|
||||
bool useNetPXN;
|
||||
bool useGdr;
|
||||
int splitCount;
|
||||
uint64_t endMagic;
|
||||
};
|
||||
|
||||
static_assert(offsetof(struct ncclComm, startMagic) == 0, "startMagic must be the first field of ncclComm");
|
||||
static_assert(offsetof(struct ncclComm, endMagic) == sizeof(struct ncclComm) - sizeof(uint64_t), "endMagic must be the last field of ncclComm");
|
||||
|
||||
enum ncclLaunchMode {
|
||||
ncclLaunchModeInvalid=0,
|
||||
ncclLaunchModeParallel,
|
||||
@@ -644,7 +658,7 @@ inline ncclResult_t ncclCommPollEventCallbacks(struct ncclComm *comm) {
|
||||
}
|
||||
}
|
||||
finish:
|
||||
cudaThreadExchangeStreamCaptureMode(&mode);
|
||||
CUDACHECK(cudaThreadExchangeStreamCaptureMode(&mode));
|
||||
return ncclSuccess;
|
||||
}
|
||||
|
||||
|
||||
@@ -38,4 +38,6 @@ extern char ncclLastError[];
|
||||
|
||||
void ncclSetThreadName(pthread_t thread, const char *fmt, ...);
|
||||
|
||||
void ncclResetDebugInit();
|
||||
|
||||
#endif
|
||||
|
||||
+10
-20
@@ -88,24 +88,18 @@ static_assert(NCCL_LL_CLEAN_MASK % NCCL_STEPS == 0, "Invalid NCCL_LL_CLEAN_MASK
|
||||
#define NCCL_LL128_SHMEM_ELEMS_PER_THREAD 8
|
||||
#define NCCL_LL128_SHMEM_SIZE (NCCL_LL128_SHMEM_ELEMS_PER_THREAD*NCCL_LL128_MAX_NTHREADS)
|
||||
|
||||
#define NCCL_DIRECT_WRITE 0x01
|
||||
#define NCCL_DIRECT_READ 0x02
|
||||
#define NCCL_P2P_WRITE 0x01
|
||||
#define NCCL_P2P_READ 0x02
|
||||
#define NCCL_DIRECT_NIC 0x04
|
||||
#define NCCL_IPC_WRITE 0x08
|
||||
#define NCCL_IPC_READ 0x10
|
||||
#define NCCL_NVLS_MIN_POLL 0x20
|
||||
#define NCCL_NVLS_MIN_POLL 0x80
|
||||
|
||||
// Number of named barriers supported by CUDA
|
||||
#define NCCL_MAX_GROUPS 16
|
||||
|
||||
#define NCCL_MAX_COLLNET_SIZE (1L << 29)
|
||||
|
||||
enum ncclRegBufferType {
|
||||
NCCL_REGULAR_BUFFER = 0,
|
||||
NCCL_IPC_REG_BUFFER = 1,
|
||||
NCCL_NVLS_REG_BUFFER = 2,
|
||||
NCCL_COLLNET_REG_BUFFER = 3
|
||||
};
|
||||
#define NCCL_REGULAR_BUFFER 0x00
|
||||
#define NCCL_IPC_REG_BUFFER 0x01
|
||||
#define NCCL_NVLS_REG_BUFFER 0x02
|
||||
#define NCCL_NET_REG_BUFFER 0x04
|
||||
|
||||
struct ncclConnInfo {
|
||||
// Regular comm mechanism
|
||||
@@ -143,8 +137,6 @@ struct ncclConnector {
|
||||
struct ncclTransportComm* transportComm;
|
||||
void* transportResources;
|
||||
struct ncclConnInfo conn;
|
||||
int sendMemSameProcess;
|
||||
int recvMemSameProcess;
|
||||
};
|
||||
|
||||
struct ncclRing {
|
||||
@@ -228,7 +220,7 @@ struct alignas(16) ncclDevWorkP2p {
|
||||
uint8_t sendChunkSize_u32fp8, recvChunkSize_u32fp8;
|
||||
|
||||
uint8_t sendProtoLL:1, recvProtoLL:1;
|
||||
uint8_t sendRegistered:1, recvRegistered:1;
|
||||
uint8_t sendNetReg:1, recvNetReg:1;
|
||||
uint8_t sendIpcReg:1, recvIpcReg:1;
|
||||
};
|
||||
|
||||
@@ -267,7 +259,7 @@ struct alignas(16) ncclDevWorkColl {
|
||||
// nChannels == (channelHi - channelLo) + 1
|
||||
uint32_t channelLo:8, channelHi:8;
|
||||
uint32_t nWarps:8;
|
||||
uint32_t redOpArgIsPtr:1, regUsed:2, oneNode:1, direct:4;
|
||||
uint32_t redOpArgIsPtr:1, regUsed:1, netRegUsed:1, oneNode:1, direct:2, isOneRPN:1;
|
||||
uint32_t root;
|
||||
void* recvbuff;
|
||||
void* sendbuff;
|
||||
@@ -393,7 +385,7 @@ struct ncclDevComm {
|
||||
int nNodes;
|
||||
int buffSizes[NCCL_NUM_PROTOCOLS];
|
||||
int p2pChunkSize;
|
||||
int isNvlink;
|
||||
int isAllNvlink;
|
||||
|
||||
// Work fifo return credits
|
||||
uint32_t* workConsumed/*[MAXCHANNELS]*/;
|
||||
@@ -525,9 +517,7 @@ inline bool ncclNvlsSupported(int devRedOp, int type) {
|
||||
case ncclInt64:
|
||||
case ncclUint64:
|
||||
case ncclFloat16:
|
||||
#if defined(__CUDA_BF16_TYPES_EXIST__)
|
||||
case ncclBfloat16:
|
||||
#endif
|
||||
return devRedOp == ncclDevSum || devRedOp == ncclDevMinMax;
|
||||
case ncclFloat:
|
||||
case ncclDouble:
|
||||
|
||||
@@ -25,5 +25,16 @@ ncclResult_t ncclLaunchKernel(struct ncclComm* comm, struct ncclKernelPlan* plan
|
||||
ncclResult_t ncclLaunchKernelAfter_NoCuda(struct ncclComm* comm, struct ncclKernelPlan* plan);
|
||||
ncclResult_t ncclLaunchFinish(struct ncclComm* comm);
|
||||
ncclResult_t ncclPrepareTasks(struct ncclComm* comm, bool* algoNeedConnect, bool* needConnect, ncclSimInfo_t* simInfo);
|
||||
ncclResult_t ncclTasksRegAndEnqueue(struct ncclComm* comm);
|
||||
|
||||
static inline size_t ncclFuncSendCount(ncclFunc_t func, int nRanks, size_t count) {
|
||||
return func == ncclFuncReduceScatter ? nRanks*count : count;
|
||||
}
|
||||
static inline size_t ncclFuncRecvCount(ncclFunc_t func, int nRanks, size_t count) {
|
||||
return func == ncclFuncAllGather ? nRanks*count : count;
|
||||
}
|
||||
static inline size_t ncclFuncMaxSendRecvCount(ncclFunc_t func, int nRanks, size_t count) {
|
||||
return func == ncclFuncAllGather || func == ncclFuncReduceScatter ? nRanks*count : count;
|
||||
}
|
||||
|
||||
#endif // End include guard
|
||||
|
||||
@@ -19,7 +19,7 @@ ncclResult_t ncclTopoCudaPath(int cudaDev, char** path);
|
||||
|
||||
struct ncclTopoSystem;
|
||||
// Build the topology
|
||||
ncclResult_t ncclTopoGetSystem(struct ncclComm* comm, struct ncclTopoSystem** system);
|
||||
ncclResult_t ncclTopoGetSystem(struct ncclComm* comm, struct ncclTopoSystem** system, const char* dumpXmlFile=NULL);
|
||||
ncclResult_t ncclTopoSortSystem(struct ncclTopoSystem* system);
|
||||
ncclResult_t ncclTopoPrint(struct ncclTopoSystem* system);
|
||||
|
||||
@@ -33,10 +33,11 @@ ncclResult_t ncclTopoComputeCommCPU(struct ncclComm* comm);
|
||||
|
||||
// Query topology
|
||||
ncclResult_t ncclTopoGetNetDev(struct ncclComm* comm, int rank, struct ncclTopoGraph* graph, int channelId, int peerRank, int64_t* id, int* dev, int* proxyRank);
|
||||
ncclResult_t ncclTopoCheckP2p(struct ncclTopoSystem* system, int rank1, int rank2, int* p2p, int *read, int* intermediateRank);
|
||||
ncclResult_t ncclTopoCheckP2p(struct ncclComm* comm, struct ncclTopoSystem* system, int rank1, int rank2, int* p2p, int *read, int* intermediateRank);
|
||||
ncclResult_t ncclTopoCheckMNNVL(struct ncclTopoSystem* system, struct ncclPeerInfo* info1, struct ncclPeerInfo* info2, int* ret);
|
||||
ncclResult_t ncclTopoCheckGdr(struct ncclTopoSystem* topo, int64_t busId, int64_t netId, int read, int* useGdr);
|
||||
ncclResult_t ncclTopoNeedFlush(struct ncclTopoSystem* system, int64_t busId, int* flush);
|
||||
ncclResult_t ncclTopoCheckGdr(struct ncclTopoSystem* topo, int rank, int64_t netId, int read, int* useGdr);
|
||||
ncclResult_t ncclTopoNeedFlush(struct ncclComm* comm, int netDev, int rank, int* flush);
|
||||
ncclResult_t ncclTopoIsGdrAvail(struct ncclTopoSystem* system, int rank, bool *avail);
|
||||
ncclResult_t ncclTopoCheckNet(struct ncclTopoSystem* system, int rank1, int rank2, int* net);
|
||||
int ncclPxnDisable(struct ncclComm* comm);
|
||||
ncclResult_t ncclTopoGetPxnRanks(struct ncclComm* comm, int** intermediateRanks, int* nranks);
|
||||
@@ -118,6 +119,6 @@ ncclResult_t ncclTopoPostset(struct ncclComm* comm, int* firstRanks, int* treePa
|
||||
struct ncclTopoRanks** allTopoRanks, int* rings, struct ncclTopoGraph** graphs, struct ncclComm* parent);
|
||||
|
||||
ncclResult_t ncclTopoTuneModel(struct ncclComm* comm, int minCompCap, int maxCompCap, struct ncclTopoGraph** graphs);
|
||||
ncclResult_t ncclTopoGetAlgoTime(struct ncclComm* comm, int coll, int algorithm, int protocol, size_t nBytes, int numPipeOps, float* time, bool* backup=nullptr);
|
||||
ncclResult_t ncclTopoGetAlgoTime(struct ncclComm* comm, int coll, int algorithm, int protocol, size_t nBytes, int numPipeOps, float* time);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
#ifndef NCCL_IBVWRAP_H_
|
||||
#define NCCL_IBVWRAP_H_
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#ifdef NCCL_BUILD_RDMA_CORE
|
||||
#include <infiniband/verbs.h>
|
||||
#else
|
||||
@@ -89,4 +91,14 @@ static inline ncclResult_t wrap_ibv_post_recv(struct ibv_qp *qp, struct ibv_recv
|
||||
|
||||
ncclResult_t wrap_ibv_event_type_str(char **ret, enum ibv_event_type event);
|
||||
|
||||
// converts a GID into a readable string. On success, returns a non-null pointer to gidStr.
|
||||
// NULL is returned if there was an error, with errno set to indicate the error.
|
||||
// errno = ENOSPC if the converted string would exceed strLen.
|
||||
static inline const char* ibvGetGidStr(union ibv_gid* gid, char* gidStr, size_t strLen) {
|
||||
// GID is a 16B handle, to convert it to a readable form, we use inet_ntop
|
||||
// sizeof(ibv_gid) == sizeof(struct in6_addr), so using AF_INET6
|
||||
static_assert(sizeof(union ibv_gid) == sizeof(struct in6_addr), "the sizeof struct ibv_gid must be the size of struct in6_addr");
|
||||
return inet_ntop(AF_INET6, gid->raw, gidStr, strLen);
|
||||
}
|
||||
|
||||
#endif //End include guard
|
||||
|
||||
@@ -32,6 +32,7 @@ typedef enum {
|
||||
NCCL_BOOTSTRAP = 0x1000,
|
||||
NCCL_REG = 0x2000,
|
||||
NCCL_PROFILE = 0x4000,
|
||||
NCCL_RAS = 0x8000,
|
||||
NCCL_ALL = ~0
|
||||
} ncclDebugLogSubSys;
|
||||
|
||||
|
||||
+158
-10
@@ -13,6 +13,9 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#define NCCL_NET_HANDLE_MAXSIZE 128
|
||||
//Maximum value NCCL can accept for maxP2pBytes and maxCollBytes net properties
|
||||
#define NCCL_MAX_NET_SIZE_BYTES (1*1024*1024*1024*1024L)
|
||||
#define NCCL_NET_OPTIONAL_RECV_COMPLETION 0x1
|
||||
|
||||
#define NCCL_PTR_HOST 0x1
|
||||
#define NCCL_PTR_CUDA 0x2
|
||||
@@ -21,6 +24,161 @@
|
||||
// Maximum number of requests per comm object
|
||||
#define NCCL_NET_MAX_REQUESTS 32
|
||||
|
||||
// Max number of ncclNet objects which can live in the same process
|
||||
#define NCCL_NET_MAX_PLUGINS 3
|
||||
|
||||
#define NCCL_NET_MAX_DEVS_PER_NIC_V9 4
|
||||
#define NCCL_NET_MAX_DEVS_PER_NIC NCCL_NET_MAX_DEVS_PER_NIC_V9
|
||||
|
||||
typedef struct {
|
||||
int ndevs;
|
||||
int devs[NCCL_NET_MAX_DEVS_PER_NIC_V9];
|
||||
} ncclNetVDeviceProps_v9_t;
|
||||
typedef ncclNetVDeviceProps_v9_t ncclNetVDeviceProps_t;
|
||||
|
||||
typedef struct {
|
||||
char* name; // Used mostly for logging.
|
||||
char* pciPath; // Path to the PCI device in /sys.
|
||||
uint64_t guid; // Unique identifier for the NIC chip. Important for
|
||||
// cards with multiple PCI functions (Physical or virtual).
|
||||
int ptrSupport; // [NCCL_PTR_HOST|NCCL_PTR_CUDA|NCCL_PTR_DMABUF]
|
||||
int regIsGlobal; // regMr is not tied to a particular comm
|
||||
int forceFlush; // Force a flush on receives
|
||||
int speed; // Port speed in Mbps.
|
||||
int port; // Port number.
|
||||
float latency; // Network latency
|
||||
int maxComms; // Maximum number of comms we can create
|
||||
int maxRecvs; // Maximum number of grouped receives.
|
||||
ncclNetDeviceType netDeviceType; // Network offload type
|
||||
int netDeviceVersion; // Version number for network offload
|
||||
ncclNetVDeviceProps_v9_t vProps;
|
||||
size_t maxP2pBytes; // Max transfer size for point-to-point operations
|
||||
size_t maxCollBytes; // Max transfer size for collective operations
|
||||
} ncclNetProperties_v9_t;
|
||||
typedef ncclNetProperties_v9_t ncclNetProperties_t;
|
||||
|
||||
typedef struct {
|
||||
// Name of the network (mainly for logs)
|
||||
const char* name;
|
||||
// Initialize the network.
|
||||
ncclResult_t (*init)(ncclDebugLogger_t logFunction);
|
||||
// Return the number of adapters.
|
||||
ncclResult_t (*devices)(int* ndev);
|
||||
// Get various device properties.
|
||||
ncclResult_t (*getProperties)(int dev, ncclNetProperties_v9_t* props);
|
||||
// Create a receiving object and provide a handle to connect to it. The
|
||||
// handle can be up to NCCL_NET_HANDLE_MAXSIZE bytes and will be exchanged
|
||||
// between ranks to create a connection.
|
||||
ncclResult_t (*listen)(int dev, void* handle, void** listenComm);
|
||||
// Connect to a handle and return a sending comm object for that peer.
|
||||
// This call must not block for the connection to be established, and instead
|
||||
// should return successfully with sendComm == NULL with the expectation that
|
||||
// it will be called again until sendComm != NULL.
|
||||
// If *sendDevComm points to a valid object, then NCCL is requesting device offload for this connection
|
||||
ncclResult_t (*connect)(int dev, void* handle, void** sendComm, ncclNetDeviceHandle_v8_t** sendDevComm);
|
||||
// Finalize connection establishment after remote peer has called connect.
|
||||
// This call must not block for the connection to be established, and instead
|
||||
// should return successfully with recvComm == NULL with the expectation that
|
||||
// it will be called again until recvComm != NULL.
|
||||
// If *recvDevComm points to a valid object, then NCCL is requesting device offload for this connection
|
||||
ncclResult_t (*accept)(void* listenComm, void** recvComm, ncclNetDeviceHandle_v8_t** recvDevComm);
|
||||
// Register/Deregister memory. Comm can be either a sendComm or a recvComm.
|
||||
// Type is either NCCL_PTR_HOST or NCCL_PTR_CUDA.
|
||||
ncclResult_t (*regMr)(void* comm, void* data, size_t size, int type, void** mhandle);
|
||||
/* DMA-BUF support */
|
||||
ncclResult_t (*regMrDmaBuf)(void* comm, void* data, size_t size, int type, uint64_t offset, int fd, void** mhandle);
|
||||
ncclResult_t (*deregMr)(void* comm, void* mhandle);
|
||||
// Asynchronous send to a peer.
|
||||
// May return request == NULL if the call cannot be performed (or would block)
|
||||
ncclResult_t (*isend)(void* sendComm, void* data, size_t size, int tag, void* mhandle, void** request);
|
||||
// Asynchronous recv from a peer.
|
||||
// May return request == NULL if the call cannot be performed (or would block)
|
||||
ncclResult_t (*irecv)(void* recvComm, int n, void** data, size_t* sizes, int* tags, void** mhandles, void** request);
|
||||
// Perform a flush/fence to make sure all data received with NCCL_PTR_CUDA is
|
||||
// visible to the GPU
|
||||
ncclResult_t (*iflush)(void* recvComm, int n, void** data, int* sizes, void** mhandles, void** request);
|
||||
// Test whether a request is complete. If size is not NULL, it returns the
|
||||
// number of bytes sent/received.
|
||||
ncclResult_t (*test)(void* request, int* done, int* sizes);
|
||||
// Close and free send/recv comm objects
|
||||
ncclResult_t (*closeSend)(void* sendComm);
|
||||
ncclResult_t (*closeRecv)(void* recvComm);
|
||||
ncclResult_t (*closeListen)(void* listenComm);
|
||||
|
||||
// Copy the given mhandle to a dptr in a format usable by this plugin's device code
|
||||
ncclResult_t (*getDeviceMr)(void* comm, void* mhandle, void** dptr_mhandle);
|
||||
|
||||
// Notify the plugin that a recv has completed by the device
|
||||
ncclResult_t (*irecvConsumed)(void* recvComm, int n, void* request);
|
||||
|
||||
// Create a virtual NIC given the specified properties, which can be accessed at device index d
|
||||
ncclResult_t (*makeVDevice)(int* d, ncclNetVDeviceProps_t* props);
|
||||
} ncclNet_v9_t;
|
||||
|
||||
typedef ncclNet_v9_t ncclNet_t;
|
||||
|
||||
#define NCCL_NET_PLUGIN_SYMBOL ncclNetPlugin_v9
|
||||
|
||||
typedef struct {
|
||||
void* mhandle;
|
||||
void* address;
|
||||
size_t size;
|
||||
} ncclNetSGE_v9_t;
|
||||
|
||||
typedef struct {
|
||||
// Name of the collective network (mainly for logs)
|
||||
const char* name;
|
||||
// Initialize the collective network.
|
||||
ncclResult_t (*init)(ncclDebugLogger_t logFunction);
|
||||
// Return the number of adapters capable of doing collective operations.
|
||||
// If ndev returns 0, all other functions might be set to NULL.
|
||||
ncclResult_t (*devices)(int* ndev);
|
||||
// Get various device properties.
|
||||
ncclResult_t (*getProperties)(int dev, ncclNetProperties_v9_t* props);
|
||||
// Create a receiving object and provide a handle to connect to it. The
|
||||
// handle can be up to NCCL_NET_HANDLE_MAXSIZE bytes and will be exchanged
|
||||
// between ranks to create connections.
|
||||
ncclResult_t (*listen)(int dev, void* handle, void** listenComm);
|
||||
// Create a group for collective operations. handles have been created
|
||||
// using listen() above. rank indicates caller's rank in the collective network.
|
||||
ncclResult_t (*connect)(void* handles[], int nranks, int rank, void* listenComm, void** collComm);
|
||||
// Returns whether a reduction operation on a data type is supported.
|
||||
// 1 for supported, 0 otherwise.
|
||||
ncclResult_t (*reduceSupport)(ncclDataType_t dataType, ncclRedOp_t redOp, int* supported);
|
||||
// Register/Deregister memory. Type is either NCCL_PTR_HOST or NCCL_PTR_CUDA.
|
||||
ncclResult_t (*regMr)(void* collComm, void* data, size_t size, int type, void** mhandle);
|
||||
/* DMA-BUF support */
|
||||
ncclResult_t (*regMrDmaBuf)(void* collComm, void* data, size_t size, int type, uint64_t offset, int fd, void** mhandle);
|
||||
ncclResult_t (*deregMr)(void* collComm, void* mhandle);
|
||||
// Performs an asynchronous allreduce operation on the collective group.
|
||||
// May return request == NULL if the call cannot be performed (or would block).
|
||||
ncclResult_t (*iallreduce)(void* collComm, void* sendData, void* recvData, size_t count,
|
||||
ncclDataType_t dataType, ncclRedOp_t redOp, void* sendMhandle, void* recvMhandle, void** request);
|
||||
ncclResult_t (*iallgather)(void* collComm, void* sendData, int nRecvParts, ncclNetSGE_v9_t* recvParts,
|
||||
size_t bytesPerRank, size_t windowOffset, size_t windowBytes,
|
||||
void* sendMhandle, void** request);
|
||||
ncclResult_t (*ireducescatter)(void* collComm, int nSendParts, ncclNetSGE_v9_t* sendParts, void* recvData,
|
||||
size_t bytesPerRank, size_t windowOffset, size_t windowBytes,
|
||||
ncclDataType_t dataType, ncclRedOp_t redOp,
|
||||
void* recvMhandle, void** request);
|
||||
// Perform a flush/fence to make sure all data received with NCCL_PTR_CUDA is
|
||||
// visible to the GPU
|
||||
ncclResult_t (*iflush)(void* collComm, void* data, int size, void* mhandle, void** request);
|
||||
// Test whether a request is complete. If size is not NULL, it returns the
|
||||
// number of bytes sent/received.
|
||||
ncclResult_t (*test)(void* request, int* done, int* size);
|
||||
// Close and free collective comm objects
|
||||
ncclResult_t (*closeColl)(void* collComm);
|
||||
ncclResult_t (*closeListen)(void* listenComm);
|
||||
|
||||
// Create a virtual NIC given the specified properties, which can be accessed at device index d
|
||||
ncclResult_t (*makeVDevice)(int* d, ncclNetVDeviceProps_t* props);
|
||||
} ncclCollNet_v9_t;
|
||||
|
||||
typedef ncclCollNet_v9_t ncclCollNet_t;
|
||||
|
||||
#define NCCL_COLLNET_PLUGIN_SYMBOL ncclCollNetPlugin_v9
|
||||
|
||||
typedef struct {
|
||||
char* name; // Used mostly for logging.
|
||||
char* pciPath; // Path to the PCI device in /sys.
|
||||
@@ -37,8 +195,6 @@ typedef struct {
|
||||
int netDeviceVersion; // Version number for network offload
|
||||
} ncclNetProperties_v8_t;
|
||||
|
||||
typedef ncclNetProperties_v8_t ncclNetProperties_t;
|
||||
|
||||
typedef struct {
|
||||
// Name of the network (mainly for logs)
|
||||
const char* name;
|
||||
@@ -94,10 +250,6 @@ typedef struct {
|
||||
ncclResult_t (*irecvConsumed)(void* recvComm, int n, void* request);
|
||||
} ncclNet_v8_t;
|
||||
|
||||
typedef ncclNet_v8_t ncclNet_t;
|
||||
|
||||
#define NCCL_NET_PLUGIN_SYMBOL ncclNetPlugin_v8
|
||||
|
||||
typedef struct {
|
||||
void* mhandle;
|
||||
void* address;
|
||||
@@ -151,10 +303,6 @@ typedef struct {
|
||||
ncclResult_t (*closeListen)(void* listenComm);
|
||||
} ncclCollNet_v8_t;
|
||||
|
||||
typedef ncclCollNet_v8_t ncclCollNet_t;
|
||||
|
||||
#define NCCL_COLLNET_PLUGIN_SYMBOL ncclCollNetPlugin_v8
|
||||
|
||||
typedef struct {
|
||||
char* name; // Used mostly for logging.
|
||||
char* pciPath; // Path to the PCI device in /sys.
|
||||
|
||||
+127
-42
@@ -16,9 +16,133 @@ enum {
|
||||
ncclProfileProxyOp = (1 << 3), // proxy operation event type
|
||||
ncclProfileProxyStep = (1 << 4), // proxy step event type
|
||||
ncclProfileProxyCtrl = (1 << 5), // proxy control event type
|
||||
ncclProfileNumEvents = ( 6),
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint8_t type; // event type descriptor: ncclProfileColl, ...
|
||||
void* parentObj; // pointer to the profiler parent object (for coll is the group)
|
||||
int rank; // originating rank
|
||||
union {
|
||||
struct {
|
||||
const char* name;
|
||||
uint64_t commHash;
|
||||
uint64_t seqNumber;
|
||||
const char* func;
|
||||
void const* sendBuff;
|
||||
void* recvBuff;
|
||||
size_t count;
|
||||
int root;
|
||||
const char* datatype;
|
||||
size_t trafficBytes;
|
||||
uint8_t nMaxChannels;
|
||||
uint8_t nWarps;
|
||||
const char* algo;
|
||||
const char* proto;
|
||||
} coll;
|
||||
|
||||
struct {
|
||||
const char* name;
|
||||
uint64_t commHash;
|
||||
const char* func;
|
||||
void* buff;
|
||||
const char* datatype;
|
||||
size_t count;
|
||||
int peer;
|
||||
} p2p;
|
||||
|
||||
struct {
|
||||
pid_t pid; // pid of the originating process
|
||||
uint8_t channelId; // channel id for this proxy operation
|
||||
int peer; // remote rank for send/recv
|
||||
int nSteps; // number of steps for this proxy operation
|
||||
int chunkSize; // amount of data transferred by this proxy operation
|
||||
int isSend;
|
||||
} proxyOp;
|
||||
|
||||
struct {
|
||||
int step;
|
||||
} proxyStep;
|
||||
};
|
||||
} ncclProfilerEventDescr_v2_t;
|
||||
|
||||
typedef enum {
|
||||
ncclProfilerProxyOpSendPosted,
|
||||
ncclProfilerProxyOpSendRemFifoWait,
|
||||
ncclProfilerProxyOpSendTransmitted,
|
||||
ncclProfilerProxyOpSendDone,
|
||||
ncclProfilerProxyOpRecvPosted,
|
||||
ncclProfilerProxyOpRecvReceived,
|
||||
ncclProfilerProxyOpRecvTransmitted,
|
||||
ncclProfilerProxyOpRecvDone,
|
||||
|
||||
/* Legacy proxy profiler states */
|
||||
ncclProfilerProxyStepSendGPUWait,
|
||||
ncclProfilerProxyStepSendWait,
|
||||
ncclProfilerProxyStepRecvWait,
|
||||
ncclProfilerProxyStepRecvFlushWait,
|
||||
ncclProfilerProxyStepRecvGPUWait,
|
||||
|
||||
/* Legacy proxy control states */
|
||||
ncclProfilerProxyCtrlIdle,
|
||||
ncclProfilerProxyCtrlActive,
|
||||
ncclProfilerProxyCtrlSleep,
|
||||
ncclProfilerProxyCtrlWakeup,
|
||||
ncclProfilerProxyCtrlAppend,
|
||||
ncclProfilerProxyCtrlAppendEnd,
|
||||
} ncclProfilerEventState_v2_t;
|
||||
|
||||
typedef union {
|
||||
struct {
|
||||
size_t transSize;
|
||||
int steps;
|
||||
} proxyOp;
|
||||
|
||||
struct {
|
||||
int appendedProxyOps;
|
||||
} proxyCtrl;
|
||||
} ncclProfilerEventStateArgs_v2_t;
|
||||
|
||||
typedef struct {
|
||||
const char* name;
|
||||
|
||||
// init - initialize the profiler plugin
|
||||
// Input
|
||||
// - context : opaque profiler context object for separating profiler behavior across comms
|
||||
// Output
|
||||
// - eActivationMask: bitmask of active events set by the plugin
|
||||
ncclResult_t (*init)(void** context, int* eActivationMask);
|
||||
|
||||
// startEvent - initialize and start a new event for the supplied event descriptor inside the eventset
|
||||
// Input
|
||||
// - context: opaque profiler context object
|
||||
// - eDescr : pointer to ncclProfilerEventDescr_t object
|
||||
// Output
|
||||
// - eHandle: return event handle for supplied event descriptor object
|
||||
ncclResult_t (*startEvent)(void* context, void** eHandle, ncclProfilerEventDescr_v2_t* eDescr);
|
||||
|
||||
// stopEvent - stop/finalize an event inside and event set
|
||||
// Input
|
||||
// - eHandle: handle to event object
|
||||
ncclResult_t (*stopEvent)(void* eHandle);
|
||||
|
||||
// recordEventState - record event state transitions and event attribute updates
|
||||
// Input
|
||||
// - eHandle : handle to event object created through startEvent
|
||||
// - eStateArgs: optional argument used to capture event attribute updates associated with the state transition
|
||||
// - eState : event state transition
|
||||
ncclResult_t (*recordEventState)(void* eHandle, ncclProfilerEventState_v2_t eState, ncclProfilerEventStateArgs_v2_t* eStateArgs);
|
||||
|
||||
// finalize - finalize the profiler plugin
|
||||
// Input
|
||||
// - context: opaque profiler context object
|
||||
ncclResult_t (*finalize)(void* context);
|
||||
} ncclProfiler_v2_t;
|
||||
|
||||
typedef ncclProfilerEventDescr_v2_t ncclProfilerEventDescr_t;
|
||||
typedef ncclProfilerEventState_v2_t ncclProfilerEventState_t;
|
||||
typedef ncclProfilerEventStateArgs_v2_t ncclProfilerEventStateArgs_t;
|
||||
typedef ncclProfiler_v2_t ncclProfiler_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t type; // event type descriptor: ncclProfileColl, ...
|
||||
void* parentObj; // pointer to the profiler parent object (for coll is the group)
|
||||
@@ -69,42 +193,8 @@ typedef struct {
|
||||
};
|
||||
} ncclProfilerEventDescr_v1_t;
|
||||
|
||||
typedef enum {
|
||||
ncclProfilerProxyOpSendPosted,
|
||||
ncclProfilerProxyOpSendRemFifoWait,
|
||||
ncclProfilerProxyOpSendTransmitted,
|
||||
ncclProfilerProxyOpSendDone,
|
||||
ncclProfilerProxyOpRecvPosted,
|
||||
ncclProfilerProxyOpRecvReceived,
|
||||
ncclProfilerProxyOpRecvTransmitted,
|
||||
ncclProfilerProxyOpRecvDone,
|
||||
|
||||
/* Legacy proxy profiler states */
|
||||
ncclProfilerProxyStepSendGPUWait,
|
||||
ncclProfilerProxyStepSendWait,
|
||||
ncclProfilerProxyStepRecvWait,
|
||||
ncclProfilerProxyStepRecvFlushWait,
|
||||
ncclProfilerProxyStepRecvGPUWait,
|
||||
|
||||
/* Legacy proxy control states */
|
||||
ncclProfilerProxyCtrlIdle,
|
||||
ncclProfilerProxyCtrlActive,
|
||||
ncclProfilerProxyCtrlSleep,
|
||||
ncclProfilerProxyCtrlWakeup,
|
||||
ncclProfilerProxyCtrlAppend,
|
||||
ncclProfilerProxyCtrlAppendEnd,
|
||||
} ncclProfilerEventState_v1_t;
|
||||
|
||||
typedef union {
|
||||
struct {
|
||||
size_t transSize;
|
||||
int steps;
|
||||
} proxyOp;
|
||||
|
||||
struct {
|
||||
int appendedProxyOps;
|
||||
} proxyCtrl;
|
||||
} ncclProfilerEventStateArgs_v1_t;
|
||||
typedef ncclProfilerEventState_v2_t ncclProfilerEventState_v1_t;
|
||||
typedef ncclProfilerEventStateArgs_v2_t ncclProfilerEventStateArgs_v1_t;
|
||||
|
||||
typedef struct {
|
||||
const char* name;
|
||||
@@ -142,9 +232,4 @@ typedef struct {
|
||||
ncclResult_t (*finalize)(void* context);
|
||||
} ncclProfiler_v1_t;
|
||||
|
||||
typedef ncclProfilerEventDescr_v1_t ncclProfilerEventDescr_t;
|
||||
typedef ncclProfilerEventState_v1_t ncclProfilerEventState_t;
|
||||
typedef ncclProfilerEventStateArgs_v1_t ncclProfilerEventStateArgs_t;
|
||||
typedef ncclProfiler_v1_t ncclProfiler_t;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -11,6 +11,55 @@
|
||||
#include "nccl.h"
|
||||
#include "nccl_common.h"
|
||||
|
||||
// API to be implemented by external tuner
|
||||
typedef struct {
|
||||
// Name of the tuner
|
||||
const char* name;
|
||||
|
||||
// Initializes tuner states.
|
||||
// Inputs:
|
||||
// - nRanks: number of ranks in current communicator. Each communicator initialize its own tuner.
|
||||
// - nNodes: number of nodes in current communicator.
|
||||
// - logFunction: a logFunction can be useful to integrate logging together with NCCL core.
|
||||
// Outputs:
|
||||
// - context: tuner context object
|
||||
ncclResult_t (*init)(size_t nRanks, size_t nNodes, ncclDebugLogger_t logFunction, void **context);
|
||||
|
||||
// Gets info (algo, protocol, number of ctas and threads) for a given collective.
|
||||
// Inputs:
|
||||
// - context: tuner context object
|
||||
// - collType: collective type , e.g., allreduce, allgather…
|
||||
// - nBytes: collective size in bytes
|
||||
// - numPipeOps: number of operations in the group
|
||||
// - numAlgo: number of algorithms in collCostTable
|
||||
// - numProto: number of protocols in collCostTable
|
||||
// - regBuff: can register user buffer
|
||||
//
|
||||
// Outputs:
|
||||
// - nChannels: number of channels (hence SMs) to be used.
|
||||
//
|
||||
// InOut:
|
||||
// - collCostTable: collective cost table, generated by NCCL core, containing algo|proto|time entries for collType.
|
||||
// NCCL core sets ignored algo/proto cost table entries to -1.0 (NCCL_ALGO_PROTO_IGNORE).
|
||||
//
|
||||
// If getCollInfo() does not return ncclSuccess, NCCL will fall back to the
|
||||
// default tuning for the given collective.
|
||||
// Also, the plugin is allowed to not set any output, or set only the
|
||||
// algorithm and protocol, but not only the algorithm or only the protocol.
|
||||
// Unset fields will be set automatically by NCCL.
|
||||
ncclResult_t (*getCollInfo)(void* context, ncclFunc_t collType, size_t nBytes,
|
||||
int numPipeOps, float** collCostTable, int numAlgo, int numProto,
|
||||
int regBuff, int* nChannels);
|
||||
|
||||
// Terminates the plugin and cleans up any resources that the plugin allocated.
|
||||
// context: tuner context object
|
||||
ncclResult_t (*destroy)(void* context);
|
||||
} ncclTuner_v4_t;
|
||||
|
||||
typedef ncclTuner_v4_t ncclTuner_t;
|
||||
|
||||
#define NCCL_TUNER_PLUGIN_SYMBOL "ncclTunerPlugin_v4"
|
||||
|
||||
// API to be implemented by external tuner
|
||||
typedef struct {
|
||||
// Name of the tuner
|
||||
@@ -55,10 +104,6 @@ typedef struct {
|
||||
ncclResult_t (*destroy)(void* context);
|
||||
} ncclTuner_v3_t;
|
||||
|
||||
typedef ncclTuner_v3_t ncclTuner_t;
|
||||
|
||||
#define NCCL_TUNER_PLUGIN_SYMBOL "ncclTunerPlugin_v3"
|
||||
|
||||
// API to be implemented by external tuner
|
||||
typedef struct {
|
||||
// Name of the tuner
|
||||
|
||||
@@ -25,6 +25,7 @@ typedef struct {
|
||||
} ncclNetDeviceHandle_v7_t;
|
||||
|
||||
typedef ncclNetDeviceHandle_v7_t ncclNetDeviceHandle_v8_t;
|
||||
typedef ncclNetDeviceHandle_v8_t ncclNetDeviceHandle_t;
|
||||
typedef ncclNetDeviceHandle_v8_t ncclNetDeviceHandle_v9_t;
|
||||
typedef ncclNetDeviceHandle_v9_t ncclNetDeviceHandle_t;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -302,7 +302,7 @@ extern ncclNvmlDevicePairInfo ncclNvmlDevicePairs[ncclNvmlMaxDevices][ncclNvmlMa
|
||||
|
||||
struct ncclNvmlCCStatus {
|
||||
bool CCEnabled;
|
||||
bool multiGpuCCEnabled;
|
||||
bool multiGpuProtectedPCIE;
|
||||
};
|
||||
|
||||
// All ncclNvmlFoo() functions call ncclNvmlEnsureInitialized() implicitly.
|
||||
|
||||
@@ -36,9 +36,9 @@ ncclResult_t ncclProfilerStartRecvProxyOpEvent(int sub, struct ncclProxyArgs* ar
|
||||
ncclResult_t ncclProfilerStopProxyOpEvent(int sub, struct ncclProxyArgs* args);
|
||||
|
||||
// Proxy Step Start/Stop Event Wrappers
|
||||
ncclResult_t ncclProfilerStartSendProxyStepEvents(int sub, struct ncclProxyArgs* args, uint64_t stepLo, uint64_t stepHi);
|
||||
ncclResult_t ncclProfilerStartRecvProxyStepEvents(int sub, struct ncclProxyArgs* args, uint64_t stepLo, uint64_t stepHi);
|
||||
ncclResult_t ncclProfilerStopProxyStepEvents(int sub, struct ncclProxyArgs* args, uint64_t stepLo, uint64_t stepHi);
|
||||
ncclResult_t ncclProfilerStartSendProxyStepEvent(int sub, struct ncclProxyArgs* args, int stepId);
|
||||
ncclResult_t ncclProfilerStartRecvProxyStepEvent(int sub, struct ncclProxyArgs* args, int stepId);
|
||||
ncclResult_t ncclProfilerStopProxyStepEvent(int sub, struct ncclProxyArgs* args, int stepId);
|
||||
|
||||
// Proxy Control Start/Stop Events Wrappers
|
||||
ncclResult_t ncclProfilerStartProxyCtrlEvent(void* profilerContext, void** eHandle);
|
||||
@@ -46,7 +46,7 @@ ncclResult_t ncclProfilerStopProxyCtrlEvent(void* eHandle);
|
||||
|
||||
// Record Event Wrappers
|
||||
ncclResult_t ncclProfilerRecordProxyOpEventState(int sub, struct ncclProxyArgs* args, int steps, size_t transSize, ncclProfilerEventState_t eState);
|
||||
ncclResult_t ncclProfilerRecordProxyStepEventStates(int sub, struct ncclProxyArgs* args, uint64_t stepLo, uint64_t stepHi, ncclProfilerEventState_t eState);
|
||||
ncclResult_t ncclProfilerRecordProxyStepEventState(int sub, struct ncclProxyArgs* args, int stepId, ncclProfilerEventState_t eState);
|
||||
ncclResult_t ncclProfilerRecordProxyCtrlEventState(void*eHandle, int appended, ncclProfilerEventState_t eState);
|
||||
|
||||
// Profiler utility functions
|
||||
|
||||
+21
-11
@@ -15,6 +15,7 @@
|
||||
#include <pthread.h>
|
||||
#include "shmutils.h"
|
||||
#include "p2p.h"
|
||||
#include "collectives.h"
|
||||
|
||||
typedef enum : uint8_t {
|
||||
ncclPatternRing,
|
||||
@@ -56,7 +57,11 @@ struct ncclProxyOp {
|
||||
int root;
|
||||
int next;
|
||||
int nsteps;
|
||||
int chunkSize;
|
||||
size_t chunkSize;
|
||||
size_t sliceSize;
|
||||
size_t loopSize;
|
||||
size_t loopOffset;
|
||||
size_t channelSize;
|
||||
uint8_t sliceSteps;
|
||||
uint8_t chunkSteps;
|
||||
uint8_t channelId;
|
||||
@@ -65,13 +70,15 @@ struct ncclProxyOp {
|
||||
uint8_t /*ncclFunc_t*/ coll;
|
||||
uint8_t /*ncclPattern_t*/ pattern;
|
||||
uint8_t protocol;
|
||||
uint8_t algorithm;
|
||||
uint8_t reg;
|
||||
// collnet buffer reg handles
|
||||
// collnet/p2p/coll buffer reg handles
|
||||
void* sendMhandle;
|
||||
void* recvMhandle;
|
||||
uint8_t* sendbuff;
|
||||
uint8_t* recvbuff;
|
||||
|
||||
int isOneRPN;
|
||||
RingAlgorithm *ringAlgo;
|
||||
union ncclProxyOpSpecifics specifics;
|
||||
|
||||
// Profiler plugin
|
||||
@@ -93,19 +100,21 @@ struct ncclProxyOp {
|
||||
struct ncclProxySubArgs {
|
||||
struct ncclProxyConnection* connection;
|
||||
int reg;
|
||||
// p2p mhandle
|
||||
void* mhandle;
|
||||
// collnet handles
|
||||
void* sendMhandle;
|
||||
void* recvMhandle;
|
||||
uint8_t* sendbuff;
|
||||
uint8_t* recvbuff;
|
||||
size_t offset;
|
||||
ssize_t loopSize;
|
||||
ssize_t loopOffset;
|
||||
int channelId;
|
||||
int nsteps;
|
||||
ssize_t nbytes;
|
||||
ssize_t chunkSize;
|
||||
int peer;
|
||||
|
||||
int isOneRPN;
|
||||
RingAlgorithm *ringAlgo;
|
||||
int groupSize; // Number of consecutive sub operations sharing the same recvComm
|
||||
uint64_t base;
|
||||
uint64_t posted;
|
||||
@@ -114,11 +123,14 @@ struct ncclProxySubArgs {
|
||||
uint64_t transmitted;
|
||||
uint64_t done;
|
||||
uint64_t end;
|
||||
int regBufferReady;
|
||||
void* requests[NCCL_STEPS];
|
||||
|
||||
// Profiler plugin
|
||||
int eActivationMask;
|
||||
int rank;
|
||||
pid_t pid;
|
||||
void* profilerContext;
|
||||
void* taskEventHandle;
|
||||
void* opEventHandle;
|
||||
void* stepEventHandles[NCCL_STEPS];
|
||||
@@ -133,10 +145,11 @@ struct ncclProxyArgs {
|
||||
proxyProgressFunc_t progress;
|
||||
int nsubs;
|
||||
int done;
|
||||
int onePPN;
|
||||
uint64_t opCount;
|
||||
int sliceSteps;
|
||||
int chunkSteps;
|
||||
int chunkSize;
|
||||
size_t chunkSize;
|
||||
size_t totalSendSize;
|
||||
size_t totalRecvSize;
|
||||
size_t sendSizePerRound;
|
||||
@@ -146,16 +159,13 @@ struct ncclProxyArgs {
|
||||
uint8_t /*ncclPattern_t*/ pattern;
|
||||
uint8_t /*ncclFunc_t*/ coll;
|
||||
uint8_t protocol;
|
||||
uint8_t algorithm;
|
||||
int state;
|
||||
char* sharedBuff[NCCL_STEPS];
|
||||
int sharedSize[NCCL_STEPS];
|
||||
|
||||
int idle;
|
||||
|
||||
// Profiler plugin
|
||||
pid_t pid;
|
||||
void* profilerContext;
|
||||
|
||||
// Element linking
|
||||
struct ncclProxyArgs* next;
|
||||
struct ncclProxyArgs* nextPeer;
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
/*************************************************************************
|
||||
* Copyright (c) 2016-2024, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* See LICENSE.txt for license information
|
||||
************************************************************************/
|
||||
|
||||
#ifndef NCCL_RAS_H_
|
||||
#define NCCL_RAS_H_
|
||||
|
||||
#include "socket.h"
|
||||
|
||||
// Structure used to communicate data about NCCL ranks from NCCL threads to RAS.
|
||||
struct rasRankInit {
|
||||
union ncclSocketAddress addr;
|
||||
pid_t pid;
|
||||
int cudaDev;
|
||||
int nvmlDev;
|
||||
};
|
||||
|
||||
ncclResult_t ncclRasCommInit(struct ncclComm* comm, struct rasRankInit* myRank);
|
||||
ncclResult_t ncclRasCommFini(const struct ncclComm* comm);
|
||||
ncclResult_t ncclRasAddRanks(struct rasRankInit* ranks, int nranks);
|
||||
|
||||
#endif // !NCCL_RAS_H_
|
||||
@@ -6,6 +6,9 @@
|
||||
#include <cuda.h>
|
||||
#include <stdint.h>
|
||||
|
||||
int64_t ncclParamLocalRegister();
|
||||
int64_t ncclParamGraphRegister();
|
||||
|
||||
enum {
|
||||
NET_REG_COMPLETE = 0x01,
|
||||
NVLS_REG_COMPLETE = 0x02,
|
||||
@@ -20,16 +23,21 @@ struct ncclPeerRegIpcAddr {
|
||||
uintptr_t* hostPeerRmtAddrs;
|
||||
};
|
||||
|
||||
struct ncclRegNetHandles {
|
||||
void* handle;
|
||||
struct ncclProxyConnector* proxyConn;
|
||||
struct ncclRegNetHandles* next;
|
||||
};
|
||||
|
||||
struct ncclReg {
|
||||
// common attributes
|
||||
size_t pages;
|
||||
int refs;
|
||||
int localRefs;
|
||||
int graphRefs;
|
||||
uintptr_t addr;
|
||||
uint32_t state;
|
||||
// net reg
|
||||
int nDevs;
|
||||
int devs[MAXCHANNELS];
|
||||
void** handles;
|
||||
struct ncclRegNetHandles* netHandleHead;
|
||||
// nvls reg
|
||||
uintptr_t baseAddr;
|
||||
size_t baseSize;
|
||||
@@ -50,11 +58,12 @@ struct ncclRegCache {
|
||||
struct ncclReg **slots;
|
||||
int capacity, population;
|
||||
uintptr_t pageSize;
|
||||
void* sComms[MAXCHANNELS];
|
||||
void* rComms[MAXCHANNELS];
|
||||
};
|
||||
|
||||
ncclResult_t ncclRegCleanup(struct ncclComm* comm);
|
||||
ncclResult_t ncclRegFind(struct ncclComm* comm, const void* data, size_t size, struct ncclReg** reg);
|
||||
ncclResult_t ncclCommGraphRegister(const ncclComm_t comm, void* buff, size_t size, void** handle);
|
||||
ncclResult_t ncclCommGraphDeregister(const ncclComm_t comm, struct ncclReg *handle);
|
||||
ncclResult_t ncclRegLocalIsValid(struct ncclReg *reg, bool *isValid);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include "nccl.h"
|
||||
|
||||
typedef void* ncclShmHandle_t;
|
||||
ncclResult_t ncclShmOpen(char* shmPath, size_t shmSize, void** shmPtr, void** devShmPtr, int refcount, ncclShmHandle_t* handle);
|
||||
ncclResult_t ncclShmOpen(char* shmPath, size_t shmPathSize, size_t shmSize, void** shmPtr, void** devShmPtr, int refcount, ncclShmHandle_t* handle);
|
||||
ncclResult_t ncclShmClose(ncclShmHandle_t handle);
|
||||
ncclResult_t ncclShmUnlink(ncclShmHandle_t handle);
|
||||
|
||||
|
||||
+14
-12
@@ -17,9 +17,6 @@
|
||||
|
||||
#define MAX_IFS 16
|
||||
#define MAX_IF_NAME_SIZE 16
|
||||
#define SLEEP_INT 1000 // connection retry sleep interval in usec
|
||||
#define RETRY_REFUSED_TIMES 2e4 // connection refused retry times before reporting a timeout (20 sec)
|
||||
#define RETRY_TIMEDOUT_TIMES 3 // connection timed out retry times (each one can take 20s)
|
||||
#define SOCKET_NAME_MAXLEN (NI_MAXHOST+NI_MAXSERV)
|
||||
#define NCCL_SOCKET_MAGIC 0x564ab9f2fc4b9d6cULL
|
||||
|
||||
@@ -39,9 +36,10 @@ enum ncclSocketState {
|
||||
ncclSocketStateConnectPolling = 5,
|
||||
ncclSocketStateConnected = 6,
|
||||
ncclSocketStateReady = 7,
|
||||
ncclSocketStateClosed = 8,
|
||||
ncclSocketStateError = 9,
|
||||
ncclSocketStateNum = 10
|
||||
ncclSocketStateTerminating = 8,
|
||||
ncclSocketStateClosed = 9,
|
||||
ncclSocketStateError = 10,
|
||||
ncclSocketStateNum = 11
|
||||
};
|
||||
|
||||
enum ncclSocketType {
|
||||
@@ -49,14 +47,14 @@ enum ncclSocketType {
|
||||
ncclSocketTypeBootstrap = 1,
|
||||
ncclSocketTypeProxy = 2,
|
||||
ncclSocketTypeNetSocket = 3,
|
||||
ncclSocketTypeNetIb = 4
|
||||
ncclSocketTypeNetIb = 4,
|
||||
ncclSocketTypeRasNetwork = 5
|
||||
};
|
||||
|
||||
struct ncclSocket {
|
||||
int fd;
|
||||
int acceptFd;
|
||||
int timedOutRetries;
|
||||
int refusedRetries;
|
||||
int errorRetries;
|
||||
union ncclSocketAddress addr;
|
||||
volatile uint32_t* abortFlag;
|
||||
int asyncFlag;
|
||||
@@ -64,15 +62,18 @@ struct ncclSocket {
|
||||
int salen;
|
||||
uint64_t magic;
|
||||
enum ncclSocketType type;
|
||||
int customRetry;
|
||||
int finalizeCounter; // Used to keep track of initial handshake for async sockets.
|
||||
char finalizeBuffer[sizeof(uint64_t)]; // Used to keep track of initial handshake for async sockets.
|
||||
};
|
||||
|
||||
const char *ncclSocketToString(union ncclSocketAddress *addr, char *buf, const int numericHostForm = 1);
|
||||
const char *ncclSocketToString(const union ncclSocketAddress *addr, char *buf, const int numericHostForm = 1);
|
||||
ncclResult_t ncclSocketGetAddrFromString(union ncclSocketAddress* ua, const char* ip_port_pair);
|
||||
int ncclFindInterfaceMatchSubnet(char* ifNames, union ncclSocketAddress* localAddrs, union ncclSocketAddress* remoteAddr, int ifNameMaxSize, int maxIfs);
|
||||
int ncclFindInterfaces(char* ifNames, union ncclSocketAddress *ifAddrs, int ifNameMaxSize, int maxIfs);
|
||||
|
||||
// Initialize a socket
|
||||
ncclResult_t ncclSocketInit(struct ncclSocket* sock, union ncclSocketAddress* addr = NULL, uint64_t magic = NCCL_SOCKET_MAGIC, enum ncclSocketType type = ncclSocketTypeUnknown, volatile uint32_t* abortFlag = NULL, int asyncFlag = 0);
|
||||
ncclResult_t ncclSocketInit(struct ncclSocket* sock, const union ncclSocketAddress* addr = NULL, uint64_t magic = NCCL_SOCKET_MAGIC, enum ncclSocketType type = ncclSocketTypeUnknown, volatile uint32_t* abortFlag = NULL, int asyncFlag = 0, int customRetry = 0);
|
||||
// Create a listening socket. sock->addr can be pre-filled with IP & port info. sock->fd is set after a successful call
|
||||
ncclResult_t ncclSocketListen(struct ncclSocket* sock);
|
||||
ncclResult_t ncclSocketGetAddr(struct ncclSocket* sock, union ncclSocketAddress* addr);
|
||||
@@ -88,11 +89,12 @@ ncclResult_t ncclSocketSetFd(int fd, struct ncclSocket* sock);
|
||||
#define NCCL_SOCKET_SEND 0
|
||||
#define NCCL_SOCKET_RECV 1
|
||||
|
||||
ncclResult_t ncclSocketProgress(int op, struct ncclSocket* sock, void* ptr, int size, int* offset);
|
||||
ncclResult_t ncclSocketProgress(int op, struct ncclSocket* sock, void* ptr, int size, int* offset, int* closed = NULL);
|
||||
ncclResult_t ncclSocketWait(int op, struct ncclSocket* sock, void* ptr, int size, int* offset);
|
||||
ncclResult_t ncclSocketSend(struct ncclSocket* sock, void* ptr, int size);
|
||||
ncclResult_t ncclSocketRecv(struct ncclSocket* sock, void* ptr, int size);
|
||||
ncclResult_t ncclSocketSendRecv(struct ncclSocket* sendSock, void* sendPtr, int sendSize, struct ncclSocket* recvSock, void* recvPtr, int recvSize);
|
||||
ncclResult_t ncclSocketTryRecv(struct ncclSocket* sock, void* ptr, int size, int* closed, bool blocking);
|
||||
ncclResult_t ncclSocketShutdown(struct ncclSocket* sock, int how);
|
||||
ncclResult_t ncclSocketClose(struct ncclSocket* sock);
|
||||
#endif
|
||||
|
||||
@@ -28,7 +28,6 @@ extern struct ncclTransport netTransport;
|
||||
extern struct ncclTransport collNetTransport;
|
||||
|
||||
extern struct ncclTransport* ncclTransports[];
|
||||
|
||||
// Forward declarations
|
||||
struct ncclRing;
|
||||
struct ncclConnector;
|
||||
@@ -115,16 +114,16 @@ struct ncclTransport {
|
||||
};
|
||||
|
||||
ncclResult_t ncclTransportP2pConnect(struct ncclComm* comm, int channelId, int nrecv, int* peerRecv, int nsend, int* peerSend, int connIndex);
|
||||
ncclResult_t ncclTransportP2pSetup(struct ncclComm* comm, struct ncclTopoGraph* graph, int connIndex, int* highestTransportType=NULL);
|
||||
ncclResult_t ncclTransportP2pSetup(struct ncclComm* comm, struct ncclTopoGraph* graph, int connIndex);
|
||||
ncclResult_t ncclTransportCheckP2pType(struct ncclComm* comm, bool* intraNodeP2pSupport, bool* directMode);
|
||||
|
||||
ncclResult_t ncclNvlsInit(struct ncclComm* comm);
|
||||
ncclResult_t ncclNvlsSetup(struct ncclComm* comm, struct ncclComm* parent);
|
||||
ncclResult_t ncclNvlsBufferSetup(struct ncclComm* comm);
|
||||
ncclResult_t ncclNvlsTreeConnect(struct ncclComm* comm);
|
||||
ncclResult_t ncclNvlsGraphRegisterBuffer(struct ncclComm *comm, const void *sendbuff, void *recvbuff, size_t sendbuffSize, size_t recvbuffSize, bool *outRegBufUsed, void **outRegBufSend, void **outRegBufRecv, struct ncclIntruQueue<struct ncclCommCallback, &ncclCommCallback::next>* cleanupQueue, int* nCleanupQueueElts);
|
||||
ncclResult_t ncclNvlsLocalRegisterBuffer(struct ncclComm *comm, const void *sendbuff, void *recvbuff, size_t sendbuffSize, size_t recvbuffSize, bool *outRegBufUsed, void **outRegBufSend, void **outRegBufRecv);
|
||||
ncclResult_t ncclNvlsDeregBuffer(CUmemGenericAllocationHandle *mcHandler, CUdeviceptr ptr, int dev, size_t size);
|
||||
ncclResult_t ncclNvlsGraphRegisterBuffer(struct ncclComm *comm, const void *sendbuff, void *recvbuff, size_t sendbuffSize, size_t recvbuffSize, int *outRegBufUsed, void **outRegBufSend, void **outRegBufRecv, struct ncclIntruQueue<struct ncclCommCallback, &ncclCommCallback::next>* cleanupQueue, int* nCleanupQueueElts);
|
||||
ncclResult_t ncclNvlsLocalRegisterBuffer(struct ncclComm *comm, const void *sendbuff, void *recvbuff, size_t sendbuffSize, size_t recvbuffSize, int *outRegBufUsed, void **outRegBufSend, void **outRegBufRecv);
|
||||
ncclResult_t ncclNvlsDeregBuffer(struct ncclComm* comm, CUmemGenericAllocationHandle *mcHandler, CUdeviceptr ptr, int dev, size_t size);
|
||||
ncclResult_t ncclNvlsFree(struct ncclComm* comm);
|
||||
|
||||
enum { collNetRecv=0, collNetSend=1 };
|
||||
@@ -143,4 +142,13 @@ ncclResult_t ncclCollNetSetup(ncclComm_t comm, ncclComm_t parent, struct ncclTop
|
||||
ncclResult_t ncclCollNetChainBufferSetup(ncclComm_t comm);
|
||||
ncclResult_t ncclCollNetDirectBufferSetup(ncclComm_t comm);
|
||||
|
||||
ncclResult_t ncclNetDeregBuffer(struct ncclComm* comm, struct ncclProxyConnector* proxyConn, void* handle);
|
||||
ncclResult_t ncclNetLocalRegisterBuffer(ncclComm* comm, const void* userbuff, size_t buffSize, struct ncclConnector** peerConns, int nPeers, int* outRegBufFlag, void** outHandle);
|
||||
ncclResult_t ncclNetGraphRegisterBuffer(ncclComm* comm, const void* userbuff, size_t buffSize, struct ncclConnector** peerConns, int nPeers, int* outRegBufFlag, void** outHandle, struct ncclIntruQueue<struct ncclCommCallback, &ncclCommCallback::next>* cleanupQueue, int* nCleanupQueueElts);
|
||||
|
||||
ncclResult_t ncclRegisterP2pIpcBuffer(struct ncclComm* comm, void* userbuff, size_t size, int peerRank, int* regFlag, void** regAddr, struct ncclIntruQueue<struct ncclCommCallback, &ncclCommCallback::next>* cleanupQueue);
|
||||
ncclResult_t ncclRegisterP2pNetBuffer(struct ncclComm* comm, void* userbuff, size_t size, struct ncclConnector* conn, int* regFlag, void** handle, struct ncclIntruQueue<struct ncclCommCallback, &ncclCommCallback::next>* cleanupQueue);
|
||||
ncclResult_t ncclRegisterCollBuffers(struct ncclComm* comm, struct ncclTaskColl* info, void* outRegBufSend[NCCL_MAX_LOCAL_RANKS], void* outRegBufRecv[NCCL_MAX_LOCAL_RANKS], struct ncclIntruQueue<struct ncclCommCallback, &ncclCommCallback::next>* cleanupQueue, bool* regNeedConnect);
|
||||
ncclResult_t ncclRegisterCollNvlsBuffers(struct ncclComm* comm, struct ncclTaskColl* info, void* outRegBufSend[NCCL_MAX_LOCAL_RANKS], void* outRegBufRecv[NCCL_MAX_LOCAL_RANKS], struct ncclIntruQueue<struct ncclCommCallback, &ncclCommCallback::next>* cleanupQueue, bool* regNeedConnect);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -49,8 +49,7 @@ inline uint64_t clockNano() {
|
||||
return uint64_t(ts.tv_sec)*1000*1000*1000 + ts.tv_nsec;
|
||||
}
|
||||
|
||||
/* get any bytes of random data from /dev/urandom, return 0 if it succeeds; else
|
||||
* return -1 */
|
||||
/* get any bytes of random data from /dev/urandom, return ncclSuccess (0) if it succeeds. */
|
||||
inline ncclResult_t getRandomData(void* buffer, size_t bytes) {
|
||||
ncclResult_t ret = ncclSuccess;
|
||||
if (bytes > 0) {
|
||||
|
||||
Reference in New Issue
Block a user