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

268 lines
8.2 KiB
C++
Raw Normal View History

2018-09-24 16:06:59 -07:00
/*************************************************************************
2019-03-14 19:39:20 -07:00
* Copyright (c) 2016-2019, NVIDIA CORPORATION. All rights reserved.
2018-09-24 16:06:59 -07:00
*
* See LICENSE.txt for license information
************************************************************************/
#include "nccl.h"
#include "core.h"
#include "socket.h"
#include "net.h"
#include <assert.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <poll.h>
2018-11-13 10:37:20 -08:00
#include <limits.h>
2018-09-24 16:06:59 -07:00
/* Init functions */
static char ncclNetIfNames[MAX_IF_NAME_SIZE*MAX_IFS];
static union socketAddress ncclNetIfAddrs[MAX_IFS];
static int ncclNetIfs = -1;
pthread_mutex_t ncclSocketLock = PTHREAD_MUTEX_INITIALIZER;
2018-11-13 10:37:20 -08:00
ncclResult_t ncclSocketInit(ncclDebugLogger_t logFunction) {
2018-09-24 16:06:59 -07:00
if (ncclNetIfs == -1) {
pthread_mutex_lock(&ncclSocketLock);
if (ncclNetIfs == -1) {
ncclNetIfs = findInterfaces(ncclNetIfNames, ncclNetIfAddrs, MAX_IF_NAME_SIZE, MAX_IFS);
if (ncclNetIfs <= 0) {
WARN("NET/Socket : no interface found");
2018-11-13 10:37:20 -08:00
return ncclInternalError;
2018-12-13 15:56:12 -08:00
} else {
char line[1024];
char addrline[1024];
line[0] = '\0';
for (int i=0; i<ncclNetIfs; i++) {
snprintf(line+strlen(line), 1023-strlen(line), " [%d]%s:%s", i, ncclNetIfNames+i*MAX_IF_NAME_SIZE,
socketToString(&ncclNetIfAddrs[i].sa, addrline));
}
line[1023] = '\0';
INFO(NCCL_INIT|NCCL_NET,"NET/Socket : Using%s", line);
2018-09-24 16:06:59 -07:00
}
}
pthread_mutex_unlock(&ncclSocketLock);
}
2018-11-13 10:37:20 -08:00
return ncclSuccess;
2018-09-24 16:06:59 -07:00
}
2018-11-13 10:37:20 -08:00
ncclResult_t ncclSocketPtrSupport(int dev, int* supportedTypes) {
*supportedTypes = NCCL_PTR_HOST;
return ncclSuccess;
}
ncclResult_t ncclSocketDevices(int* ndev) {
2018-09-24 16:06:59 -07:00
*ndev = ncclNetIfs;
2018-11-13 10:37:20 -08:00
return ncclSuccess;
}
ncclResult_t ncclSocketPciPath(int dev, char** path) {
char devicepath[PATH_MAX];
snprintf(devicepath, PATH_MAX, "/sys/class/net/%s/device", ncclNetIfNames+dev*MAX_IF_NAME_SIZE);
*path = realpath(devicepath, NULL);
if (*path == NULL) {
INFO(NCCL_NET|NCCL_INIT, "Could not find real path of %s", devicepath);
return ncclSystemError;
2018-09-24 16:06:59 -07:00
}
return ncclSuccess;
}
static ncclResult_t GetSocketAddr(int dev, union socketAddress* addr) {
if (dev >= ncclNetIfs) return ncclInternalError;
memcpy(addr, ncclNetIfAddrs+dev, sizeof(*addr));
return ncclSuccess;
}
/* Communication functions */
struct ncclSocketHandle {
union socketAddress connectAddr;
};
struct ncclSocketRequest {
2018-11-19 17:43:50 -08:00
int op;
void* data;
2018-09-24 16:06:59 -07:00
int size;
2018-11-19 17:43:50 -08:00
int fd;
int offset;
int used;
2018-09-24 16:06:59 -07:00
};
struct ncclSocketReqs {
struct ncclSocketRequest* requests;
};
struct ncclSocketComm {
int fd;
struct ncclSocketReqs reqs;
};
ncclResult_t ncclSocketNewComm(struct ncclSocketComm** comm) {
NCCLCHECK(ncclCalloc(comm, 1));
(*comm)->fd = -1;
return ncclSuccess;
}
ncclResult_t ncclSocketCreateHandle(void* opaqueHandle, const char* str) {
struct ncclSocketHandle* handle = (struct ncclSocketHandle*) opaqueHandle;
NCCLCHECK(GetSocketAddrFromString(&(handle->connectAddr), str));
return ncclSuccess;
}
ncclResult_t ncclSocketListen(int dev, void* opaqueHandle, void** listenComm) {
struct ncclSocketHandle* handle = (struct ncclSocketHandle*) opaqueHandle;
static_assert(sizeof(struct ncclSocketHandle) < NCCL_NET_HANDLE_MAXSIZE, "ncclSocketHandle size too large");
// if dev >= 0, listen based on dev
if (dev >= 0) {
NCCLCHECK(GetSocketAddr(dev, &(handle->connectAddr)));
} else if (dev == findSubnetIf) {
// handle stores a remote address
// need to find a local addr that is in the same network as the remote addr
union socketAddress localAddr;
char ifName[MAX_IF_NAME_SIZE];
if (findInterfaceMatchSubnet(ifName, &localAddr, handle->connectAddr, MAX_IF_NAME_SIZE, 1) <= 0) {
2018-12-13 15:56:12 -08:00
WARN("NET/Socket : No usable listening interface found");
2018-09-24 16:06:59 -07:00
return ncclSystemError;
}
// pass the local address back
memcpy(&handle->connectAddr, &localAddr, sizeof(handle->connectAddr));
} // Otherwise, handle stores a local address
struct ncclSocketComm* comm;
NCCLCHECK(ncclSocketNewComm(&comm));
NCCLCHECK(createListenSocket(&comm->fd, &handle->connectAddr));
*listenComm = comm;
return ncclSuccess;
}
ncclResult_t ncclSocketConnect(int dev, void* opaqueHandle, void** sendComm) {
struct ncclSocketComm* comm;
NCCLCHECK(ncclSocketNewComm(&comm));
struct ncclSocketHandle* handle = (struct ncclSocketHandle*) opaqueHandle;
NCCLCHECK(connectAddress(&comm->fd, &handle->connectAddr));
*sendComm = comm;
return ncclSuccess;
}
ncclResult_t ncclSocketAccept(void* listenComm, void** recvComm) {
struct ncclSocketComm* lComm = (struct ncclSocketComm*)listenComm;
struct ncclSocketComm* rComm;
NCCLCHECK(ncclSocketNewComm(&rComm));
struct sockaddr_in sockaddr;
socklen_t socklen = sizeof(struct sockaddr_in);
SYSCHECKVAL(accept(lComm->fd, (struct sockaddr*)&sockaddr, &socklen), "accept", rComm->fd);
*recvComm = rComm;
return ncclSuccess;
}
#define MAX_REQUESTS 128
2018-11-19 17:43:50 -08:00
ncclResult_t ncclSocketGetRequest(struct ncclSocketReqs* reqs, int op, void* data, int size, int fd, struct ncclSocketRequest** req) {
2018-09-24 16:06:59 -07:00
if (reqs->requests == NULL) {
NCCLCHECK(ncclCalloc(&reqs->requests, MAX_REQUESTS));
}
for (int i=0; i<MAX_REQUESTS; i++) {
struct ncclSocketRequest* r = reqs->requests+i;
if (r->used == 0) {
2018-11-19 17:43:50 -08:00
r->op = op;
r->data = data;
r->size = size;
r->fd = fd;
r->offset = -1;
2018-09-24 16:06:59 -07:00
r->used = 1;
*req = r;
return ncclSuccess;
}
}
WARN("Socket : unable to allocate requests");
return ncclInternalError;
}
2018-11-19 17:43:50 -08:00
ncclResult_t ncclSocketTest(void* request, int* done, int* size) {
*done = 0;
struct ncclSocketRequest *r = (struct ncclSocketRequest*)request;
if (r == NULL) {
WARN("NET/Socket : test called with NULL request");
return ncclInternalError;
}
if (r->offset == -1) { /* try to send/recv size */
int data = r->size;
int offset = 0;
NCCLCHECK(socketProgress(r->op, r->fd, &data, sizeof(int), &offset));
if (offset == 0) return ncclSuccess; /* Not ready -- retry later */
// Not sure we could ever receive less than 4 bytes, but just in case ...
if (offset < sizeof(int)) NCCLCHECK(socketWait(r->op, r->fd, &data, sizeof(int), &offset));
// Check size is less or equal to the size provided by the user
if (r->op == NCCL_SOCKET_RECV && data > r->size) {
WARN("NET/Socket : message truncated : receiving %d bytes instead of %d", data, r->size);
return ncclInternalError;
}
r->size = data;
r->offset = 0;
}
if (r->offset < r->size) {
NCCLCHECK(socketProgress(r->op, r->fd, r->data, r->size, &r->offset));
}
if (r->offset == r->size) {
if (size) *size = r->size;
*done = 1;
r->used = 0;
}
return ncclSuccess;
}
2018-12-13 15:56:12 -08:00
ncclResult_t ncclSocketRegMr(void* comm, void* data, int size, int type, void** mhandle) {
return (type != NCCL_PTR_HOST) ? ncclInternalError : ncclSuccess;
}
ncclResult_t ncclSocketDeregMr(void* comm, void* mhandle) { return ncclSuccess; }
ncclResult_t ncclSocketIsend(void* sendComm, void* data, int size, void* mhandle, void** request) {
2018-09-24 16:06:59 -07:00
struct ncclSocketComm* comm = (struct ncclSocketComm*)sendComm;
2018-11-19 17:43:50 -08:00
NCCLCHECK(ncclSocketGetRequest(&comm->reqs, NCCL_SOCKET_SEND, data, size, comm->fd, (struct ncclSocketRequest**)request));
2018-09-24 16:06:59 -07:00
return ncclSuccess;
}
2018-12-13 15:56:12 -08:00
ncclResult_t ncclSocketIrecv(void* recvComm, void* data, int size, void* mhandle, void** request) {
2018-09-24 16:06:59 -07:00
struct ncclSocketComm* comm = (struct ncclSocketComm*)recvComm;
2018-11-19 17:43:50 -08:00
NCCLCHECK(ncclSocketGetRequest(&comm->reqs, NCCL_SOCKET_RECV, data, size, comm->fd, (struct ncclSocketRequest**)request));
2018-09-24 16:06:59 -07:00
return ncclSuccess;
}
2018-12-13 15:56:12 -08:00
ncclResult_t ncclSocketFlush(void* recvComm, void* data, int size, void* mhandle) {
2018-09-24 16:06:59 -07:00
// We don't support CUDA pointers, so we don't need a flush operation
return ncclInternalError;
}
ncclResult_t ncclSocketClose(void* opaqueComm) {
struct ncclSocketComm* comm = (struct ncclSocketComm*)opaqueComm;
if (comm) {
free(comm->reqs.requests);
close(comm->fd);
free(comm);
}
return ncclSuccess;
}
ncclNet_t ncclNetSocket = {
"Socket",
2018-11-13 10:37:20 -08:00
ncclSocketInit,
2018-09-24 16:06:59 -07:00
ncclSocketDevices,
2018-11-13 10:37:20 -08:00
ncclSocketPciPath,
2018-09-24 16:06:59 -07:00
ncclSocketPtrSupport,
ncclSocketListen,
ncclSocketConnect,
ncclSocketAccept,
2018-12-13 15:56:12 -08:00
ncclSocketRegMr,
ncclSocketDeregMr,
2018-09-24 16:06:59 -07:00
ncclSocketIsend,
ncclSocketIrecv,
ncclSocketFlush,
ncclSocketTest,
ncclSocketClose,
ncclSocketClose,
ncclSocketClose
};