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

443 lines
18 KiB
C++
Raw Normal View History

2018-09-24 16:06:59 -07:00
/*************************************************************************
2020-05-12 14:40:18 -07:00
* Copyright (c) 2016-2020, NVIDIA CORPORATION. All rights reserved.
2020-01-15 17:54:27 -07:00
* Modifications Copyright (c) 2019-2020 Advanced Micro Devices, Inc. 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"
2020-05-28 00:15:47 +00:00
#include <sys/time.h>
#include <numaif.h>
2018-09-24 16:06:59 -07:00
struct netConnectInfo {
ncclNetHandle_t netHandle;
};
2020-05-12 14:40:18 -07:00
#define LOC_HOSTMEM 0
#define LOC_DEVMEM 1
#define LOC_COUNT 2
2018-09-24 16:06:59 -07:00
struct netSendResources {
void* netSendComm;
2020-05-12 14:40:18 -07:00
struct ncclSendMem* sendMem;
struct ncclRecvMem* recvMem;
2018-09-24 16:06:59 -07:00
int netDev;
2018-11-13 10:37:20 -08:00
int useGdr;
2020-05-12 14:40:18 -07:00
char* buffers[LOC_COUNT];
int buffSizes[LOC_COUNT];
void* mhandles[LOC_COUNT];
void** mhandlesProto[NCCL_NUM_PROTOCOLS];
2018-12-13 15:56:12 -08:00
uint64_t step;
2018-09-24 16:06:59 -07:00
uint64_t llLastCleaning;
};
struct netRecvResources {
void* netListenComm;
void* netRecvComm;
2020-05-12 14:40:18 -07:00
struct ncclSendMem* sendMem;
struct ncclRecvMem* recvMem;
2018-09-24 16:06:59 -07:00
int netDev;
2018-11-13 10:37:20 -08:00
int useGdr;
2020-05-12 14:40:18 -07:00
char* buffers[LOC_COUNT];
int buffSizes[LOC_COUNT];
void* mhandles[LOC_COUNT];
void** mhandlesProto[NCCL_NUM_PROTOCOLS];
2018-12-13 15:56:12 -08:00
uint64_t step;
2018-09-24 16:06:59 -07:00
uint64_t llLastCleaning;
2019-07-05 15:43:00 -07:00
uint32_t* curr_hdp_reg; // Curr GPU in ring (for rdma transport use only)
2018-09-24 16:06:59 -07:00
};
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;
}
/* Determine if we will use this transport for this peer and return connect
* information for this peer */
2020-05-12 14:40:18 -07:00
ncclResult_t netSendSetup(struct ncclTopoSystem* topo, struct ncclTopoGraph* graph, struct ncclPeerInfo* myInfo, struct ncclPeerInfo* peerInfo, struct ncclConnect* connectInfo, struct ncclConnector* send, 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;
2020-05-12 14:40:18 -07:00
NCCLCHECK(ncclTopoGetNetDev(topo, myInfo->rank, graph, channelId, &resources->netDev));
2020-01-16 16:02:42 -08:00
NCCLCHECK(ncclTopoCheckGdr(topo, myInfo->busId, resources->netDev, 1, &resources->useGdr));
2018-09-24 16:06:59 -07:00
2020-05-12 14:40:18 -07:00
NCCLCHECK(ncclCudaHostCalloc(&resources->sendMem, 1));
NCCLCHECK(ncclCudaHostCalloc(&resources->recvMem, 1));
send->conn.direct |= resources->useGdr ? NCCL_DIRECT_NIC : 0;
send->conn.tail = &resources->recvMem->tail;
send->conn.opCountRem = &resources->recvMem->opCount;
send->conn.fifo = resources->recvMem->sizesFifo;
send->conn.head = &resources->sendMem->head;
send->conn.opCountLoc = &resources->sendMem->opCount;
for (int i=0; i<NCCL_STEPS; i++) send->conn.fifo[i] = -1;
int protoLoc[NCCL_NUM_PROTOCOLS];
for (int p=0; p<NCCL_NUM_PROTOCOLS; p++) {
protoLoc[p] = p != NCCL_PROTO_LL && resources->useGdr ? LOC_DEVMEM : LOC_HOSTMEM;
}
2018-09-24 16:06:59 -07:00
2020-05-12 14:40:18 -07:00
int buffSizes[NCCL_NUM_PROTOCOLS];
for (int p=0; p<NCCL_NUM_PROTOCOLS; p++) {
// Only allocate buffers for simple for p2p connections
buffSizes[p] = graph == NULL && p != NCCL_PROTO_SIMPLE ? 0 : send->comm->buffSizes[p];
resources->buffSizes[protoLoc[p]] += buffSizes[p];
2018-09-24 16:06:59 -07:00
}
2020-05-12 14:40:18 -07:00
if (resources->buffSizes[LOC_DEVMEM]) {
NCCLCHECK(ncclCudaCalloc(resources->buffers+LOC_DEVMEM, resources->buffSizes[LOC_DEVMEM], resources->useGdr));
2020-05-12 14:40:18 -07:00
}
char line[16];
2020-05-12 14:40:18 -07:00
if (resources->buffSizes[LOC_HOSTMEM]) {
NCCLCHECK(ncclCudaHostCalloc(resources->buffers+LOC_HOSTMEM, resources->buffSizes[LOC_HOSTMEM]));
int status[1] = {-1};
line[0]= 0;
if (!move_pages(0, 1, (void **)resources->buffers+LOC_HOSTMEM, NULL, status, 0))
sprintf(line, "/MEM%d", status[0]);
2020-05-12 14:40:18 -07:00
}
int offsets[LOC_COUNT];
offsets[LOC_HOSTMEM] = offsets[LOC_DEVMEM] = 0;
for (int p=0; p<NCCL_NUM_PROTOCOLS; p++) {
resources->mhandlesProto[p] = resources->mhandles+protoLoc[p];
send->conn.buffs[p] = resources->buffers[protoLoc[p]] + offsets[protoLoc[p]];
offsets[protoLoc[p]] += buffSizes[p];
}
INFO(NCCL_INIT|NCCL_NET,"Channel %02d : %d[%lx] -> %d[%lx] [send] via NET/%s/%d%s", channelId, myInfo->rank, myInfo->busId, peerInfo->rank, peerInfo->busId, ncclNetName(), resources->netDev,
resources->useGdr ? "/GDRDMA" : line);
2018-09-24 16:06:59 -07:00
return ncclSuccess;
}
2020-05-12 14:40:18 -07:00
ncclResult_t netRecvSetup(struct ncclTopoSystem* topo, struct ncclTopoGraph* graph, struct ncclPeerInfo* myInfo, struct ncclPeerInfo* peerInfo, struct ncclConnect* connectInfo, struct ncclConnector* recv, 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
2020-05-12 14:40:18 -07:00
NCCLCHECK(ncclTopoGetNetDev(topo, myInfo->rank, graph, channelId, &resources->netDev));
2020-01-16 16:02:42 -08:00
NCCLCHECK(ncclTopoCheckGdr(topo, myInfo->busId, resources->netDev, 0, &resources->useGdr));
2018-09-24 16:06:59 -07:00
2020-05-12 14:40:18 -07:00
NCCLCHECK(ncclCudaHostCalloc(&resources->sendMem, 1));
NCCLCHECK(ncclCudaHostCalloc(&resources->recvMem, 1));
recv->conn.direct |= resources->useGdr ? NCCL_DIRECT_NIC : 0;
recv->conn.tail = &resources->recvMem->tail;
recv->conn.opCountLoc = &resources->recvMem->opCount;
recv->conn.head = &resources->sendMem->head;
recv->conn.opCountRem = &resources->sendMem->opCount;
int protoLoc[NCCL_NUM_PROTOCOLS];
for (int p=0; p<NCCL_NUM_PROTOCOLS; p++) {
protoLoc[p] = resources->useGdr ? LOC_DEVMEM : LOC_HOSTMEM;
}
int buffSizes[NCCL_NUM_PROTOCOLS];
for (int p=0; p<NCCL_NUM_PROTOCOLS; p++) {
// Only allocate buffers for simple for p2p connections
buffSizes[p] = graph == NULL && p != NCCL_PROTO_SIMPLE ? 0 : recv->comm->buffSizes[p];
resources->buffSizes[protoLoc[p]] += buffSizes[p];
}
if (resources->buffSizes[LOC_DEVMEM]) {
NCCLCHECK(ncclCudaCalloc(resources->buffers+LOC_DEVMEM, resources->buffSizes[LOC_DEVMEM], resources->useGdr));
2020-05-12 14:40:18 -07:00
}
char line[16];
2020-05-12 14:40:18 -07:00
if (resources->buffSizes[LOC_HOSTMEM]) {
NCCLCHECK(ncclCudaHostCalloc(resources->buffers+LOC_HOSTMEM, resources->buffSizes[LOC_HOSTMEM]));
int status[1] = {-1};
line[0]= 0;
if (!move_pages(0, 1, (void **)resources->buffers+LOC_HOSTMEM, NULL, status, 0))
sprintf(line, "/MEM%d", status[0]);
2020-05-12 14:40:18 -07:00
}
2018-09-24 16:06:59 -07:00
2020-05-12 14:40:18 -07:00
int offsets[LOC_COUNT];
offsets[LOC_HOSTMEM] = offsets[LOC_DEVMEM] = 0;
for (int p=0; p<NCCL_NUM_PROTOCOLS; p++) {
resources->mhandlesProto[p] = resources->mhandles+protoLoc[p];
recv->conn.buffs[p] = resources->buffers[protoLoc[p]] + offsets[protoLoc[p]];
offsets[protoLoc[p]] += buffSizes[p];
2018-12-13 15:56:12 -08:00
}
2018-09-24 16:06:59 -07:00
2020-05-12 14:40:18 -07:00
INFO(NCCL_INIT|NCCL_NET,"Channel %02d : %d[%lx] -> %d[%lx] [receive] via NET/%s/%d%s", channelId, peerInfo->rank, peerInfo->busId, myInfo->rank, myInfo->busId, ncclNetName(), resources->netDev,
resources->useGdr ? "/GDRDMA" : line);
2018-09-24 16:06:59 -07:00
struct netConnectInfo* info = (struct netConnectInfo*) connectInfo;
NCCLCHECK(ncclNetListen(resources->netDev, &info->netHandle, &resources->netListenComm));
2020-05-12 14:40:18 -07:00
2018-09-24 16:06:59 -07:00
return ncclSuccess;
}
2020-01-16 16:02:42 -08:00
ncclResult_t netSendConnect(struct ncclConnect* connectInfo, int nranks, int rank, struct ncclConnector* send) {
2018-09-24 16:06:59 -07:00
// Setup device pointers
struct netSendResources* resources = (struct netSendResources*)send->transportResources;
2020-05-12 14:40:18 -07:00
struct netConnectInfo* info = (struct netConnectInfo*)connectInfo;
2018-09-24 16:06:59 -07:00
// Connect to remote peer
NCCLCHECK(ncclNetConnect(resources->netDev, info->netHandle, &resources->netSendComm));
2018-12-13 15:56:12 -08:00
2020-05-12 14:40:18 -07:00
if (resources->buffSizes[LOC_DEVMEM]) {
NCCLCHECK(ncclNetRegMr(resources->netSendComm, resources->buffers[LOC_DEVMEM], resources->buffSizes[LOC_DEVMEM], NCCL_PTR_CUDA, &resources->mhandles[LOC_DEVMEM]));
}
if (resources->buffSizes[LOC_HOSTMEM]) {
NCCLCHECK(ncclNetRegMr(resources->netSendComm, resources->buffers[LOC_HOSTMEM], resources->buffSizes[LOC_HOSTMEM], NCCL_PTR_HOST, &resources->mhandles[LOC_HOSTMEM]));
}
2018-09-24 16:06:59 -07:00
return ncclSuccess;
}
/* Connect to this peer */
2020-01-16 16:02:42 -08:00
ncclResult_t netRecvConnect(struct ncclConnect* connectInfo, int nranks, int rank, struct ncclConnector* recv) {
2018-09-24 16:06:59 -07:00
// Setup device pointers
struct netRecvResources* resources = (struct netRecvResources*)recv->transportResources;
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));
2020-05-12 14:40:18 -07:00
if (resources->buffSizes[LOC_DEVMEM]) {
NCCLCHECK(ncclNetRegMr(resources->netRecvComm, resources->buffers[LOC_DEVMEM], resources->buffSizes[LOC_DEVMEM], NCCL_PTR_CUDA, &resources->mhandles[LOC_DEVMEM]));
}
if (resources->buffSizes[LOC_HOSTMEM]) {
NCCLCHECK(ncclNetRegMr(resources->netRecvComm, resources->buffers[LOC_HOSTMEM], resources->buffSizes[LOC_HOSTMEM], NCCL_PTR_HOST, &resources->mhandles[LOC_HOSTMEM]));
}
2018-09-24 16:06:59 -07:00
return ncclSuccess;
}
ncclResult_t netSendFree(void* transportResources) {
struct netSendResources* resources = (struct netSendResources*)transportResources;
2020-05-12 14:40:18 -07:00
NCCLCHECK(ncclCudaHostFree(resources->sendMem));
NCCLCHECK(ncclCudaHostFree(resources->recvMem));
for (int l=0; l<LOC_COUNT; l++) {
if (resources->buffers[l])
NCCLCHECK(ncclNetDeregMr(resources->netSendComm, resources->mhandles[l]));
}
NCCLCHECK(ncclCudaHostFree(resources->buffers[LOC_HOSTMEM]));
CUDACHECK(hipFree(resources->buffers[LOC_DEVMEM]));
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;
2020-05-12 14:40:18 -07:00
NCCLCHECK(ncclCudaHostFree(resources->sendMem));
NCCLCHECK(ncclCudaHostFree(resources->recvMem));
for (int l=0; l<LOC_COUNT; l++) {
if (resources->buffers[l])
NCCLCHECK(ncclNetDeregMr(resources->netRecvComm, resources->mhandles[l]));
}
NCCLCHECK(ncclCudaHostFree(resources->buffers[LOC_HOSTMEM]));
CUDACHECK(hipFree(resources->buffers[LOC_DEVMEM]));
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
STORE(&resources->recvMem->opCount, args->opCount);
2018-12-13 15:56:12 -08:00
// 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) {
2020-05-12 14:40:18 -07:00
int p = args->protocol;
int stepSize = args->connector->comm->buffSizes[p] / NCCL_STEPS;
char* localBuff = args->connector->conn.buffs[p];
void* mhandle = *(resources->mhandlesProto[p]);
2018-12-13 15:56:12 -08:00
args->idle = 1;
if (args->head < args->end) {
2020-05-12 14:40:18 -07:00
int buffSlot = args->tail%NCCL_STEPS;
2018-12-13 15:56:12 -08:00
if (args->tail < args->end && args->tail < args->head + NCCL_STEPS) {
2020-05-12 14:40:18 -07:00
volatile int* sizesFifo = resources->recvMem->sizesFifo;
volatile uint64_t* recvTail = &resources->recvMem->tail;
2019-11-19 14:57:39 -08:00
if (args->protocol == NCCL_PROTO_LL128) {
2019-11-26 16:33:13 -08:00
if (args->tail < LOAD(recvTail)) {
if (LOAD(sizesFifo+buffSlot) != -1) {
2019-11-19 14:57:39 -08:00
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;
2019-11-26 16:33:13 -08:00
int nFifoLines = DIVUP(LOAD(sizesFifo+buffSlot), sizeof(uint64_t)*NCCL_LL128_LINEELEMS);
2019-11-19 14:57:39 -08:00
volatile uint64_t* lines = (volatile uint64_t*)(localBuff+buffSlot*stepSize);
ready = 1;
for (int i=0; i<nFifoLines; i++) {
2019-11-26 16:33:13 -08:00
if (LOAD(lines+i*NCCL_LL128_LINEELEMS+NCCL_LL128_DATAELEMS) != flag) { ready = 0; break; }
2019-11-19 14:57:39 -08:00
}
}
if (ready) {
// Send through network
NCCLCHECK(ncclNetIsend(resources->netSendComm, localBuff+buffSlot*stepSize, LOAD(sizesFifo+buffSlot), mhandle, args->requests+buffSlot));
2019-11-19 14:57:39 -08:00
if (args->requests[buffSlot] != NULL) {
2019-11-26 16:33:13 -08:00
STORE(sizesFifo+buffSlot, -1);
2019-11-19 14:57:39 -08:00
// 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) {
2019-07-05 15:43:00 -07:00
int size = LOAD(sizesFifo+buffSlot);
2018-12-13 15:56:12 -08:00
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);
2020-05-12 14:40:18 -07:00
union ncclLLFifoLine* lines = (union ncclLLFifoLine*)(localBuff+buffSlot*stepSize);
2018-12-13 15:56:12 -08:00
int ready = 1;
for (int i=0; i<nFifoLines; i++) {
volatile uint32_t *f1 = &lines[i].flag1;
volatile uint32_t *f2 = &lines[i].flag2;
2019-07-05 15:43:00 -07:00
if (LOAD(f1) != flag || LOAD(f2) != flag) { ready = 0; break; }
2018-12-13 15:56:12 -08:00
}
if (ready) {
2020-05-12 14:40:18 -07:00
NCCLCHECK(ncclNetIsend(resources->netSendComm, lines, size, mhandle, args->requests+buffSlot));
2018-12-13 15:56:12 -08:00
if (args->requests[buffSlot] != NULL) {
2019-07-05 15:43:00 -07:00
STORE(sizesFifo+buffSlot, -1);
2018-12-13 15:56:12 -08:00
// 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-07-05 15:43:00 -07:00
} else if (args->tail < LOAD(recvTail)) {
2018-12-13 15:56:12 -08:00
// Send through network
2019-11-26 16:33:13 -08:00
if (LOAD(sizesFifo+buffSlot) != -1) {
2020-05-12 14:40:18 -07:00
NCCLCHECK(ncclNetIsend(resources->netSendComm, localBuff+buffSlot*stepSize, sizesFifo[buffSlot], mhandle, args->requests+buffSlot));
2019-11-19 14:57:39 -08:00
if (args->requests[buffSlot] != NULL) {
2020-05-28 00:15:47 +00:00
#ifdef ENABLE_PROFILING
2020-06-12 22:29:30 +00:00
if (args->channel->active_req == 0) {
gettimeofday(&args->channel->tvs, NULL);
args->channel->sizes = 0;
}
args->channel->active_req ++;
args->channel->sizes += LOAD(sizesFifo+buffSlot);
args->channel->send_byte += LOAD(sizesFifo+buffSlot);
2020-05-28 00:15:47 +00:00
#endif
STORE(sizesFifo+buffSlot, -1);
2019-11-19 14:57:39 -08:00
// 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) {
2020-05-28 00:15:47 +00:00
#ifdef ENABLE_PROFILING
2020-06-12 22:29:30 +00:00
args->channel->active_req --;
if (args->channel->active_req == 0) {
struct timeval tv;
gettimeofday(&tv, NULL);
args->channel->bw_cumulative += (float)args->channel->sizes/((tv.tv_sec - args->channel->tvs.tv_sec)*1000*1000 + tv.tv_usec - args->channel->tvs.tv_usec)/1000.0;
args->channel->bw_count ++;
}
2020-05-28 00:15:47 +00:00
#endif
2018-12-13 15:56:12 -08:00
args->head += args->sliceSteps;
STORE(&resources->sendMem->head, args->head);
2018-12-13 15:56:12 -08:00
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
STORE(&resources->sendMem->opCount, args->opCount);
2018-12-13 15:56:12 -08:00
// 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;
2020-05-12 14:40:18 -07:00
int p = args->protocol;
int stepSize = args->connector->comm->buffSizes[p] / NCCL_STEPS;
char* localBuff = args->connector->conn.buffs[p];
void* mhandle = *(resources->mhandlesProto[p]);
2018-12-13 15:56:12 -08:00
if (args->head < args->end) {
2020-05-12 14:40:18 -07:00
volatile uint64_t* sendHead = &resources->sendMem->head;
2019-07-05 15:43:00 -07:00
if ((args->tail < args->head + NCCL_STEPS) && (args->tail < LOAD(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) {
2020-06-12 22:29:30 +00:00
#ifdef ENABLE_PROFILING
if (args->channel->active_req == 0) {
gettimeofday(&args->channel->tvs, NULL);
args->channel->sizes = 0;
}
args->channel->active_req ++;
#endif
2018-12-13 15:56:12 -08:00
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) {
2020-05-28 00:15:47 +00:00
#ifdef ENABLE_PROFILING
2020-06-12 22:29:30 +00:00
args->channel->active_req --;
args->channel->sizes += size;
args->channel->recv_byte += size;
if (args->channel->active_req == 0) {
2020-05-28 00:15:47 +00:00
struct timeval tv;
gettimeofday(&tv, NULL);
2020-06-12 22:29:30 +00:00
args->channel->bw_cumulative += (float)args->channel->sizes/((tv.tv_sec - args->channel->tvs.tv_sec)*1000*1000 + tv.tv_usec - args->channel->tvs.tv_usec)/1000.0;
args->channel->bw_count ++;
}
2020-05-28 00:15:47 +00:00
#endif
2020-03-16 18:33:48 -07:00
if (resources->useGdr) NCCLCHECK(ncclNetFlush(resources->netRecvComm, localBuff+buffSlot*stepSize, size, mhandle));
STORE(&resources->recvMem->tail, args->head);
2018-12-13 15:56:12 -08:00
}
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 }
};