Files
rocm-systems/src/transport/net.cc
T

403 řádky
17 KiB
C++
Surový Normální zobrazení Historie

2018-09-24 16:06:59 -07:00
/*************************************************************************
2018-12-13 15:56:12 -08:00
* Copyright (c) 2016-2019, NVIDIA CORPORATION. All rights reserved.
2018-09-24 16:06:59 -07:00
*
* See LICENSE.txt for license information
************************************************************************/
2019-11-19 14:57:39 -08:00
#include "comm.h"
2018-09-24 16:06:59 -07:00
#include "net.h"
2019-11-19 14:57:39 -08:00
#include "graph.h"
2018-09-24 16:06:59 -07:00
struct netConnectInfo {
ncclNetHandle_t netHandle;
};
struct netSendResources {
void* netSendComm;
struct ncclSendMem* hostSendMem;
struct ncclRecvMem* hostRecvMem;
struct ncclSendMem* devHostSendMem;
struct ncclRecvMem* devHostRecvMem;
int netDev;
2018-11-13 10:37:20 -08:00
int useGdr;
2018-12-13 15:56:12 -08:00
int buffSize;
void* mhandle;
void* llMhandle;
2019-11-19 14:57:39 -08:00
void* ll128Mhandle;
2018-12-13 15:56:12 -08:00
struct ncclRecvMem* devRecvMem;
uint64_t step;
2018-09-24 16:06:59 -07:00
uint64_t llLastCleaning;
};
struct netRecvResources {
void* netListenComm;
void* netRecvComm;
struct ncclSendMem* hostSendMem;
struct ncclRecvMem* hostRecvMem;
struct ncclSendMem* devHostSendMem;
struct ncclRecvMem* devHostRecvMem;
int netDev;
2018-11-13 10:37:20 -08:00
int useGdr;
2018-12-13 15:56:12 -08:00
int buffSize;
void* mhandle;
void* llMhandle;
2019-11-19 14:57:39 -08:00
void* ll128Mhandle;
2018-12-13 15:56:12 -08:00
struct ncclRecvMem* devRecvMem;
uint64_t step;
2018-09-24 16:06:59 -07:00
uint64_t llLastCleaning;
};
2019-11-19 14:57:39 -08:00
/* Determine if two peers can communicate with NET */
ncclResult_t netCanConnect(int* ret, struct ncclTopoSystem* topo, struct ncclTopoGraph* graph, struct ncclPeerInfo* info1, struct ncclPeerInfo* info2) {
*ret = 1;
2018-09-24 16:06:59 -07:00
return ncclSuccess;
}
NCCL_PARAM(NetGdrRead, "NET_GDR_READ", -2);
2018-11-13 10:37:20 -08:00
NCCL_PARAM(NetGdrLevel, "NET_GDR_LEVEL", PATH_PHB);
2019-11-19 14:57:39 -08:00
static ncclResult_t netGetGdrSupport(struct ncclTopoSystem* topo, int64_t busId, int netDev, int read, int* useGdr) {
2018-11-13 10:37:20 -08:00
*useGdr = 0;
if (read) { // For reads (sends) only enable under certain conditions
int gdrReadParam = ncclParamNetGdrRead();
if (gdrReadParam == 0) return ncclSuccess;
2018-12-13 15:56:12 -08:00
if (gdrReadParam < 0) {
int nvlink;
2019-11-19 14:57:39 -08:00
NCCLCHECK(ncclTopoHasNvlink(topo, busId, &nvlink));
2018-12-13 15:56:12 -08:00
if (!nvlink) return ncclSuccess;
2018-11-13 10:37:20 -08:00
}
}
// Check if we are close enough that it makes sense to enable GDR
int netGdrLevel = ncclParamNetGdrLevel();
2019-11-19 14:57:39 -08:00
int distance;
NCCLCHECK(ncclTopoNetDistance(topo, busId, netDev, &distance));
2018-11-13 10:37:20 -08:00
if (distance >= netGdrLevel) {
2019-11-19 14:57:39 -08:00
INFO(NCCL_NET,"NET/%s : GPU Direct RDMA Disabled for GPU %lx / HCA %d (distance %d >= %d)", ncclNetName(), busId, netDev, distance, netGdrLevel);
2018-11-13 10:37:20 -08:00
return ncclSuccess;
}
// Finally, check if the NIC supports it
int flags;
2019-11-19 14:57:39 -08:00
NCCLCHECK(ncclNetPtrSupport(netDev, &flags));
2018-12-04 14:42:28 -08:00
if ((flags & NCCL_PTR_CUDA) == 0) return ncclSuccess;
2018-11-13 10:37:20 -08:00
*useGdr = 1;
2019-11-19 14:57:39 -08:00
INFO(NCCL_NET,"NET/%s : GPU Direct RDMA Enabled for GPU %lx / HCA %d (distance %d < %d), read %d", ncclNetName(), busId, netDev, distance, netGdrLevel, read);
2018-11-13 10:37:20 -08:00
return ncclSuccess;
}
2018-09-24 16:06:59 -07:00
/* Determine if we will use this transport for this peer and return connect
* information for this peer */
2019-11-19 14:57:39 -08:00
ncclResult_t netSendSetup(struct ncclTopoSystem* topo, struct ncclTopoGraph* graph, struct ncclPeerInfo* myInfo, struct ncclPeerInfo* peerInfo, struct ncclConnect* connectInfo, struct ncclConnector* send, int buffSize, int channelId) {
2018-09-24 16:06:59 -07:00
struct netSendResources* resources;
NCCLCHECK(ncclCalloc(&resources, 1));
2018-12-13 15:56:12 -08:00
send->transportResources = resources;
2019-11-19 14:57:39 -08:00
NCCLCHECK(ncclTopoGetNetDev(graph, 1, channelId, &resources->netDev));
NCCLCHECK(netGetGdrSupport(topo, myInfo->busId, resources->netDev, 1, &resources->useGdr));
2018-09-24 16:06:59 -07:00
2018-12-13 15:56:12 -08:00
int sendSize = sizeof(struct ncclSendMem);
NCCLCHECK(ncclCudaHostAlloc((void**)&resources->hostSendMem, (void**)&resources->devHostSendMem, sendSize));
2018-09-24 16:06:59 -07:00
2018-12-13 15:56:12 -08:00
int recvSize = offsetof(struct ncclRecvMem, buff)+buffSize;
2018-11-13 10:37:20 -08:00
if (resources->useGdr) {
2018-12-13 15:56:12 -08:00
NCCLCHECK(ncclCudaCalloc((char**)(&resources->devRecvMem), recvSize));
2018-09-24 16:06:59 -07:00
}
2018-12-13 15:56:12 -08:00
NCCLCHECK(ncclCudaHostAlloc((void**)&resources->hostRecvMem, (void**)&resources->devHostRecvMem, recvSize));
resources->buffSize = buffSize;
2018-09-24 16:06:59 -07:00
2019-11-19 14:57:39 -08:00
INFO(NCCL_INIT|NCCL_NET,"Ring %02d : %d[%lx] -> %d[%lx] [send] via NET/%s/%d%s", channelId, myInfo->rank, myInfo->busId, peerInfo->rank, peerInfo->busId, ncclNetName(), resources->netDev,
2018-12-13 15:56:12 -08:00
resources->useGdr ? "/GDRDMA" : "");
2018-09-24 16:06:59 -07:00
return ncclSuccess;
}
2019-11-19 14:57:39 -08:00
ncclResult_t netRecvSetup(struct ncclTopoSystem* topo, struct ncclTopoGraph* graph, struct ncclPeerInfo* myInfo, struct ncclPeerInfo* peerInfo, struct ncclConnect* connectInfo, struct ncclConnector* recv, int buffSize, int channelId) {
2018-09-24 16:06:59 -07:00
struct netRecvResources* resources;
NCCLCHECK(ncclCalloc(&resources, 1));
2018-12-13 15:56:12 -08:00
recv->transportResources = resources;
2018-09-24 16:06:59 -07:00
2019-11-19 14:57:39 -08:00
NCCLCHECK(ncclTopoGetNetDev(graph, 0, channelId, &resources->netDev));
NCCLCHECK(netGetGdrSupport(topo, myInfo->busId, resources->netDev, 0, &resources->useGdr));
2018-09-24 16:06:59 -07:00
int sendSize = sizeof(struct ncclSendMem);
NCCLCHECK(ncclCudaHostAlloc((void**)&resources->hostSendMem, (void**)&resources->devHostSendMem, sendSize));
2018-12-13 15:56:12 -08:00
int recvSize = offsetof(struct ncclRecvMem, buff)+buffSize;
if (resources->useGdr) {
NCCLCHECK(ncclCudaCalloc((char**)(&resources->devRecvMem), recvSize));
}
2018-09-24 16:06:59 -07:00
NCCLCHECK(ncclCudaHostAlloc((void**)&resources->hostRecvMem, (void**)&resources->devHostRecvMem, recvSize));
2018-12-13 15:56:12 -08:00
resources->buffSize = buffSize;
2018-09-24 16:06:59 -07:00
2019-11-19 14:57:39 -08:00
INFO(NCCL_INIT|NCCL_NET,"Ring %02d : %d[%lx] -> %d[%lx] [receive] via NET/%s/%d%s", channelId, peerInfo->rank, peerInfo->busId, myInfo->rank, myInfo->busId, ncclNetName(), resources->netDev,
2018-12-13 15:56:12 -08:00
resources->useGdr ? "/GDRDMA" : "");
2018-09-24 16:06:59 -07:00
struct netConnectInfo* info = (struct netConnectInfo*) connectInfo;
NCCLCHECK(ncclNetListen(resources->netDev, &info->netHandle, &resources->netListenComm));
return ncclSuccess;
}
ncclResult_t netSendConnect(struct ncclConnect* connectInfo, struct ncclConnector* send) {
// Setup device pointers
struct netSendResources* resources = (struct netSendResources*)send->transportResources;
2018-12-13 15:56:12 -08:00
// Intermediate buffering on GPU for GPU Direct RDMA, but LL buffer is always on host
struct ncclRecvMem* recvMem = resources->useGdr ? resources->devRecvMem : resources->devHostRecvMem;
send->conn.buff = recvMem->buff;
send->conn.llBuff = resources->devHostRecvMem->llBuff;
2019-11-19 14:57:39 -08:00
send->conn.ll128Buff = recvMem->ll128Buff;
2018-12-13 15:56:12 -08:00
// Head/Tail/Opcount/Fifos are always on host
2018-09-24 16:06:59 -07:00
send->conn.tail = &resources->devHostRecvMem->tail;
2018-12-13 15:56:12 -08:00
send->conn.opCountRem = &resources->devHostRecvMem->opCount;
2018-09-24 16:06:59 -07:00
send->conn.fifo = resources->devHostRecvMem->sizesFifo;
2018-12-13 15:56:12 -08:00
send->conn.head = &resources->devHostSendMem->head;
send->conn.opCountLoc = &resources->devHostSendMem->opCount;
for (int i=0; i<NCCL_STEPS; i++) send->conn.fifo[i] = -1;
2018-09-24 16:06:59 -07:00
// Connect to remote peer
struct netConnectInfo* info = (struct netConnectInfo*)connectInfo;
NCCLCHECK(ncclNetConnect(resources->netDev, info->netHandle, &resources->netSendComm));
2018-12-13 15:56:12 -08:00
NCCLCHECK(ncclNetRegMr(resources->netSendComm, recvMem->buff, resources->buffSize,
resources->useGdr ? NCCL_PTR_CUDA : NCCL_PTR_HOST, &resources->mhandle));
NCCLCHECK(ncclNetRegMr(resources->netSendComm, resources->devHostRecvMem->llBuff,
NCCL_LL_BUFF_SIZE, NCCL_PTR_HOST, &resources->llMhandle));
2019-11-19 14:57:39 -08:00
NCCLCHECK(ncclNetRegMr(resources->netSendComm, recvMem->ll128Buff, NCCL_LL128_BUFF_SIZE,
resources->useGdr ? NCCL_PTR_CUDA : NCCL_PTR_HOST, &resources->ll128Mhandle));
2018-12-13 15:56:12 -08:00
2018-09-24 16:06:59 -07:00
return ncclSuccess;
}
/* Connect to this peer */
ncclResult_t netRecvConnect(struct ncclConnect* connectInfo, struct ncclConnector* recv) {
// Setup device pointers
struct netRecvResources* resources = (struct netRecvResources*)recv->transportResources;
2018-12-13 15:56:12 -08:00
// Intermediate buffering on GPU for GPU Direct RDMA
struct ncclRecvMem* recvMem = resources->useGdr ? resources->devRecvMem : resources->devHostRecvMem;
recv->conn.buff = recvMem->buff;
recv->conn.llBuff = recvMem->llBuff;
2019-11-19 14:57:39 -08:00
recv->conn.ll128Buff = recvMem->ll128Buff;
2018-09-24 16:06:59 -07:00
2018-12-13 15:56:12 -08:00
// Head/Tail/Opcount are always on host
recv->conn.tail = &resources->devHostRecvMem->tail;
recv->conn.opCountLoc = &resources->devHostRecvMem->opCount;
recv->conn.head = &resources->devHostSendMem->head;
recv->conn.opCountRem = &resources->devHostSendMem->opCount;
2018-09-24 16:06:59 -07:00
2018-12-13 15:56:12 -08:00
// Finish connection establishment from remote peer
2018-09-24 16:06:59 -07:00
NCCLCHECK(ncclNetAccept(resources->netListenComm, &resources->netRecvComm));
NCCLCHECK(ncclNetCloseListen(resources->netListenComm));
2018-12-13 15:56:12 -08:00
NCCLCHECK(ncclNetRegMr(resources->netRecvComm, recvMem->buff, resources->buffSize,
resources->useGdr ? NCCL_PTR_CUDA : NCCL_PTR_HOST, &resources->mhandle));
NCCLCHECK(ncclNetRegMr(resources->netRecvComm, recvMem->llBuff, NCCL_LL_BUFF_SIZE,
resources->useGdr ? NCCL_PTR_CUDA : NCCL_PTR_HOST, &resources->llMhandle));
2019-11-19 14:57:39 -08:00
NCCLCHECK(ncclNetRegMr(resources->netRecvComm, recvMem->ll128Buff, NCCL_LL128_BUFF_SIZE,
resources->useGdr ? NCCL_PTR_CUDA : NCCL_PTR_HOST, &resources->ll128Mhandle));
2018-12-13 15:56:12 -08:00
2018-09-24 16:06:59 -07:00
return ncclSuccess;
}
ncclResult_t netSendFree(void* transportResources) {
struct netSendResources* resources = (struct netSendResources*)transportResources;
NCCLCHECK(ncclCudaHostFree(resources->hostSendMem));
2018-12-13 15:56:12 -08:00
NCCLCHECK(ncclNetDeregMr(resources->netSendComm, resources->mhandle));
NCCLCHECK(ncclNetDeregMr(resources->netSendComm, resources->llMhandle));
2019-11-19 14:57:39 -08:00
NCCLCHECK(ncclNetDeregMr(resources->netSendComm, resources->ll128Mhandle));
2018-09-24 16:06:59 -07:00
NCCLCHECK(ncclCudaHostFree(resources->hostRecvMem));
2018-11-13 10:37:20 -08:00
if (resources->useGdr)
2018-12-13 15:56:12 -08:00
CUDACHECK(cudaFree(resources->devRecvMem));
2018-09-24 16:06:59 -07:00
NCCLCHECK(ncclNetCloseSend(resources->netSendComm));
free(resources);
return ncclSuccess;
}
ncclResult_t netRecvFree(void* transportResources) {
struct netRecvResources* resources = (struct netRecvResources*)transportResources;
NCCLCHECK(ncclCudaHostFree(resources->hostSendMem));
2018-12-13 15:56:12 -08:00
NCCLCHECK(ncclNetDeregMr(resources->netRecvComm, resources->mhandle));
NCCLCHECK(ncclNetDeregMr(resources->netRecvComm, resources->llMhandle));
2019-11-19 14:57:39 -08:00
NCCLCHECK(ncclNetDeregMr(resources->netRecvComm, resources->ll128Mhandle));
2018-09-24 16:06:59 -07:00
NCCLCHECK(ncclCudaHostFree(resources->hostRecvMem));
2018-12-13 15:56:12 -08:00
if (resources->useGdr)
CUDACHECK(cudaFree(resources->devRecvMem));
2018-09-24 16:06:59 -07:00
NCCLCHECK(ncclNetCloseRecv(resources->netRecvComm));
free(resources);
return ncclSuccess;
}
ncclResult_t netSendProxy(struct ncclProxyArgs* args) {
2018-12-13 15:56:12 -08:00
struct netSendResources* resources = (struct netSendResources*) (args->connector->transportResources);
if (args->state == ncclProxyOpReady) {
// Update opCount
resources->hostRecvMem->opCount = args->opCount;
// Round to next multiple of sliceSteps
resources->step = ROUNDUP(resources->step, args->chunkSteps);
args->head = resources->step;
args->tail = resources->step;
args->end = args->head + args->nsteps;
args->state = ncclProxyOpProgress;
}
if (args->state == ncclProxyOpProgress) {
args->idle = 1;
if (args->head < args->end) {
if (args->tail < args->end && args->tail < args->head + NCCL_STEPS) {
volatile int* sizesFifo = resources->hostRecvMem->sizesFifo;
2019-03-14 19:39:20 -07:00
volatile uint64_t* recvTail = &resources->hostRecvMem->tail;
2019-11-19 14:57:39 -08:00
if (args->protocol == NCCL_PROTO_LL128) {
int stepSize = NCCL_LL128_BUFF_SIZE/NCCL_STEPS;
if (args->tail < *recvTail) {
int buffSlot = args->tail%NCCL_STEPS;
if (sizesFifo[buffSlot] != -1) {
struct ncclRecvMem* localMem = resources->useGdr ? resources->devRecvMem : resources->hostRecvMem;
char* localBuff = (char*)localMem->ll128Buff;
int ready = resources->useGdr;
if (!ready) {
// When data is in sysmem, we need to wait until all flags are correct since the GPU only
// called threadfence()
uint64_t flag = args->tail + 1;
int nFifoLines = DIVUP(sizesFifo[buffSlot], sizeof(uint64_t)*NCCL_LL128_LINEELEMS);
volatile uint64_t* lines = (volatile uint64_t*)(localBuff+buffSlot*stepSize);
ready = 1;
for (int i=0; i<nFifoLines; i++) {
if (lines[i*NCCL_LL128_LINEELEMS+NCCL_LL128_DATAELEMS] != flag) { ready = 0; break; }
}
}
if (ready) {
// Send through network
NCCLCHECK(ncclNetIsend(resources->netSendComm, localBuff+buffSlot*stepSize, sizesFifo[buffSlot], resources->ll128Mhandle, args->requests+buffSlot));
if (args->requests[buffSlot] != NULL) {
sizesFifo[buffSlot] = -1;
// Make sure size is reset to zero before we update the head.
__sync_synchronize();
args->tail += args->sliceSteps;
args->idle = 0;
}
}
}
}
} else if (args->protocol == NCCL_PROTO_LL) {
2018-12-13 15:56:12 -08:00
int buffSlot = args->tail%NCCL_STEPS;
int size = sizesFifo[buffSlot];
if (size != -1) {
2019-03-14 19:39:20 -07:00
uint32_t flag = NCCL_LL_FLAG(args->tail + 1);
2018-12-13 15:56:12 -08:00
int nFifoLines = DIVUP(size, sizeof(union ncclLLFifoLine));
size = nFifoLines * sizeof(union ncclLLFifoLine);
union ncclLLFifoLine* lines = resources->hostRecvMem->llBuff+buffSlot*NCCL_LL_SLICE_LINES;
int ready = 1;
for (int i=0; i<nFifoLines; i++) {
volatile uint32_t *f1 = &lines[i].flag1;
volatile uint32_t *f2 = &lines[i].flag2;
if (f1[0] != flag || f2[0] != flag) { ready = 0; break; }
}
if (ready) {
NCCLCHECK(ncclNetIsend(resources->netSendComm, lines, size, resources->llMhandle, args->requests+buffSlot));
if (args->requests[buffSlot] != NULL) {
sizesFifo[buffSlot] = -1;
// Make sure size is reset to zero before we update the head.
__sync_synchronize();
args->tail += args->sliceSteps;
args->idle = 0;
}
}
2018-09-24 16:06:59 -07:00
}
2019-03-14 19:39:20 -07:00
} else if (args->tail < *recvTail) {
2018-12-13 15:56:12 -08:00
int stepSize = args->channel->buffSize/NCCL_STEPS;
2019-11-19 14:57:39 -08:00
struct ncclRecvMem* localMem = resources->useGdr ? resources->devRecvMem : resources->hostRecvMem;
2018-12-13 15:56:12 -08:00
// Send through network
int buffSlot = args->tail%NCCL_STEPS;
2019-11-19 14:57:39 -08:00
if (sizesFifo[buffSlot] != -1) {
NCCLCHECK(ncclNetIsend(resources->netSendComm, localMem->buff+buffSlot*stepSize, sizesFifo[buffSlot], resources->mhandle, args->requests+buffSlot));
if (args->requests[buffSlot] != NULL) {
sizesFifo[buffSlot] = -1;
// Make sure size is reset to zero before we update the head.
__sync_synchronize();
args->tail += args->sliceSteps;
args->idle = 0;
}
2018-11-19 17:43:50 -08:00
}
2018-09-24 16:06:59 -07:00
}
}
2018-12-13 15:56:12 -08:00
if (args->head < args->tail) {
int done;
int buffSlot = args->head%NCCL_STEPS;
NCCLCHECK(ncclNetTest(args->requests[buffSlot], &done, NULL));
if (done) {
args->head += args->sliceSteps;
resources->hostSendMem->head = args->head;
args->idle = 0;
2018-09-24 16:06:59 -07:00
}
}
}
2018-12-13 15:56:12 -08:00
if (args->head == args->end) {
resources->step = args->end;
args->idle = 0;
2019-03-14 19:39:20 -07:00
args->state = ncclProxyOpNone;
2018-09-24 16:06:59 -07:00
}
}
return ncclSuccess;
}
ncclResult_t netRecvProxy(struct ncclProxyArgs* args) {
2018-12-13 15:56:12 -08:00
struct netRecvResources* resources = (struct netRecvResources*) (args->connector->transportResources);
if (args->state == ncclProxyOpReady) {
// Update opCount
resources->hostSendMem->opCount = args->opCount;
// Round to next multiple of sliceSteps
resources->step = ROUNDUP(resources->step, args->chunkSteps);
args->head = resources->step;
args->tail = resources->step;
args->end = args->head + args->nsteps;
args->state = ncclProxyOpProgress;
2018-09-24 16:06:59 -07:00
}
2018-12-13 15:56:12 -08:00
if (args->state == ncclProxyOpProgress) {
args->idle = 1;
2019-11-19 14:57:39 -08:00
int stepSize = ( args->protocol == NCCL_PROTO_LL ? NCCL_LL_BUFF_SIZE : args->protocol == NCCL_PROTO_LL128 ? NCCL_LL128_BUFF_SIZE : args->channel->buffSize ) / NCCL_STEPS;
2018-12-13 15:56:12 -08:00
if (args->head < args->end) {
struct ncclRecvMem* localMem = resources->useGdr ? resources->devRecvMem : resources->hostRecvMem;
2019-11-19 14:57:39 -08:00
char* localBuff = args->protocol == NCCL_PROTO_LL ? (char*)localMem->llBuff : args->protocol == NCCL_PROTO_LL128 ? (char*)localMem->ll128Buff : localMem->buff;
void* mhandle = args->protocol == NCCL_PROTO_LL ? resources->llMhandle : args->protocol == NCCL_PROTO_LL128 ? resources->ll128Mhandle : resources->mhandle;
2019-03-14 19:39:20 -07:00
volatile uint64_t* sendHead = &resources->hostSendMem->head;
if ((args->tail < args->head + NCCL_STEPS) && (args->tail < *sendHead + NCCL_STEPS) && (args->tail < args->end)) {
2018-12-13 15:56:12 -08:00
int buffSlot = args->tail%NCCL_STEPS;
int sliceSize = stepSize * args->sliceSteps;
NCCLCHECK(ncclNetIrecv(resources->netRecvComm, localBuff+buffSlot*stepSize, sliceSize, mhandle, args->requests+buffSlot));
if (args->requests[buffSlot] != NULL) {
args->tail += args->sliceSteps;
args->idle = 0;
}
2018-11-19 17:43:50 -08:00
}
2018-12-13 15:56:12 -08:00
if (args->tail > args->head) {
int buffSlot = args->head%NCCL_STEPS;
int done, size;
NCCLCHECK(ncclNetTest(args->requests[buffSlot], &done, &size));
if (done) {
args->head += args->sliceSteps;
2019-11-19 14:57:39 -08:00
if (args->protocol == NCCL_PROTO_SIMPLE) {
2018-12-13 15:56:12 -08:00
if (resources->useGdr) ncclNetFlush(resources->netRecvComm, localBuff+buffSlot*stepSize, size, mhandle);
resources->hostRecvMem->tail = args->head;
}
args->idle = 0;
2018-09-24 16:06:59 -07:00
}
}
}
2018-12-13 15:56:12 -08:00
if (args->head == args->end) {
resources->step = args->end;
args->idle = 0;
2019-03-14 19:39:20 -07:00
args->state = ncclProxyOpNone;
2018-09-24 16:06:59 -07:00
}
}
return ncclSuccess;
}
struct ncclTransport netTransport = {
"NET",
netCanConnect,
{ netSendSetup, netSendConnect, netSendFree, netSendProxy },
{ netRecvSetup, netRecvConnect, netRecvFree, netRecvProxy }
};