char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
b114b4739
char/aliceai-t5-moe
1#include "transport.h" 2#include "ggml-impl.h" 3 4#ifdef _WIN32 5# define WIN32_LEAN_AND_MEAN 6# ifndef NOMINMAX 7# define NOMINMAX 8# endif 9# include <windows.h> 10# include <winsock2.h> 11#else 12# include <arpa/inet.h> 13# include <sys/socket.h> 14# include <sys/types.h> 15# include <netinet/in.h> 16# include <netinet/tcp.h> 17# include <netdb.h> 18# include <unistd.h> 19#endif 20#include <cstdlib> 21#include <cstring> 22#include <mutex> 23#include <optional> 24 25#ifdef GGML_RPC_RDMA 26# include <infiniband/verbs.h> 27# include <array> 28# include <time.h> 29# ifndef _WIN32 30# include <poll.h> 31# endif 32# ifdef GGML_RPC_RDMA_APPLE 33# include "transport-apple.h" 34# endif 35#endif // GGML_RPC_RDMA 36 37#ifdef _WIN32 38typedef SOCKET sockfd_t ; 39using ssize_t = __int64 ; 40#else 41typedef int sockfd_t ; 42#endif 43 44static const char * RPC_DEBUG = std::getenv ("GGML_RPC_DEBUG" ); 45 46#define LOG_DBG (...) \ 47 do { if (RPC_DEBUG) GGML_LOG_DEBUG(__VA_ARGS__); } while (0) 48 49#ifdef GGML_RPC_RDMA 50static constexpr size_t RDMA_GID_SIZE = 16 ;// RoCE GID / IB GID is always 16 bytes 51using rdma_gid_t = std::array < uint8_t ,RDMA_GID_SIZE > ; 52#endif // GGML_RPC_RDMA 53 54#if defined(GGML_RPC_RDMA )&& !defined(GGML_RPC_RDMA_APPLE ) 55static constexpr size_t RDMA_CHUNK = 256 * 1024 ;// 256 KiB per send/recv (fits default 8 MiB memlock) 56static constexpr int RDMA_RX_DEPTH = 24 ;// pre-posted recv ring: 24 × 256 KiB = 6 MiB 57 58struct rdma_conn { 59struct ibv_context * ctx = nullptr ; 60struct ibv_pd * pd = nullptr ; 61struct ibv_cq * scq = nullptr ;// send completions 62struct ibv_cq * rcq = nullptr ;// recv completions 63struct ibv_qp * qp = nullptr ; 64 65void * tx_buf = nullptr ; 66struct ibv_mr * tx_mr = nullptr ; 67 68void * rx_buf = nullptr ;// RDMA_RX_DEPTH × RDMA_CHUNK contiguous 69struct ibv_mr * rx_mr = nullptr ; 70int rx_head = 0 ; 71 72uint32_t max_inline = 0 ; 73 74uint8_t * rx_slot (int i )const { 75return static_cast < uint8_t *> (rx_buf )+ static_cast < size_t > (i )* RDMA_CHUNK ; 76 } 77 78bool post_rx (int i ) { 79struct ibv_sge sge = {}; 80sge .addr = (uintptr_t )rx_slot (i ); 81sge .length = RDMA_CHUNK ; 82sge .lkey = rx_mr -> lkey ; 83struct ibv_recv_wr wr = {},* bad = nullptr ; 84wr .wr_id = (uint64_t )i ; 85wr .sg_list = & sge ; 86wr .num_sge = 1 ; 87return ibv_post_recv (qp ,& wr ,& bad )== 0 ; 88 } 89 90 ~rdma_conn () { 91if (tx_mr )ibv_dereg_mr (tx_mr ); 92if (rx_mr )ibv_dereg_mr (rx_mr ); 93free (tx_buf ); 94free (rx_buf ); 95if (qp )ibv_destroy_qp (qp ); 96if (scq )ibv_destroy_cq (scq ); 97if (rcq )ibv_destroy_cq (rcq ); 98if (pd )ibv_dealloc_pd (pd ); 99if (ctx )ibv_close_device (ctx ); 100 } 101}; 102 103// Local RDMA parameters captured during the probe phase and later consumed 104// by rdma_activate() after the remote side's caps arrive via HELLO. 105struct rdma_local_info { 106uint32_t qpn = 0 ; 107uint32_t psn = 0 ; 108uint8_t gid [RDMA_GID_SIZE ]= {}; 109uint8_t ib_port = 0 ; 110int gid_idx = 0 ; 111enum ibv_mtu path_mtu = IBV_MTU_1024 ; 112}; 113 114struct rdma_caps { 115uint32_t qpn ; 116uint32_t psn ; 117uint8_t gid [RDMA_GID_SIZE ]; 118}; 119 120static_assert(sizeof (rdma_caps )== RPC_CONN_CAPS_SIZE ,"rdma_caps must match conn_caps size" ); 121 122#endif // GGML_RPC_RDMA && !GGML_RPC_RDMA_APPLE 123 124struct socket_t::impl { 125impl (sockfd_t fd ) :use_rdma (false),fd (fd ) {} 126 ~impl (); 127bool send_data (const void * data ,size_t size ); 128bool recv_data (void * data ,size_t size ); 129bool flush (); 130void get_caps (uint8_t * local_caps ); 131void update_caps (const uint8_t * remote_caps ); 132 133#ifdef GGML_RPC_RDMA 134 std::optional < rdma_gid_t > rdma_build_target_gid (); 135 136# ifdef GGML_RPC_RDMA_APPLE 137 std::unique_ptr < apple_rdma > rdma ; 138# else 139bool rdma_probe (); 140bool rdma_send (const void * data ,size_t size ); 141bool rdma_recv (void * data ,size_t size ); 142bool tcp_peer_closed (); 143bool rdma_activate (uint32_t remote_qpn ,uint32_t remote_psn ,const uint8_t * remote_gid ); 144bool rdma_poll (struct ibv_cq * cq ,struct ibv_wc * wc ); 145 146 std::unique_ptr < rdma_conn > rdma ; 147rdma_local_info rdma_local = {}; 148# endif 149#endif // GGML_RPC_RDMA 150bool use_rdma ; 151sockfd_t fd ; 152}; 153 154socket_t::impl::~impl () { 155#ifdef GGML_RPC_RDMA 156rdma .reset (); 157#endif // GGML_RPC_RDMA 158LOG_DBG ("[%s] closing socket %d\n" ,__func__ ,this -> fd ); 159#ifdef _WIN32 160if (fd != INVALID_SOCKET )closesocket (this -> fd ); 161#else 162if (fd >=0 )close (this -> fd ); 163#endif 164} 165 166#ifdef GGML_RPC_RDMA 167 168// Build a RoCE GID-shaped 16-byte target from a TCP socket's local address. 169// Used to match the socket's local IP against the kernel's GID table so that 170// a single memcmp handles IPv4, IPv4-mapped IPv6, and native IPv6 uniformly: 171// AF_INET -> ::ffff:a.b.c.d (bytes 10-11 = 0xff, last 4 = IPv4) 172// AF_INET6 (IPv4-mapped) -> ::ffff:a.b.c.d (already in GID shape) 173// AF_INET6 (native v6) -> the 16-byte IPv6 address as-is 174// Returns std::nullopt on unsupported family or getsockname failure. 175std::optional < rdma_gid_t > socket_t::impl::rdma_build_target_gid () { 176sockaddr_storage addr = {}; 177socklen_t addr_len = sizeof (addr ); 178if (getsockname (fd ,reinterpret_cast < sockaddr *> (& addr ),& addr_len )!= 0 ) { 179return std::nullopt ; 180 } 181rdma_gid_t target = {}; 182if (addr .ss_family == AF_INET ) { 183const auto * a = reinterpret_cast < const sockaddr_in *> (& addr ); 184target [10 ]= 0xff ; 185target [11 ]= 0xff ; 186memcpy (& target [12 ],& a -> sin_addr ,4 ); 187return target ; 188 } 189if (addr .ss_family == AF_INET6 ) { 190const auto * a = reinterpret_cast < const sockaddr_in6 *> (& addr ); 191memcpy (target .data (),& a -> sin6_addr ,RDMA_GID_SIZE ); 192return target ; 193 } 194return std::nullopt ; 195} 196 197#ifndef GGML_RPC_RDMA_APPLE 198 199bool socket_t::impl::tcp_peer_closed () { 200if (fd < 0 )return false; 201#ifndef _WIN32 202struct pollfd pfd = {fd ,POLLIN |POLLRDHUP ,0 }; 203int r = poll (& pfd ,1 ,0 ); 204return r > 0 && (pfd .revents & (POLLHUP |POLLERR |POLLRDHUP )); 205#else 206return false; 207#endif 208} 209 210bool socket_t::impl::rdma_probe () { 211const char * dev_env = std::getenv ("GGML_RDMA_DEV" ); 212const char * gid_env = std::getenv ("GGML_RDMA_GID" ); 213 214auto target_gid = rdma_build_target_gid (); 215if (!target_gid ) { 216return false; 217 } 218 219const uint8_t ib_port = 1 ; 220int num_devs = 0 ; 221ibv_device ** devs = ibv_get_device_list (& num_devs ); 222if (!devs || num_devs == 0 )return false; 223 224ibv_context * ibctx = nullptr ; 225const char * matched_dev = nullptr ; 226int gid_idx = gid_env ?atoi (gid_env ) :-1 ; 227int gid_version = IBV_GID_TYPE_IB ;// 0 = unknown/IB 228 229for (int d = 0 ;d < num_devs ;d ++ ) { 230const char * dn = ibv_get_device_name (devs [d ]); 231if (dev_env && strcmp (dev_env ,dn )!= 0 )continue ; 232 233ibv_context * ctx = ibv_open_device (devs [d ]); 234if (!ctx )continue ; 235 236ibv_port_attr pa ; 237if (ibv_query_port (ctx ,ib_port ,& pa )!= 0 ) {ibv_close_device (ctx );continue ; } 238 239int found_gid = gid_idx ; 240int found_version = IBV_GID_TYPE_IB ; 241if (found_gid < 0 ) { 242// Find a GID on this port whose bytes equal the local TCP address 243// (IPv4 or IPv6). Prefer RoCE v2 (UDP/IP, L3-routable) over v1 244// (raw Ethernet, same-L2 only) so silent hangs on L3-routed paths 245// are avoided. ibv_query_gid_ex returns gid+type in one call. 246int v2_idx = -1 ; 247int v1_idx = -1 ; 248for (int i = 0 ;i < pa .gid_tbl_len ;i ++ ) { 249ibv_gid_entry entry = {}; 250if (ibv_query_gid_ex (ctx ,ib_port ,i ,& entry ,0 )!= 0 )continue ; 251if (memcmp (entry .gid .raw ,target_gid -> data (),RDMA_GID_SIZE )!= 0 )continue ; 252if (entry .gid_type == IBV_GID_TYPE_ROCE_V2 && v2_idx < 0 ) { 253v2_idx = i ; 254 }else if (entry .gid_type == IBV_GID_TYPE_ROCE_V1 && v1_idx < 0 ) { 255v1_idx = i ; 256 } 257 } 258if (v2_idx >=0 ) { 259found_gid = v2_idx ; 260found_version = IBV_GID_TYPE_ROCE_V2 ; 261 }else if (v1_idx >=0 ) { 262found_gid = v1_idx ; 263found_version = IBV_GID_TYPE_ROCE_V1 ; 264 } 265 }else { 266// Explicit GID index from GGML_RDMA_GID — fetch its type for logging. 267ibv_gid_entry entry = {}; 268if (ibv_query_gid_ex (ctx ,ib_port ,found_gid ,& entry ,0 )== 0 ) { 269found_version = entry .gid_type ; 270 } 271 } 272if (found_gid >=0 ) { 273ibctx = ctx ; 274gid_idx = found_gid ; 275gid_version = found_version ; 276matched_dev = dn ; 277rdma_local .path_mtu = pa .active_mtu ; 278break ; 279 } 280ibv_close_device (ctx ); 281 } 282ibv_free_device_list (devs ); 283if (!ibctx )return false; 284 285rdma_local .ib_port = ib_port ; 286rdma_local .gid_idx = gid_idx ; 287 288rdma = std::make_unique < rdma_conn > (); 289rdma -> ctx = ibctx ; 290 291rdma -> pd = ibv_alloc_pd (ibctx ); 292if (!rdma -> pd )return false; 293 294rdma -> scq = ibv_create_cq (ibctx ,16 ,nullptr ,nullptr ,0 ); 295rdma -> rcq = ibv_create_cq (ibctx ,RDMA_RX_DEPTH + 4 ,nullptr ,nullptr ,0 ); 296if (!rdma -> scq || !rdma -> rcq )return false; 297 298ibv_qp_init_attr qia = {}; 299qia .send_cq = rdma -> scq ; 300qia .recv_cq = rdma -> rcq ; 301qia .qp_type = IBV_QPT_RC ; 302qia .cap .max_send_wr = 4 ; 303qia .cap .max_recv_wr = RDMA_RX_DEPTH + 4 ; 304qia .cap .max_send_sge = 1 ; 305qia .cap .max_recv_sge = 1 ; 306qia .cap .max_inline_data = 256 ; 307 308rdma -> qp = ibv_create_qp (rdma -> pd ,& qia ); 309if (!rdma -> qp )return false; 310rdma -> max_inline = qia .cap .max_inline_data ; 311 312rdma -> tx_buf = aligned_alloc (4096 ,RDMA_CHUNK ); 313rdma -> rx_buf = aligned_alloc (4096 ,static_cast < size_t > (RDMA_RX_DEPTH )* RDMA_CHUNK ); 314if (!rdma -> tx_buf || !rdma -> rx_buf )return false; 315 316rdma -> tx_mr = ibv_reg_mr (rdma -> pd ,rdma -> tx_buf ,RDMA_CHUNK ,IBV_ACCESS_LOCAL_WRITE ); 317rdma -> rx_mr = ibv_reg_mr (rdma -> pd ,rdma -> rx_buf ,static_cast < size_t > (RDMA_RX_DEPTH )* RDMA_CHUNK , 318IBV_ACCESS_LOCAL_WRITE |IBV_ACCESS_REMOTE_WRITE ); 319if (!rdma -> tx_mr || !rdma -> rx_mr )return false; 320 321ibv_gid local_gid ; 322if (ibv_query_gid (ibctx ,ib_port ,gid_idx ,& local_gid )!= 0 )return false; 323 324rdma_local .qpn = rdma -> qp -> qp_num ; 325rdma_local .psn = rdma -> qp -> qp_num & 0xffffff ; 326memcpy (& rdma_local .gid ,& local_gid ,RDMA_GID_SIZE ); 327 328const char * ver_str = "" ; 329if (gid_version == IBV_GID_TYPE_ROCE_V2 ) { 330ver_str = " RoCEv2" ; 331 }else if (gid_version == IBV_GID_TYPE_ROCE_V1 ) { 332ver_str = " RoCEv1" ; 333 } 334GGML_LOG_INFO ("RDMA probed: dev=%s gid=%d%s qpn=%u inline=%u\n" , 335matched_dev ,gid_idx ,ver_str ,rdma_local .qpn ,rdma -> max_inline ); 336return true; 337} 338 339// Phase 2: Given remote QPN/PSN/GID, transition QP: RESET->INIT->pre-post->RTR->RTS. 340// On success, the connection is live and ready for rdma_send/rdma_recv. 341bool socket_t::impl::rdma_activate (uint32_t remote_qpn ,uint32_t remote_psn ,const uint8_t * remote_gid ) { 342// RESET -> INIT 343 { 344struct ibv_qp_attr a = {}; 345a .qp_state = IBV_QPS_INIT ; 346a .port_num = rdma_local .ib_port ; 347a .pkey_index = 0 ; 348a .qp_access_flags = IBV_ACCESS_REMOTE_WRITE |IBV_ACCESS_REMOTE_READ |IBV_ACCESS_LOCAL_WRITE ; 349if (ibv_modify_qp (rdma -> qp ,& a , 350IBV_QP_STATE |IBV_QP_PKEY_INDEX |IBV_QP_PORT |IBV_QP_ACCESS_FLAGS )!= 0 ) { 351return false; 352 } 353 } 354 355for (int i = 0 ;i < RDMA_RX_DEPTH ;i ++ ) { 356if (!rdma -> post_rx (i ))return false; 357 } 358 359// INIT -> RTR 360 { 361struct ibv_qp_attr a = {}; 362a .qp_state = IBV_QPS_RTR ; 363a .path_mtu = rdma_local .path_mtu ; 364a .dest_qp_num = remote_qpn ; 365a .rq_psn = remote_psn ; 366a .max_dest_rd_atomic = 1 ; 367a .min_rnr_timer = 1 ; 368a .ah_attr .is_global = 1 ; 369memcpy (& a .ah_attr .grh .dgid ,remote_gid ,RDMA_GID_SIZE ); 370a .ah_attr .grh .hop_limit = 1 ; 371a .ah_attr .grh .sgid_index = rdma_local .gid_idx ; 372a .ah_attr .dlid = 0 ; 373a .ah_attr .port_num = rdma_local .ib_port ; 374if (ibv_modify_qp (rdma -> qp ,& a , 375IBV_QP_STATE |IBV_QP_AV |IBV_QP_PATH_MTU |IBV_QP_DEST_QPN | 376IBV_QP_RQ_PSN |IBV_QP_MAX_DEST_RD_ATOMIC |IBV_QP_MIN_RNR_TIMER )!= 0 ) { 377return false; 378 } 379 } 380 381// RTR -> RTS 382 { 383struct ibv_qp_attr a = {}; 384a .qp_state = IBV_QPS_RTS ; 385a .timeout = 14 ; 386a .retry_cnt = 7 ; 387a .rnr_retry = 7 ; 388a .sq_psn = rdma_local .psn ; 389a .max_rd_atomic = 1 ; 390if (ibv_modify_qp (rdma -> qp ,& a , 391IBV_QP_STATE |IBV_QP_TIMEOUT |IBV_QP_RETRY_CNT |IBV_QP_RNR_RETRY | 392IBV_QP_SQ_PSN |IBV_QP_MAX_QP_RD_ATOMIC )!= 0 ) { 393return false; 394 } 395 } 396 397GGML_LOG_INFO ("RDMA activated: qpn=%u->%u mtu=%d rx_depth=%d\n" , 398rdma_local .qpn ,remote_qpn ,128 <<rdma_local .path_mtu ,RDMA_RX_DEPTH ); 399return true; 400} 401 402bool socket_t::impl::rdma_poll (struct ibv_cq * cq ,struct ibv_wc * wc ) { 403for (uint64_t s = 0 ; ;s ++ ) { 404int n = ibv_poll_cq (cq ,1 ,wc ); 405if (n > 0 ) { 406if (wc -> status != IBV_WC_SUCCESS ) { 407GGML_LOG_ERROR ("RDMA CQ wc error: status=%d (%s) vendor_err=0x%x\n" , 408wc -> status ,ibv_wc_status_str (wc -> status ),wc -> vendor_err ); 409 } 410return wc -> status == IBV_WC_SUCCESS ; 411 } 412if (n < 0 )return false; 413if ((s & 0xFFFFF )== 0 && s > 0 ) { 414if (tcp_peer_closed ()) { 415return false; 416 } 417 } 418 } 419} 420 421bool socket_t::impl::rdma_send (const void * data ,size_t size ) { 422rdma_conn * c = rdma .get (); 423const uint8_t * src = (const uint8_t * )data ; 424size_t rem = size ; 425while (rem > 0 ) { 426size_t chunk = std::min (rem ,RDMA_CHUNK ); 427 428struct ibv_sge sge = {}; 429struct ibv_send_wr wr = {},* bad = nullptr ; 430wr .opcode = IBV_WR_SEND ; 431wr .sg_list = & sge ; 432wr .num_sge = 1 ; 433 434if (chunk <=c -> max_inline ) { 435sge .addr = (uintptr_t )src ; 436sge .length = chunk ; 437wr .send_flags = IBV_SEND_SIGNALED |IBV_SEND_INLINE ; 438 }else { 439memcpy (c -> tx_buf ,src ,chunk ); 440sge .addr = (uintptr_t )c -> tx_buf ; 441sge .length = chunk ; 442sge .lkey = c -> tx_mr -> lkey ; 443wr .send_flags = IBV_SEND_SIGNALED ; 444 } 445 446if (ibv_post_send (c -> qp ,& wr ,& bad )!= 0 )return false; 447struct ibv_wc wc ; 448if (!rdma_poll (c -> scq ,& wc ))return false; 449 450src += chunk ; 451rem -= chunk ; 452 } 453return true; 454} 455 456bool socket_t::impl::rdma_recv (void * data ,size_t size ) { 457rdma_conn * c = rdma .get (); 458uint8_t * dst = (uint8_t * )data ; 459size_t rem = size ; 460while (rem > 0 ) { 461struct ibv_wc wc ; 462if (!rdma_poll (c -> rcq ,& wc ))return false; 463 464int slot = (int )wc .wr_id ; 465size_t got = wc .byte_len ; 466memcpy (dst ,c -> rx_slot (slot ),got ); 467 468if (!c -> post_rx (slot ))return false; 469 470dst += got ; 471rem -= got ; 472 } 473return true; 474} 475 476#endif // !GGML_RPC_RDMA_APPLE (Linux RC transport) 477 478#endif // GGML_RPC_RDMA 479 480bool socket_t::impl::send_data (const void * data ,size_t size ) { 481#ifdef GGML_RPC_RDMA_APPLE 482if (use_rdma ) { 483return rdma -> send (data ,size ); 484 } 485#elif defined(GGML_RPC_RDMA ) 486if (use_rdma ) { 487return rdma_send (data ,size ); 488 } 489#endif 490size_t bytes_sent = 0 ; 491while (bytes_sent < size ) { 492size_t size_to_send = std::min (size - bytes_sent ,MAX_CHUNK_SIZE ); 493ssize_t n = send (fd , (const char * )data + bytes_sent ,size_to_send ,0 ); 494if (n < 0 ) { 495GGML_LOG_ERROR ("send failed (bytes_sent=%zu, size_to_send=%zu)\n" , 496bytes_sent ,size_to_send ); 497return false; 498 } 499bytes_sent += (size_t )n ; 500 } 501return true; 502} 503 504bool socket_t::impl::recv_data (void * data ,size_t size ) { 505#ifdef GGML_RPC_RDMA_APPLE 506if (use_rdma ) { 507return rdma -> recv (data ,size ); 508 } 509#elif defined(GGML_RPC_RDMA ) 510if (use_rdma ) { 511return rdma_recv (data ,size ); 512 } 513#endif 514size_t bytes_recv = 0 ; 515while (bytes_recv < size ) { 516size_t size_to_recv = std::min (size - bytes_recv ,MAX_CHUNK_SIZE ); 517ssize_t n = recv (fd , (char * )data + bytes_recv ,size_to_recv ,0 ); 518if (n < 0 ) { 519GGML_LOG_ERROR ("recv failed (bytes_recv=%zu, size_to_recv=%zu)\n" , 520bytes_recv ,size_to_recv ); 521return false; 522 } 523if (n == 0 ) { 524LOG_DBG ("recv returned 0 (peer closed?)\n" ); 525return false; 526 } 527bytes_recv += (size_t )n ; 528 } 529return true; 530} 531 532void socket_t::impl::get_caps (uint8_t * local_caps ) { 533memset (local_caps ,0 ,RPC_CONN_CAPS_SIZE ); 534#ifdef GGML_RPC_RDMA 535if (std::getenv ("GGML_RPC_NO_RDMA" )) { 536return ; 537 } 538# ifdef GGML_RPC_RDMA_APPLE 539auto target_gid = rdma_build_target_gid (); 540if (target_gid ) { 541rdma = apple_rdma::probe (fd ,target_gid -> data (),local_caps ); 542 } 543# else 544rdma_local = {}; 545if (rdma_probe ()) { 546rdma_caps rc = {}; 547rc .qpn = rdma_local .qpn ; 548rc .psn = rdma_local .psn ; 549memcpy (rc .gid ,rdma_local .gid ,RDMA_GID_SIZE ); 550memcpy (local_caps ,& rc ,sizeof (rc )); 551 }else { 552rdma .reset (); 553 } 554# endif 555#endif // GGML_RPC_RDMA 556} 557 558void socket_t::impl::update_caps (const uint8_t * remote_caps ) { 559#ifdef GGML_RPC_RDMA 560// a peer that has no RDMA advertises all-zero caps and takes no further part 561// in the negotiation, so drop to TCP without reporting a failure 562bool remote_rdma = false; 563for (size_t i = 0 ;i < RPC_CONN_CAPS_SIZE ;i ++ ) { 564remote_rdma |=remote_caps [i ]!= 0 ; 565 } 566if (!rdma || !remote_rdma ) { 567rdma .reset (); 568return ; 569 } 570# ifdef GGML_RPC_RDMA_APPLE 571bool activated = rdma -> activate (remote_caps ); 572# else 573rdma_caps rc = {}; 574memcpy (& rc ,remote_caps ,sizeof (rc )); 575bool activated = rdma_activate (rc .qpn ,rc .psn ,rc .gid ); 576# endif 577if (activated ) { 578use_rdma = true; 579 }else { 580GGML_LOG_ERROR ("RDMA activate failed, staying on TCP\n" ); 581rdma .reset (); 582 } 583#else 584 (void )remote_caps ; 585#endif // GGML_RPC_RDMA 586} 587 588bool socket_t::impl::flush () { 589#ifdef GGML_RPC_RDMA_APPLE 590if (use_rdma ) { 591return rdma -> flush (); 592 } 593#endif 594return true; 595} 596 597///////////////////////////////////////////////////////////////////////////// 598 599socket_t::socket_t (std::unique_ptr < impl > p ) :pimpl (std::move (p )) {} 600 601socket_t::~socket_t ()= default ; 602 603bool socket_t::send_data (const void * data ,size_t size ) { 604return pimpl -> send_data (data ,size ); 605} 606 607bool socket_t::recv_data (void * data ,size_t size ) { 608return pimpl -> recv_data (data ,size ); 609} 610 611bool socket_t::flush () { 612return pimpl -> flush (); 613} 614 615void socket_t::get_caps (uint8_t * local_caps ) { 616return pimpl -> get_caps (local_caps ); 617} 618 619void socket_t::update_caps (const uint8_t * remote_caps ) { 620return pimpl -> update_caps (remote_caps ); 621} 622 623static bool is_valid_fd (sockfd_t sockfd ) { 624#ifdef _WIN32 625return sockfd != INVALID_SOCKET ; 626#else 627return sockfd >=0 ; 628#endif 629} 630 631static bool set_no_delay (sockfd_t sockfd ) { 632int flag = 1 ; 633// set TCP_NODELAY to disable Nagle's algorithm 634int ret = setsockopt (sockfd ,IPPROTO_TCP ,TCP_NODELAY , (char * )& flag ,sizeof (int )); 635return ret == 0 ; 636} 637 638static bool set_reuse_addr (sockfd_t sockfd ) { 639int flag = 1 ; 640int ret = setsockopt (sockfd ,SOL_SOCKET ,SO_REUSEADDR , (char * )& flag ,sizeof (int )); 641return ret == 0 ; 642} 643 644socket_ptr socket_t::accept () { 645auto client_socket_fd = ::accept (pimpl -> fd ,NULL ,NULL ); 646if (!is_valid_fd (client_socket_fd )) { 647return nullptr ; 648 } 649if (!set_no_delay (client_socket_fd )) { 650GGML_LOG_ERROR ("Failed to set TCP_NODELAY\n" ); 651return nullptr ; 652 } 653return socket_ptr (new socket_t (std::make_unique < impl > (client_socket_fd ))); 654} 655 656socket_ptr socket_t::create_server (const char * host ,int port ) { 657auto sockfd = socket (AF_INET ,SOCK_STREAM ,0 ); 658if (!is_valid_fd (sockfd )) { 659return nullptr ; 660 } 661if (!set_reuse_addr (sockfd )) { 662GGML_LOG_ERROR ("Failed to set SO_REUSEADDR\n" ); 663return nullptr ; 664 } 665if (inet_addr (host )== INADDR_NONE ) { 666GGML_LOG_ERROR ("Invalid host address: %s\n" ,host ); 667return nullptr ; 668 } 669struct sockaddr_in serv_addr ; 670serv_addr .sin_family = AF_INET ; 671serv_addr .sin_addr .s_addr = inet_addr (host ); 672serv_addr .sin_port = htons (port ); 673 674if (bind (sockfd , (struct sockaddr * )& serv_addr ,sizeof (serv_addr ))< 0 ) { 675return nullptr ; 676 } 677if (listen (sockfd ,1 )< 0 ) { 678return nullptr ; 679 } 680return socket_ptr (new socket_t (std::make_unique < impl > (sockfd ))); 681} 682 683socket_ptr socket_t::connect (const char * host ,int port ) { 684auto sockfd = socket (AF_INET ,SOCK_STREAM ,0 ); 685if (!is_valid_fd (sockfd )) { 686return nullptr ; 687 } 688if (!set_no_delay (sockfd )) { 689GGML_LOG_ERROR ("Failed to set TCP_NODELAY\n" ); 690return nullptr ; 691 } 692struct sockaddr_in addr ; 693addr .sin_family = AF_INET ; 694addr .sin_port = htons (port ); 695struct hostent * server = gethostbyname (host ); 696if (server == NULL ) { 697GGML_LOG_ERROR ("Cannot resolve host '%s'\n" ,host ); 698return nullptr ; 699 } 700memcpy (& addr .sin_addr .s_addr ,server -> h_addr ,server -> h_length ); 701if (::connect (sockfd , (struct sockaddr * )& addr ,sizeof (addr ))< 0 ) { 702return nullptr ; 703 } 704return socket_ptr (new socket_t (std::make_unique < impl > (sockfd ))); 705} 706 707#ifdef _WIN32 708static std::mutex g_rpc_transport_mu ; 709static bool g_rpc_transport_wsa_started = false; 710#endif 711 712bool rpc_transport_init () { 713#ifdef _WIN32 714 std::lock_guard < std::mutex > lock (g_rpc_transport_mu ); 715if (g_rpc_transport_wsa_started ) { 716return true; 717 } 718WSADATA wsaData ; 719int res = WSAStartup (MAKEWORD (2 ,2 ),& wsaData ); 720if (res != 0 ) { 721return false; 722 } 723g_rpc_transport_wsa_started = true; 724return true; 725#else 726return true; 727#endif 728} 729 730void rpc_transport_shutdown () { 731#ifdef _WIN32 732 std::lock_guard < std::mutex > lock (g_rpc_transport_mu ); 733if (!g_rpc_transport_wsa_started ) { 734return ; 735 } 736WSACleanup (); 737g_rpc_transport_wsa_started = false; 738#endif 739}