疑問
ncclAsyncMode とは
- Channel とは
- opCount とは
- devComm とは → comm との違い
- ``llmode` とは
NCCL_MAX_OPS とは
AllReduce の動作
AllReduce の main
ncclCommInitRank
ncclAllReduce
ncclCommDestroy
- IF
ncclAsyncModel
- ELSE
ArgsCheck(info)
saveKernel(info)
ncclBarrierEnqueue(info->comm)
ncclBarrierEnqueueWait(info->comm)
ncclEnqueueEvents(info->comm)
computeColl(info, &coll, &proxyArgs) → 何をしている?
blockDim.x を指定 → 何をしている?
- cudaStream 指定
for (int bid=0; bid<coll.args.nChannels, bid++)
For 文の中身
まだ良くわからない
- Block ID ごとにループを回している?
- ループが回る回数は
nChannels だけ → 何を意味している?
computeColl(info, &coll, &proxyArgs)
info から coll へ情報(root, count, send/recv buffers, devComm, opCount)をコピー
info から proxyArgs へ情報(nsteps, sliceSteps, chunkSteps, llMode, opCount)を計算及びコピー
- その際に llMode or treeMode を判定している → これらの違いは?
- llMode の意味は?
- sliceSteps の意味は?
- chunkSteps の意味は?
ncclBarrierEnqueue(info->comm)
基本的には User stream (nccl の通信を呼び出すストリーミ?、デフォルトストリーミかな)、とパラメータで指定されたストリーム(グループの場合もある)の違いによって、 cudaStreamWaitEvent を呼び出すようになっている
ncclCpuBarrierIn → わからない
ncclCpuBarrierLast → わからない
このあとに if(isLast) があるので、intra のプロセスを待ち、最後のプロセスが処理をするようになっている
if (comm->launchMode == ncclComm::GROUP) {
// I'm the last. Launch all operations.
NCCLCHECK(ncclLaunchCooperativeKernelMultiDevice(comm->intraParams, comm->intraCudaDevs, comm->intraRanks, *comm-
}
NCCLCHECK(ncclCpuBarrierLast(comm));
こんな処理
ncclBarrierEnqueueWait(info->comm)
ncclCpuBarrierOut(comm)
- launchMode == GROUP の場合は
ncclBarrierEnqueue でカーネルが呼びされていだが、 PARALLEL の場合はここで呼び出される
comm->channels に格納されている各 channel に対して次の二つのを定義
collStart = channel->collFifiTail
collCount = 0
NCCLCHECK(transportStartProxy(comm));
// Start the network proxies as soon as the kernel has been launched. We can't
// perform any CUDA call between the two or having a cudaFree between the CUDA
// launch and the transportStartProxy call could cause a deadlock.
// Also, starting the proxies after the CUDA launch seems to be better for
// performance (latency).
ncclEnqueueEvents(comm)
必要ならストリームを待つのと、 userStreamSet を初期化する
けっこう単純な関数
ncclResult_t ncclEnqueueEvents(ncclComm_t comm) {
struct cudaLaunchParams *params = comm->myParams;
// Enqueue event after NCCL kernel
CUDACHECK(cudaEventRecord(comm->doneEvent, params->stream));
// Use internal NCCL stream for CGMD/GROUP launch if required or if the user stream is NULL
if (comm->launchMode == ncclComm::GROUP && (comm->groupCudaStream || comm->userStream == NULL)) {
// Create dependency between NCCL internal stream and user stream
CUDACHECK(cudaStreamWaitEvent(comm->userStream, comm->doneEvent, 0));
}
comm->userStreamSet = false;
return ncclSuccess;
}
疑問
ncclAsyncModeとはNCCL_MAX_OPSとはAllReduce の動作
AllReduce の main
ncclCommInitRankncclAllReduceinfo = ncclCommInfo(...)collectives/all_reduce.cc#L14ncclEnqueueCheck(&info)ncclCommDestroyncclEnqueueCheckenqueue.cc#L409ncclAsyncModelArgsCheck(info)saveKernel(info)ncclBarrierEnqueue(info->comm)ncclBarrierEnqueueWait(info->comm)ncclEnqueueEvents(info->comm)saveKernel(info)enqueue.cc#L356computeColl(info, &coll, &proxyArgs)→ 何をしている?blockDim.xを指定 → 何をしている?for (int bid=0; bid<coll.args.nChannels, bid++)For 文の中身
まだ良くわからない
nChannelsだけ → 何を意味している?computeColl(info, &coll, &proxyArgs)infoからcollへ情報(root, count, send/recv buffers, devComm, opCount)をコピーinfoからproxyArgsへ情報(nsteps, sliceSteps, chunkSteps, llMode, opCount)を計算及びコピーncclBarrierEnqueue(info->comm)基本的には User stream (nccl の通信を呼び出すストリーミ?、デフォルトストリーミかな)、とパラメータで指定されたストリーム(グループの場合もある)の違いによって、
cudaStreamWaitEventを呼び出すようになっているncclCpuBarrierIn→ わからないncclCpuBarrierLast→ わからないこのあとに
if(isLast)があるので、intra のプロセスを待ち、最後のプロセスが処理をするようになっているこんな処理
ncclBarrierEnqueueWait(info->comm)ncclCpuBarrierOut(comm)ncclBarrierEnqueueでカーネルが呼びされていだが、 PARALLEL の場合はここで呼び出されるcomm->channelsに格納されている各 channel に対して次の二つのを定義collStart = channel->collFifiTailcollCount = 0NCCLCHECK(transportStartProxy(comm));ncclEnqueueEvents(comm)必要ならストリームを待つのと、
userStreamSetを初期化するけっこう単純な関数