109 lines
3.2 KiB
C++
109 lines
3.2 KiB
C++
// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
#ifdef _WIN32
|
|
#include <gloo/common/win.h>
|
|
#include <winsock2.h>
|
|
#include <ws2tcpip.h>
|
|
#else
|
|
#include <netdb.h>
|
|
#include <sys/socket.h>
|
|
#include <unistd.h>
|
|
#include <array>
|
|
#endif
|
|
|
|
#include <cstdlib>
|
|
#include <cstring>
|
|
|
|
#include "paddle/common/errors.h"
|
|
#include "paddle/phi/core/distributed/gloo_utils.h"
|
|
#include "paddle/phi/core/distributed/store/tcp_utils.h"
|
|
#include "paddle/phi/core/enforce.h"
|
|
|
|
namespace phi::distributed {
|
|
std::shared_ptr<gloo::transport::Device> CreateDeviceForInterface(
|
|
const std::string& ifname) {
|
|
gloo::transport::tcp::attr attr;
|
|
attr.iface = ifname;
|
|
return gloo::transport::tcp::CreateDevice(attr);
|
|
}
|
|
|
|
std::shared_ptr<gloo::transport::Device> CreateDeviceForHostname(
|
|
const std::string& hostname) {
|
|
gloo::transport::tcp::attr attr;
|
|
attr.hostname = hostname;
|
|
return gloo::transport::tcp::CreateDevice(attr);
|
|
}
|
|
|
|
std::shared_ptr<gloo::transport::Device> CreateDefaultDevice() {
|
|
std::array<char, HOST_NAME_MAX> hostname = {};
|
|
auto ret = ::gethostname(hostname.data(), HOST_NAME_MAX);
|
|
PADDLE_ENFORCE_EQ(
|
|
ret,
|
|
0,
|
|
common::errors::Fatal("Get hostname error for createDefaultDevice."));
|
|
::addrinfo* result;
|
|
result = phi::distributed::tcputils::get_addr_info(
|
|
hostname.data(), "", 0, AF_UNSPEC);
|
|
::addrinfo* cur;
|
|
for (cur = result; cur != nullptr; cur = cur->ai_next) {
|
|
phi::distributed::SocketType socket =
|
|
::socket(cur->ai_family, cur->ai_socktype, cur->ai_protocol);
|
|
if (socket == -1) {
|
|
continue;
|
|
}
|
|
ret = ::bind(socket, cur->ai_addr, cur->ai_addrlen);
|
|
#ifdef _WIN32
|
|
closesocket(socket);
|
|
#else
|
|
close(socket);
|
|
#endif
|
|
if (ret == -1) {
|
|
continue;
|
|
}
|
|
break;
|
|
}
|
|
freeaddrinfo(result);
|
|
if (cur != nullptr) {
|
|
return CreateDeviceForHostname(hostname.data());
|
|
}
|
|
return CreateDeviceForHostname("127.0.0.1");
|
|
}
|
|
|
|
std::shared_ptr<gloo::transport::Device> CreateGlooDevice() {
|
|
char* ifname = std::getenv("GLOO_SOCKET_IFNAME");
|
|
if (ifname && std::strlen(ifname) > 1) {
|
|
return CreateDeviceForInterface(std::string(ifname));
|
|
} else {
|
|
return CreateDefaultDevice();
|
|
}
|
|
}
|
|
|
|
void send_recv(SendRecvOptions* opts) {
|
|
const auto& context = opts->context;
|
|
gloo::transport::UnboundBuffer* in = opts->in.get();
|
|
gloo::transport::UnboundBuffer* out = opts->out.get();
|
|
const auto slot = gloo::Slot::build(kSendRecvSlotPrefix, opts->tag);
|
|
|
|
if (context->rank == opts->src) {
|
|
in->send(opts->dst, slot);
|
|
in->waitSend(opts->timeout);
|
|
} else if (context->rank == opts->dst) {
|
|
out->recv(opts->src, slot);
|
|
out->waitRecv(opts->timeout);
|
|
}
|
|
}
|
|
|
|
} // namespace phi::distributed
|