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
[ROCm/rccl commit: 6aae379278]
This commit is contained in:
+65
-77
@@ -17,6 +17,7 @@
|
||||
#include "graph.h"
|
||||
#include "argcheck.h"
|
||||
#include "tuner.h"
|
||||
#include "ras.h"
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
@@ -182,6 +183,8 @@ static ncclResult_t commFree(ncclComm_t comm) {
|
||||
if (comm == NULL)
|
||||
return ncclSuccess;
|
||||
|
||||
NCCLCHECK(ncclRasCommFini(comm));
|
||||
|
||||
/* in commReclaim, we have guaranteed only last rank which calls ncclCommDestroy() will
|
||||
* free all intra-process communicators; therefore, we only need to focus on local
|
||||
* resource cleanup in commFree(). */
|
||||
@@ -193,7 +196,7 @@ static ncclResult_t commFree(ncclComm_t comm) {
|
||||
}
|
||||
}
|
||||
|
||||
CUDACHECK(cudaMemPoolDestroy(comm->memPool));
|
||||
if (comm->memPool) CUDACHECK(cudaMemPoolDestroy(comm->memPool));
|
||||
|
||||
delete[] comm->userRedOps;
|
||||
|
||||
@@ -421,11 +424,6 @@ static ncclResult_t commAlloc(struct ncclComm* comm, struct ncclComm* parent, in
|
||||
|
||||
ncclIntruQueueConstruct(&comm->eventCallbackQueue);
|
||||
|
||||
// setup intraComm0 and intraRanks 0 to default values to ensure proper cleanup of the communicator
|
||||
comm->intraComm0 = comm;
|
||||
comm->intraRank = 0;
|
||||
comm->intraRanks = 1;
|
||||
|
||||
return ncclSuccess;
|
||||
}
|
||||
|
||||
@@ -435,6 +433,7 @@ static ncclResult_t devCommSetup(ncclComm_t comm) {
|
||||
struct ncclDevCommAndChannels tmpCommAndChans;
|
||||
struct ncclDevCommAndChannels *devCommAndChans = NULL;
|
||||
struct ncclNvmlCCStatus ccStatus;
|
||||
bool ccEnable;
|
||||
|
||||
NCCLCHECKGOTO(ncclStrongStreamAcquireUncaptured(&comm->sharedRes->deviceStream), ret, fail);
|
||||
NCCLCHECKGOTO(ncclCudaCallocAsync(&devCommAndChans, 1, comm->sharedRes->deviceStream.cudaStream), ret, fail);
|
||||
@@ -448,7 +447,7 @@ static ncclResult_t devCommSetup(ncclComm_t comm) {
|
||||
tmpCommAndChans.comm.node = comm->node;
|
||||
tmpCommAndChans.comm.nNodes = comm->nNodes;
|
||||
tmpCommAndChans.comm.abortFlag = comm->abortFlagDev;
|
||||
tmpCommAndChans.comm.isNvlink = ncclTopoPathAllNVLink(comm->topo);
|
||||
tmpCommAndChans.comm.isAllNvlink = comm->isAllNvlink;
|
||||
for (int p=0; p < NCCL_NUM_PROTOCOLS; p++) {
|
||||
tmpCommAndChans.comm.buffSizes[p] = comm->buffSizes[p];
|
||||
}
|
||||
@@ -458,11 +457,9 @@ static ncclResult_t devCommSetup(ncclComm_t comm) {
|
||||
comm->workArgsBytes = std::min<size_t>(ncclParamWorkArgsBytes(), ncclMaxKernelArgsSize(comm->cudaArch));
|
||||
|
||||
memset(&ccStatus, 0, sizeof(ccStatus));
|
||||
if (ncclNvmlGetCCStatus(&ccStatus) == ncclSuccess && ccStatus.CCEnabled) {
|
||||
ccEnable = (ncclSuccess == ncclNvmlGetCCStatus(&ccStatus)) && (ccStatus.CCEnabled || ccStatus.multiGpuProtectedPCIE);
|
||||
if (ccEnable) {
|
||||
comm->workFifoBytes = 0;
|
||||
if (ccStatus.multiGpuCCEnabled == false && comm->rank == 0) {
|
||||
WARN("CC On, Multi-GPU CC Off (No inter-GPU communication protection)");
|
||||
}
|
||||
} else {
|
||||
comm->workFifoBytes = ncclParamWorkFifoBytes();
|
||||
if (0 != (comm->workFifoBytes & (comm->workFifoBytes-1))) {
|
||||
@@ -473,7 +470,7 @@ static ncclResult_t devCommSetup(ncclComm_t comm) {
|
||||
}
|
||||
|
||||
if (comm->rank == 0) {
|
||||
INFO(NCCL_INIT, "CC %s, Multi-GPU CC %s, workFifoBytes %d", ccStatus.CCEnabled ? "On" : "Off", ccStatus.multiGpuCCEnabled ? "On" : "Off", comm->workFifoBytes);
|
||||
INFO(NCCL_INIT, "CC %s, workFifoBytes %d", ccEnable ? "On" : "Off", comm->workFifoBytes);
|
||||
}
|
||||
|
||||
if (ncclGdrCopy != NULL && ncclParamGdrCopyFifoEnable() == 1) {
|
||||
@@ -608,9 +605,6 @@ NCCL_PARAM(P2pPciChunkSize, "P2P_PCI_CHUNKSIZE", (1 << 17)); /* 128 kB */
|
||||
NCCL_PARAM(P2pNvlChunkSize, "P2P_NVL_CHUNKSIZE", (1 << 19)); /* 512 kB */
|
||||
|
||||
static ncclResult_t computeBuffSizes(struct ncclComm* comm) {
|
||||
int cpuArch, cpuVendor, cpuModel;
|
||||
NCCLCHECK(ncclTopoCpuType(comm->topo, &cpuArch, &cpuVendor, &cpuModel));
|
||||
|
||||
int64_t envs[NCCL_NUM_PROTOCOLS] = { ncclParamLlBuffSize(), ncclParamLl128BuffSize(), ncclParamBuffSize() };
|
||||
int defaults[NCCL_NUM_PROTOCOLS] = { DEFAULT_LL_BUFFSIZE, DEFAULT_LL128_BUFFSIZE, DEFAULT_BUFFSIZE };
|
||||
|
||||
@@ -619,7 +613,7 @@ static ncclResult_t computeBuffSizes(struct ncclComm* comm) {
|
||||
}
|
||||
|
||||
if (comm->nNodes > 1) comm->p2pChunkSize = ncclParamP2pNetChunkSize();
|
||||
else if (ncclTopoPathAllNVLink(comm->topo)) comm->p2pChunkSize = ncclParamP2pNvlChunkSize();
|
||||
else if (comm->isAllNvlink) comm->p2pChunkSize = ncclParamP2pNvlChunkSize();
|
||||
else comm->p2pChunkSize = ncclParamP2pPciChunkSize();
|
||||
|
||||
// Make sure P2P chunksize is not larger than coll chunksize.
|
||||
@@ -850,6 +844,14 @@ static ncclResult_t initTransportsRank(struct ncclComm* comm, struct ncclComm* p
|
||||
} while(0);
|
||||
|
||||
timers[TIMER_INIT_TOPO] = clockNano();
|
||||
|
||||
// Dump XML if requested by user
|
||||
const char* dumpXmlFile;
|
||||
dumpXmlFile = ncclGetEnv("NCCL_TOPO_DUMP_FILE");
|
||||
if (dumpXmlFile) {
|
||||
NCCLCHECKGOTO(ncclTopoGetSystem(comm, NULL, dumpXmlFile), ret, fail);
|
||||
}
|
||||
|
||||
// Topo detection / System graph creation
|
||||
NCCLCHECKGOTO(ncclTopoGetSystem(comm, &comm->topo), ret, fail);
|
||||
// Compute paths between GPUs and NICs
|
||||
@@ -1076,9 +1078,9 @@ static ncclResult_t initTransportsRank(struct ncclComm* comm, struct ncclComm* p
|
||||
INFO(NCCL_INIT, "Communicator has %d nodes which is less than CollNet node threshold %d, disabling CollNet", comm->nNodes, collNetNodeThreshold);
|
||||
comm->collNetSupport = 0;
|
||||
}
|
||||
// As long as there is more than 1 rank on any node, we need to disable collnet reg
|
||||
comm->collNetRegSupport = (comm->maxLocalRanks == 1);
|
||||
}
|
||||
comm->isAllNvlink = ncclTopoPathAllNVLink(comm->topo);
|
||||
comm->isOneRPN = (comm->maxLocalRanks == 1);
|
||||
|
||||
NCCLCHECKGOTO(ncclCalloc(&rings, nranks*MAXCHANNELS), ret, fail);
|
||||
NCCLCHECKGOTO(ncclTopoPostset(comm, nodesFirstRank, nodesTreePatterns, allTopoRanks, rings, graphs, parent), ret, fail);
|
||||
@@ -1293,7 +1295,6 @@ static ncclResult_t initTransportsRank(struct ncclComm* comm, struct ncclComm* p
|
||||
// launch NCCL kernels before all cuda mem allocation is complete. That could cause a deadlock.
|
||||
NCCLCHECKGOTO(devCommSetup(comm), ret, fail);
|
||||
timers[TIMER_INIT_CONNECT] = clockNano() - timers[TIMER_INIT_CONNECT];
|
||||
|
||||
/* Local intra-node barrier */
|
||||
NCCLCHECKGOTO(bootstrapIntraNodeBarrier(comm->bootstrap, comm->localRankToRank, comm->localRank, comm->localRanks, comm->localRankToRank[0]), ret, fail);
|
||||
|
||||
@@ -1338,6 +1339,7 @@ struct ncclCommInitRankAsyncJob {
|
||||
// for ncclCommSplit
|
||||
struct ncclComm* parent;
|
||||
int color, key;
|
||||
int splitCount;
|
||||
// name of the function calling
|
||||
char funcName[NCCL_COMMINIT_FUNCNAME_LEN];
|
||||
};
|
||||
@@ -1432,13 +1434,14 @@ static ncclResult_t ncclCommInitRankFunc(struct ncclAsyncJob* job_) {
|
||||
timers[TIMER_INIT_ALLOC] = clockNano();
|
||||
NCCLCHECKGOTO(commAlloc(comm, job->parent, job->nranks, job->myrank), res, fail);
|
||||
timers[TIMER_INIT_ALLOC] = clockNano() - timers[TIMER_INIT_ALLOC];
|
||||
// obtain a unique hash for the comm, re-using part of the parent's hash, commHash is a 64bit struct (=16 hex), add the color
|
||||
// obtain a unique hash for the comm, re-using part of the parent's hash, commHash is a 64bit struct (=16 hex),
|
||||
// add unique split counter and the color
|
||||
ncclUniqueId tmpId;
|
||||
memset(&tmpId,0,sizeof(ncclUniqueId));// must set 0 here to avoid undefined bits
|
||||
snprintf((char*)&tmpId, NCCL_UNIQUE_ID_BYTES, "%016lx-%d", job->parent->commHash, job->color);
|
||||
snprintf((char*)&tmpId, NCCL_UNIQUE_ID_BYTES, "%016lx-%d-%d", job->parent->commHash, job->splitCount, job->color);
|
||||
comm->commHash = getHash(tmpId.internal, NCCL_UNIQUE_ID_BYTES);
|
||||
INFO(NCCL_INIT, "%s comm %p rank %d nranks %d cudaDev %d nvmlDev %d busId %lx parent %p color %d key %d- Init START", job->funcName,
|
||||
comm, comm->rank, comm->nRanks, comm->cudaDev, comm->nvmlDev, comm->busId, job->parent, job->color, job->key);
|
||||
INFO(NCCL_INIT, "%s comm %p rank %d nranks %d cudaDev %d nvmlDev %d busId %lx parent %p splitCount %d color %d key %d- Init START", job->funcName,
|
||||
comm, comm->rank, comm->nRanks, comm->cudaDev, comm->nvmlDev, comm->busId, job->parent, job->splitCount, job->color, job->key);
|
||||
timers[TIMER_INIT_BOOTSTRAP] = clockNano();
|
||||
NCCLCHECKGOTO(bootstrapSplit(comm->commHash, comm, job->parent, job->color, job->key, parentRanks), res, fail);
|
||||
timers[TIMER_INIT_BOOTSTRAP] = clockNano() - timers[TIMER_INIT_BOOTSTRAP];
|
||||
@@ -1474,8 +1477,8 @@ static ncclResult_t ncclCommInitRankFunc(struct ncclAsyncJob* job_) {
|
||||
/* unlink child abort flag. */
|
||||
__atomic_store_n(&job->parent->childAbortFlag, NULL, __ATOMIC_RELEASE);
|
||||
TRACE_CALL("ncclCommSplit(%p, %d, %d, %p, %d, %d)", job->parent, job->color, job->key, comm, comm->rank, comm->nRanks);
|
||||
INFO(NCCL_INIT, "%s comm %p rank %d nranks %d cudaDev %d nvmlDev %d busId %lx parent %p color %d key %d - Init COMPLETE", job->funcName,
|
||||
comm, comm->rank, comm->nRanks, comm->cudaDev, comm->nvmlDev, comm->busId, job->parent, job->color, job->key);
|
||||
INFO(NCCL_INIT, "%s comm %p rank %d nranks %d cudaDev %d nvmlDev %d busId %lx parent %p splitCount %d color %d key %d - Init COMPLETE", job->funcName,
|
||||
comm, comm->rank, comm->nRanks, comm->cudaDev, comm->nvmlDev, comm->busId, job->parent, job->splitCount, job->color, job->key);
|
||||
} else {
|
||||
// the name for the replay tool is ncclCommInitRank for all the variations
|
||||
TRACE_CALL("ncclCommInitRank(%p, %d, 0x%llx, %d, %d)", comm, comm->nRanks, commIdHash, comm->rank, comm->cudaDev);
|
||||
@@ -1716,8 +1719,8 @@ static ncclResult_t ncclCommInitRankDev(ncclComm_t* newcomm, int nranks, int nId
|
||||
comm->startMagic = comm->endMagic = NCCL_MAGIC; // Used to detect comm corruption.
|
||||
*comm->abortFlagRefCount = 1;
|
||||
NCCLCHECKGOTO(parseCommConfig(comm, config), res, fail);
|
||||
/* start with ncclInternalError and will be changed to ncclSuccess if init succeeds. */
|
||||
comm->initState = ncclInternalError;
|
||||
/* start with ncclInProgress and will be changed to ncclSuccess if init succeeds. */
|
||||
comm->initState = ncclInProgress;
|
||||
*newcomm = comm;
|
||||
|
||||
NCCLCHECKGOTO(ncclCalloc(&job, 1), res, fail);
|
||||
@@ -1749,6 +1752,7 @@ static ncclResult_t ncclCommInitRankDev(ncclComm_t* newcomm, int nranks, int nId
|
||||
exit:
|
||||
return ncclGroupErrCheck(res);
|
||||
fail:
|
||||
if (job) ncclCommInitJobFree(job);
|
||||
if (comm) {
|
||||
free(comm->abortFlag);
|
||||
if (comm->abortFlagDev) (void)ncclCudaHostFree((void*)comm->abortFlagDev);
|
||||
@@ -1846,7 +1850,7 @@ ncclResult_t ncclCommInitAll(ncclComm_t* comms, int ndev, const int* devlist) {
|
||||
NCCLCHECKGOTO(ncclGroupEnd(), ret, fail);
|
||||
|
||||
exit:
|
||||
cudaSetDevice(oldDev);
|
||||
(void)cudaSetDevice(oldDev);
|
||||
free(gpuFlags);
|
||||
return ret;
|
||||
fail:
|
||||
@@ -1926,14 +1930,9 @@ fail:
|
||||
static ncclResult_t commDestroySync(struct ncclAsyncJob* job_) {
|
||||
struct ncclCommFinalizeAsyncJob* job = (struct ncclCommFinalizeAsyncJob*) job_;
|
||||
ncclComm_t comm = job->comm;
|
||||
int savedDevice;
|
||||
int commDevice = comm->cudaDev;
|
||||
ncclResult_t ret = ncclSuccess;
|
||||
|
||||
CUDACHECKGOTO(cudaGetDevice(&savedDevice), ret, fail);
|
||||
if (savedDevice != commDevice) {
|
||||
CUDACHECKGOTO(cudaSetDevice(commDevice), ret, fail);
|
||||
}
|
||||
CUDACHECKGOTO(cudaSetDevice(comm->cudaDev), ret, fail);
|
||||
|
||||
TRACE(NCCL_INIT, "Destroying comm %p rank %d abortFlag %d asyncResult %d", comm, comm->rank, *comm->abortFlag, comm->asyncResult);
|
||||
|
||||
@@ -1963,10 +1962,6 @@ static ncclResult_t commDestroySync(struct ncclAsyncJob* job_) {
|
||||
WARN("ncclProxyStop: comm %p (rank = %d) destroys proxy resource error %d", comm, comm->rank, ret);
|
||||
}
|
||||
|
||||
if (savedDevice != commDevice) {
|
||||
CUDACHECKGOTO(cudaSetDevice(savedDevice), ret, fail);
|
||||
}
|
||||
|
||||
exit:
|
||||
return ret;
|
||||
fail:
|
||||
@@ -1974,25 +1969,12 @@ fail:
|
||||
}
|
||||
|
||||
static ncclResult_t commCleanup(ncclComm_t comm) {
|
||||
int savedDevice;
|
||||
int commDevice = comm->cudaDev;
|
||||
|
||||
CUDACHECK(cudaGetDevice(&savedDevice));
|
||||
if (savedDevice != commDevice) {
|
||||
CUDACHECK(cudaSetDevice(commDevice));
|
||||
}
|
||||
|
||||
CUDACHECK(cudaSetDevice(comm->cudaDev));
|
||||
if (comm->tuner != NULL) {
|
||||
NCCLCHECK(comm->tuner->destroy(comm->tunerContext));
|
||||
NCCLCHECK(ncclTunerPluginUnload(comm));
|
||||
}
|
||||
|
||||
NCCLCHECK(commFree(comm));
|
||||
|
||||
if (savedDevice != commDevice) {
|
||||
CUDACHECK(cudaSetDevice(savedDevice));
|
||||
}
|
||||
|
||||
return ncclSuccess;
|
||||
}
|
||||
|
||||
@@ -2099,6 +2081,7 @@ ncclResult_t ncclCommDestroy(ncclComm_t comm) {
|
||||
NVTX3_FUNC_WITH_PARAMS(CommDestroy, CommInitRankSchema, payload)
|
||||
|
||||
TRACE(NCCL_INIT, "comm %p rank %d nRanks %d cudaDev %d busId %lx", comm, rank, nranks, cudaDev, comm->busId);
|
||||
NCCLCHECK(ncclGroupStartInternal());
|
||||
// Try and prevent a double free of the comm struct (user error)
|
||||
if (comm->rank == -1 || comm->nRanks == -1 || comm->cudaDev == -1 || comm->busId == -1) {
|
||||
WARN("comm %p has already been destroyed", comm);
|
||||
@@ -2113,6 +2096,8 @@ ncclResult_t ncclCommDestroy(ncclComm_t comm) {
|
||||
NCCLCHECKGOTO(ncclAsyncLaunch((struct ncclAsyncJob*)job, commReclaim, NULL, free, comm), res, fail);
|
||||
|
||||
exit:
|
||||
ncclGroupErrCheck(res);
|
||||
NCCLCHECK(ncclGroupEndInternal());
|
||||
return res;
|
||||
fail:
|
||||
goto exit;
|
||||
@@ -2124,7 +2109,7 @@ ncclResult_t ncclCommAbort(ncclComm_t comm) {
|
||||
NVTX3_FUNC_RANGE_IN(nccl_domain);
|
||||
return ncclSuccess;
|
||||
}
|
||||
|
||||
NCCLCHECK(ncclGroupStartInternal());
|
||||
// Ask anything that might still be running on the device to quit
|
||||
if (comm->childAbortFlag != nullptr) {
|
||||
__atomic_store_n(comm->childAbortFlag, 1, __ATOMIC_RELEASE);
|
||||
@@ -2152,6 +2137,8 @@ ncclResult_t ncclCommAbort(ncclComm_t comm) {
|
||||
NCCLCHECKGOTO(ncclAsyncLaunch((struct ncclAsyncJob*)job, commReclaim, NULL, free, comm), res, fail);
|
||||
|
||||
exit:
|
||||
ncclGroupErrCheck(res);
|
||||
NCCLCHECK(ncclGroupEndInternal());
|
||||
return ncclSuccess;
|
||||
fail:
|
||||
goto exit;
|
||||
@@ -2218,14 +2205,15 @@ ncclResult_t ncclCommSplit(ncclComm_t comm, int color, int key, ncclComm_t *newc
|
||||
NCCLCHECKGOTO(parseCommConfig(childComm, config), res, fail);
|
||||
}
|
||||
|
||||
/* start with ncclInternalError and will be changed to ncclSuccess if init succeeds. */
|
||||
childComm->initState = ncclInternalError;
|
||||
/* start with ncclInProgress and will be changed to ncclSuccess if init succeeds. */
|
||||
childComm->initState = ncclInProgress;
|
||||
}
|
||||
|
||||
NCCLCHECKGOTO(ncclCalloc(&job, 1), res, fail);
|
||||
job->comm = childComm;
|
||||
job->newcomm = newcomm;
|
||||
job->parent = comm;
|
||||
job->splitCount = ++comm->splitCount;
|
||||
job->color = color;
|
||||
job->key = key;
|
||||
job->cudaDev = comm->cudaDev;
|
||||
@@ -2233,13 +2221,13 @@ ncclResult_t ncclCommSplit(ncclComm_t comm, int color, int key, ncclComm_t *newc
|
||||
NCCLCHECKGOTO(ncclAsyncLaunch((struct ncclAsyncJob*)job, ncclCommInitRankFunc, NULL, free, comm), res, fail);
|
||||
|
||||
exit:
|
||||
cudaSetDevice(oldDev);
|
||||
(void)cudaSetDevice(oldDev);
|
||||
(void)ncclGroupErrCheck(res);
|
||||
NCCLCHECK(ncclGroupEndInternal());
|
||||
return res;
|
||||
fail:
|
||||
if (childComm) {
|
||||
if (comm && !comm->config.splitShare) {
|
||||
if (!comm->config.splitShare) {
|
||||
free(childComm->abortFlag);
|
||||
if (childComm->abortFlagDev) ncclCudaHostFree(childComm->abortFlagDev);
|
||||
free(childComm->abortFlagRefCount);
|
||||
@@ -2347,14 +2335,12 @@ ncclResult_t ncclMemAlloc(void **ptr, size_t size) {
|
||||
|
||||
CUDACHECK(cudaGetDevice(&cudaDev));
|
||||
CUCHECK(cuDeviceGet(¤tDev, cudaDev));
|
||||
if (CUPFN(cuMulticastCreate) != NULL)
|
||||
CUCHECK(cuDeviceGetAttribute(&mcSupport, CU_DEVICE_ATTRIBUTE_MULTICAST_SUPPORTED, currentDev));
|
||||
|
||||
if (mcSupport) {
|
||||
if (ncclCuMemEnable()) {
|
||||
int requestedHandleTypes = CU_MEM_HANDLE_TYPE_POSIX_FILE_DESCRIPTOR;
|
||||
// Query device to see if FABRIC handle support is available
|
||||
flag = 0;
|
||||
(void) CUPFN(cuDeviceGetAttribute(&flag, CU_DEVICE_ATTRIBUTE_HANDLE_TYPE_FABRIC_SUPPORTED, currentDev));;
|
||||
(void) CUPFN(cuDeviceGetAttribute(&flag, CU_DEVICE_ATTRIBUTE_HANDLE_TYPE_FABRIC_SUPPORTED, currentDev));
|
||||
if (flag) requestedHandleTypes |= CU_MEM_HANDLE_TYPE_FABRIC;
|
||||
memprop.type = CU_MEM_ALLOCATION_TYPE_PINNED;
|
||||
memprop.location.type = CU_MEM_LOCATION_TYPE_DEVICE;
|
||||
@@ -2365,18 +2351,24 @@ ncclResult_t ncclMemAlloc(void **ptr, size_t size) {
|
||||
CUCHECK(cuDeviceGetAttribute(&flag, CU_DEVICE_ATTRIBUTE_GPU_DIRECT_RDMA_WITH_CUDA_VMM_SUPPORTED, currentDev));
|
||||
if (flag) memprop.allocFlags.gpuDirectRDMACapable = 1;
|
||||
CUCHECK(cuMemGetAllocationGranularity(&memGran, &memprop, CU_MEM_ALLOC_GRANULARITY_RECOMMENDED));
|
||||
|
||||
/* mc property */
|
||||
CUDACHECK(cudaGetDeviceCount(&dcnt));
|
||||
mcprop.size = size;
|
||||
/* device cnt is a dummy value right now, it might affect mc granularity in the future. */
|
||||
mcprop.numDevices = dcnt;
|
||||
mcprop.handleTypes = requestedHandleTypes;
|
||||
mcprop.flags = 0;
|
||||
CUCHECK(cuMulticastGetGranularity(&mcGran, &mcprop, CU_MULTICAST_GRANULARITY_RECOMMENDED));
|
||||
|
||||
/* only size needs to be aligned to mcGran */
|
||||
ALIGN_SIZE(size, mcGran);
|
||||
if (CUPFN(cuMulticastCreate) != NULL) CUCHECK(cuDeviceGetAttribute(&mcSupport, CU_DEVICE_ATTRIBUTE_MULTICAST_SUPPORTED, currentDev));
|
||||
if (mcSupport) {
|
||||
/* mc property */
|
||||
mcprop.size = size;
|
||||
/* device cnt is a dummy value right now, it might affect mc granularity in the future. */
|
||||
mcprop.numDevices = dcnt;
|
||||
mcprop.handleTypes = requestedHandleTypes;
|
||||
mcprop.flags = 0;
|
||||
CUCHECK(cuMulticastGetGranularity(&mcGran, &mcprop, CU_MULTICAST_GRANULARITY_RECOMMENDED));
|
||||
|
||||
/* only size needs to be aligned to mcGran */
|
||||
ALIGN_SIZE(size, mcGran);
|
||||
} else {
|
||||
ALIGN_SIZE(size, memGran);
|
||||
}
|
||||
|
||||
if (requestedHandleTypes & CU_MEM_HANDLE_TYPE_FABRIC) {
|
||||
/* First try cuMemCreate() with FABRIC handle support and then remove if it fails */
|
||||
CUresult err = CUPFN(cuMemCreate(&handle, size, &memprop, 0));
|
||||
@@ -2403,6 +2395,7 @@ ncclResult_t ncclMemAlloc(void **ptr, size_t size) {
|
||||
accessDesc.flags = CU_MEM_ACCESS_FLAGS_PROT_READWRITE;
|
||||
CUCHECK(cuMemSetAccess((CUdeviceptr)*ptr, size, &accessDesc, 1));
|
||||
}
|
||||
if (0 == p2p && i != cudaDev) INFO(NCCL_ALLOC, "P2P not supported between GPU%d and GPU%d", cudaDev, i);
|
||||
}
|
||||
goto exit;
|
||||
}
|
||||
@@ -2429,18 +2422,13 @@ ncclResult_t ncclMemFree(void *ptr) {
|
||||
CUDACHECK(cudaGetDevice(&saveDevice));
|
||||
#if CUDART_VERSION >= 12010
|
||||
CUdevice ptrDev = 0;
|
||||
int mcSupport = 0;
|
||||
|
||||
if (ptr == NULL) goto fallback;
|
||||
|
||||
if (ncclCudaLibraryInit() != ncclSuccess) goto fallback;
|
||||
|
||||
CUCHECKGOTO(cuPointerGetAttribute((void*)&ptrDev, CU_POINTER_ATTRIBUTE_DEVICE_ORDINAL, (CUdeviceptr)ptr), ret, fail);
|
||||
if (CUPFN(cuMulticastCreate) != NULL)
|
||||
CUCHECKGOTO(cuDeviceGetAttribute(&mcSupport, CU_DEVICE_ATTRIBUTE_MULTICAST_SUPPORTED, ptrDev), ret, fail);
|
||||
|
||||
CUDACHECKGOTO(cudaSetDevice((int)ptrDev), ret, fail);
|
||||
if (mcSupport) {
|
||||
if (ncclCuMemEnable()) {
|
||||
NCCLCHECKGOTO(ncclCuMemFree(ptr), ret, fail);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user