파일
rocm-systems/src/include/enqueue.h
T

133 라인
4.7 KiB
C++
Raw 일반 보기 히스토리

2018-09-24 16:06:59 -07:00
/*************************************************************************
2022-01-07 06:39:55 -08:00
* Copyright (c) 2015-2022, NVIDIA CORPORATION. All rights reserved.
2018-09-24 16:06:59 -07:00
*
* See LICENSE.txt for license information
************************************************************************/
#ifndef NCCL_ENQUEUE_H_
#define NCCL_ENQUEUE_H_
2019-11-19 14:57:39 -08:00
#include "comm.h"
2018-09-24 16:06:59 -07:00
#include "group.h"
2019-11-19 14:57:39 -08:00
#include "collectives.h"
2019-03-14 19:39:20 -07:00
2021-07-08 14:12:04 -07:00
#define NCCL_MIN_CHANNEL_SIZE (NCCL_LL_THREAD_THRESHOLD*64)
#define NCCL_AGG_CHANNEL_SIZE (1LL << 21) /* 2 MiB, ideal per-channel size to fully utilize bandwidth */
2021-04-12 16:00:11 -07:00
size_t ncclKernMaxLocalSize();
2018-12-13 15:56:12 -08:00
ncclResult_t ncclEnqueueCheck(struct ncclInfo* info);
2020-05-12 14:40:18 -07:00
ncclResult_t ncclCpuBarrierIn(struct ncclComm* comm, int* isLast);
ncclResult_t ncclCpuBarrierLast(struct ncclComm* comm);
ncclResult_t ncclCpuBarrierOut(struct ncclComm* comm);
2021-04-12 16:00:11 -07:00
ncclResult_t ncclLaunchBarrier(struct ncclComm* comm);
ncclResult_t ncclLaunchKernel(ncclComm_t comm);
ncclResult_t ncclRecordEvents(struct ncclComm* comm);
ncclResult_t ncclLaunchReset(ncclComm_t comm);
ncclResult_t ncclSetupP2pKernel(struct ncclInfo* info);
ncclResult_t ncclSetupAsyncKernels(struct ncclComm* comm);
template<int USING_CUDA_GRAPH>
void CUDART_CB ncclEnqueueHostSetup(void* arg);
ncclResult_t ncclGetCudaGraph(ncclComm_t comm, cudaGraph_t* graph);
ncclResult_t ncclCudaGraphHostSetup(ncclComm_t comm, cudaGraph_t graph);
2018-09-24 16:06:59 -07:00
2021-09-08 13:56:25 -07:00
struct ncclBuffRegInfo {
2022-01-07 06:39:55 -08:00
void* sendbuffsBase[NCCL_MAX_LOCAL_RANKS];
void* recvbuffsBase[NCCL_MAX_LOCAL_RANKS];
void* sendbuffs[NCCL_MAX_LOCAL_RANKS];
void* recvbuffs[NCCL_MAX_LOCAL_RANKS];
2021-09-08 13:56:25 -07:00
int nBuffs;
};
2021-04-12 16:00:11 -07:00
// Enqueue information (for kernel and proxy) for each operation
struct ncclQueueElem {
2022-01-07 06:39:55 -08:00
struct ncclWork work;
struct ncclProxyOp proxyOp;
2021-09-08 13:56:25 -07:00
struct ncclBuffRegInfo buffRegInfo;
2021-04-12 16:00:11 -07:00
};
2021-07-08 14:12:04 -07:00
typedef ncclRecyclableList<struct ncclQueueElem> ncclQueueElemList;
2021-04-12 16:00:11 -07:00
// Structure passed to CUDA graph
struct ncclQueueInfo {
ncclComm_t comm;
int maxChannels; // Dynamic version of gridDim
ncclResult_t ret; // Return value of host setup call
2021-09-08 13:56:25 -07:00
int nRegBuffs;
2021-07-08 14:12:04 -07:00
ncclQueueElemList* elemList;
2021-04-12 16:00:11 -07:00
};
2021-07-08 14:12:04 -07:00
static ncclResult_t ncclCreateQueueInfo(struct ncclQueueInfo** eqInfo, ncclComm_t comm) {
NCCLCHECK(ncclCalloc(eqInfo, 1));
(*eqInfo)->comm = comm;
(*eqInfo)->elemList = new ncclQueueElemList();
2021-09-08 13:56:25 -07:00
(*eqInfo)->comm->nQueueInfoCreated++;
2021-04-12 16:00:11 -07:00
return ncclSuccess;
}
// Reset element queue
static ncclResult_t ncclResetQueueInfo(struct ncclQueueInfo* eqInfo) {
if (eqInfo == NULL) return ncclInternalError;
eqInfo->maxChannels = 0;
eqInfo->ret = ncclSuccess;
2021-09-08 13:56:25 -07:00
eqInfo->nRegBuffs = 0;
2021-07-08 14:12:04 -07:00
eqInfo->elemList->recycle();
2021-04-12 16:00:11 -07:00
return ncclSuccess;
}
// Destroy enqueue info space
// used by both CUDA graph and non CUDA graph
static void ncclDestroyQueueInfo(void* ptr) {
if (ptr == NULL) return;
struct ncclQueueInfo* eqInfo = (struct ncclQueueInfo*)ptr;
2021-09-08 13:56:25 -07:00
struct ncclComm* comm = eqInfo->comm;
// Close IPC mem handles for registered buffers
struct ncclQueueElem* eqElem = eqInfo->elemList->begin();
#if 0
// Ideally, the deregistration should happen here
// but currently the destroy function of CUDA objects does not allow CUDA API calls
while (eqElem != NULL) {
for (int i=0; i<eqElem->buffRegInfo.nBuffs; i++) {
2022-01-07 06:39:55 -08:00
if (i == eqInfo->comm->localRank) continue;
2021-09-08 13:56:25 -07:00
CUDACHECKIGNORE(cudaIpcCloseMemHandle(eqElem->buffRegInfo.sendbuffsBase[i]));
CUDACHECKIGNORE(cudaIpcCloseMemHandle(eqElem->buffRegInfo.recvbuffsBase[i]));
}
eqElem = eqInfo->elemList->getNext();
}
#else
// Instead, we push these pointers to a pool owned by ncclComm
// and asks a helper thread to close mem handles
struct ncclGraphHelperResources* res = comm->graphHelperResources;
int ipcTailOld = 0;
if (res == NULL || (!comm->graphHelperThread) || eqInfo->nRegBuffs == 0) goto skip;
pthread_mutex_lock(&res->threadLock);
ipcTailOld = res->ipcTail;
while (eqElem != NULL) {
for (int i=0; i<eqElem->buffRegInfo.nBuffs; i++) {
if (eqElem->buffRegInfo.sendbuffsBase[i] != NULL) {
res->ipcBases[res->ipcTail] = eqElem->buffRegInfo.sendbuffsBase[i];
res->ipcTail = (res->ipcTail+1)%NCCL_IPC_POOL_SIZE;
}
if (eqElem->buffRegInfo.recvbuffsBase[i] != NULL) {
res->ipcBases[res->ipcTail] = eqElem->buffRegInfo.recvbuffsBase[i];
res->ipcTail = (res->ipcTail+1)%NCCL_IPC_POOL_SIZE;
}
}
eqElem = eqInfo->elemList->getNext();
}
if (res->ipcTail != ipcTailOld) {
res->threadState = ThreadStart;
TRACE(NCCL_COLL, "CUDA Graph destroy function signaling helper thread with %d IPC handles", res->ipcTail-ipcTailOld);
pthread_cond_signal(&res->threadCond);
}
pthread_mutex_unlock(&res->threadLock);
#endif
skip:
2021-07-08 14:12:04 -07:00
delete eqInfo->elemList;
2021-04-12 16:00:11 -07:00
free(eqInfo);
2021-09-08 13:56:25 -07:00
comm->nQueueInfoDestroyed++;
return;
2021-04-12 16:00:11 -07:00
}
2018-09-24 16:06:59 -07:00
#endif // End include guard