ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

高性能计算通信库核心设计与调优实战指南

高性能计算通信库核心设计与调优实战指南 1. 为什么做通信库之前先得想清楚“通信”到底卡在哪做高性能计算的人迟早都要面对一个扎心的现实CPU算力上去了GPU显存带宽也翻倍了可多机多卡一跑起来性能就是上不去。你盯着监控面板看半天发现GPU利用率一会儿90%一会儿30%波形图跟过山车似的。这时候十有八九不是你的计算代码写得不行而是通信环节在拖后腿。高性能计算通信库就是干这个的——它负责让分布式环境里的各个计算节点、各种计算设备之间把数据“搬得又快又稳”。你可能听过MPI、NCCL、Gloo这些名字它们都属于通信库这个范畴。哪怕你用的是PyTorch DistributedDataParallel、Horovod这类上层框架底层拼的也是通信库的功力。我这篇文章想聊的不是某个通信库的API怎么查而是从做项目的角度把高性能计算通信库的核心设计思路、通信机制、选型考量、参数调优和问题排查整体拆一遍。适合两类人一类是刚接手分布式训练或高性能计算集群、被通信瓶颈折磨的工程师另一类是打算自己封装一套内部通信中间件想搞清楚设计门道的人。看完你至少能做到别人给你一个通信性能问题你能快速判断是算法问题、拓扑问题、还是参数配置问题。先说一个常见的误区。很多人觉得通信库就是把send和recv封装一下拿过来用就行。真不是这样。高性能计算通信库的核心难点在于当你有8张卡、16台机器、甚至上千个节点时数据怎么从“所有人发给一个人”再变成“所有人发给所有人”这里面的通信模式、流量模型、硬件拓扑感知、故障处理每一个环节都藏着大量的工程细节。一个设计不佳的通信过程性能可能只有优化后的十分之一甚至更少。打个比方通信库就像机场的空中管制系统。你不光要知道每架飞机从哪起飞、往哪降落数据从哪个设备发到哪个设备还得规划航线避免冲突、应对天气延误、安排跑道资源。如果没有这套系统飞机再多跑道再宽也飞不起来——你只会看到满屏延误和空中盘旋。通信库就是帮你的计算任务在“数据机场”里高效起降的那套系统。2. 通信库的底层逻辑点对点通信与集合通信2.1 点对点通信一切的起点怎么说呢所有复杂的通信行为归根到底都能拆成点对点通信——就是两个通信实体之间的一发一收。MPI里的MPI_Send和MPI_Recv就是最典型的代表。虽然现在做分布式计算很多人已经很少直接写MPI_Send了但这个基础概念不能丢因为集合通信大多是建立在点对点通信之上的。点对点通信看着简单里面有讲究。比如发送方调了Send之后数据是直接拷贝到接收方的缓冲区还是先拷贝到中间缓冲区这就牵扯到同步通信和异步通信的区别。同步发送要等接收方准备好了才真正传输这种模式安全但容易造成等待异步发送则把数据丢给通信库管理发送方立刻返回继续算效率高但需要你小心处理缓冲区的生命周期——如果你的发送缓冲区在数据没传完就被覆盖了那就容易出现数据错乱这类很隐蔽的问题。所以实际做通信库设计的时候收发两端的“握手协议”是需要仔细定义的。你是用eager协议小消息直接发不管对面收不收还是rendezvous协议大消息先握手、确认准备好了再传这个决策直接影响短消息延迟和大消息带宽。我见过不少自研通信库的项目在小消息场景下性能还行一上大消息就崩多半就是没有针对消息大小做协议切换。2.2 集合通信的常见模式与算法演进集合通信是高性能计算通信库的灵魂。用一句话概括它解决的是“一组通信实体之间协同传输”的问题常见的模式包括Broadcast一个节点把数据发给所有其他节点。Reduce所有节点把数据规约成一个结果比如求和、求最大值通常落在某一个根节点。AllreduceReduce的升级版规约后的结果要广播给所有节点。Allgather每个节点把自己的一份数据发出去最终每个节点都拥有所有人的完整数据集。Alltoall每个节点把自己的一部分数据分发给其他每个节点像一次全排列交换。这里面的核心难点在于当节点数量变大如何让通信量尽可能均衡地分配避免某一个节点变成瓶颈。以Allreduce为例朴素的实现是“星型拓扑”就是让根节点接收所有人的数据再做规约最后广播回去。这种做法有两个问题一是根节点会成为流量瓶颈所有数据都汇聚到它那里二是网络上会产生严重的拥塞。所以后来大家就想了很多聪明的办法。最简单的改进是“环形Allreduce”。所有节点排成一个环每个节点只跟相邻的两个节点通信数据在环上转一圈每个节点转发一部分数据同时做规约转完一圈之后结果也就自然规约完了。环形算法的好处是每个节点的通信量都差不多不会出现单个节点过载的情况。但它的缺点是通信次数多而且延迟和环的长度成正比——节点越多数据要经过的跳数越多延迟也就越高。再进一步就是“树形Allreduce”和“递归倍增Recursive Halving-Doubling”算法。树形算法是把节点组织成一颗逻辑树叶子节点把数据传给父节点父节点做规约再往上传最后由根节点拿到完整结果再广播下去。递归倍增则更加巧妙它把节点看成二进制编码通过多次“两两配对-交换-拼接”的方式完成规约和广播通信次数是O(logN)级别在大规模集群下优势非常明显。说实话NCCL后来大红大紫很大程度上就是因为在Allreduce上做了非常细致的算法选型组合。它不只用一种算法而是根据GPU数量、节点数、消息大小、NVLink拓扑、PCIe拓扑、网络带宽等因素动态选择最优的通信策略。这种“感知硬件”的设计才是它性能领先的关键。你自己做通信库别指望一种算法打天下一定要做算法选择器根据实际运行环境动态决策。2.3 算法选型背后的数据支撑既然说到算法选型我补充一个简单的计算框架方便你理解为什么大消息和小消息的通信策略可以完全不同。假设有N个节点参与Allreduce每个节点有M字节数据。环形算法中每个节点的通信总量大致是 2M(N-1)/N 字节转发 规约过程中每个节点都需要发送和接收约两轮数据。树形算法中每层通信量是M层数是log(N)所以每个节点的通信量大约为 2M log(N)。递归倍增算法在通信量上也接近 O(M log N)但它在通信次数上更少。当N比较小比如4个节点环形和树形的通信量差异不大但当N64甚至更大时log(N)的差距就体现出来了——环形算法每个节点要传递接近2M字节的数据而树形算法只需要大约12M字节2×M×6差了十几倍。所以大规模集群上基本都会倾向树形或递归倍增方案。但是注意树形算法在节点不多时未必比环形快因为它的拓扑层次多、同步开销大而且如果某些节点的上行、下行带宽不对称树形结构很容易造成上层节点拥塞。这也是为什么通信库内部需要一套自适应的“决策器”——拿通信库自己的benchmark跑一轮测出实际带宽和延迟再结合节点拓扑选择最合适的算法。3. 通信库的硬件感知从拓扑识别到带宽利用3.1 为什么必须搞清楚NVLink、PCIe和网卡的层次关系通信库性能优化的突破口有很大一部分在“硬件拓扑感知”上。现在的服务器单机内可能有4张、8张甚至更多GPUGPU之间通过NVLink或PCIe互联跨机器通信则要经过网卡和交换机。不同路径的带宽、延迟差异非常悬殊。举个例子一张A100 GPU通过NVLink互联的带宽是600GB/s而通过PCIe Gen4 x16的带宽大约是32GB/s跨节点走InfiniBand HDR也就约12.5GB/s单向。如果你在通信时没感知到这些层次差异把一个本来可以在NVLink上完成的数据交换硬生生通过网卡绕了一圈那性能就是断崖式下跌。所以通信库必须要先“摸清家底”也就是做拓扑识别。NCCL的做法是通过系统调用和硬件探测建立一颗逻辑拓扑树最底层是单个GPU往上是GPU所在的NUMA节点或PCIe交换机再往上是CPU socket最顶层是网卡和跨节点链路。有了这颗树通信库在做数据传输规划时就可以优先走带宽高、延迟低的路径减少跨socket的流量同时尽量让数据在本机内完成规约再发送出去降低跨节点流量。我提个实操细节你如果自己写通信库拓扑识别千万别偷懒。我曾经见过一个项目最初只在初始化时简单检测了GPU数量没做层级关系建模。结果在4卡机上表现正常换到8卡机就出现部分GPU之间走了非常慢的路径性能掉了一半。后来加上拓扑树之后问题直接解决。拓扑信息不光是性能问题它还决定了通信分组的合理性——哪些进程应该被划分为一个通信组哪些数据应该先在本机聚合。3.2 通信协议的选择从TCP到RDMA再到NVLink通信库的另一大核心设计是底层传输协议的选择。传统上跨节点通信最常见的协议是TCP/IP优点是不挑硬件、只要网络通就行缺点也很明显内核协议栈开销大、CPU占用高、延迟相对较高。高性能计算领域更偏好RDMA远程直接内存访问技术典型实现是InfiniBand和RoCERDMA over Converged Ethernet。RDMA最大的特点是“绕过内核”数据可以直接从应用缓冲区拷到网卡再由网卡发到对端内存整个过程几乎不消耗接收端CPU。这带来的好处是延迟大幅降低、带宽利用率提高。通信库在设计上通常是一个多传输层的架构它先探测硬件支持哪些协议然后按优先级选择。比如NCCL在跨节点通信时优先用IBInfiniBand如果不支持就退到RoCE再不行才用TCP Socket。这个“降级”逻辑做得好的话代码同一套在不同硬件环境下都能跑只是性能有差异。但这里也有个坑RDMA虽然快但配置复杂特别是RoCE需要开启流控PFCPriority Flow Control、正确配置拥塞控制策略否则在高负载下丢包率飙升性能一落千丈。我遇到过不少团队代码没换就是把RoCE交换机的流控关了性能直接掉两倍。这问题特别隐蔽因为网络还是通的通信也不报错就是速度慢得离谱。你排查通信性能问题时一定要先把网卡、交换机层面的配置检查一遍。3.3 多网卡多路径带宽倍增的关键去年的项目里我们遇到一个很有意思的问题机器上有两块100GbE网卡但分布式训练的通信带宽始终只有单块网卡的水平另一块网卡的流量几乎为零。查来查去发现是通信库没有启用“多路径”能力所有流量都hash到了同一块网卡上。启用多路径之后带宽几乎翻倍。多路径的核心思想是把一条通信流拆成多个子流分别走不同的网卡。这需要通信库在逻辑层支持“Channel”的概念——一个Channel就是一个独立的通信链路可以绑定到一个具体的网络接口。通信发起时数据被拆分成多个块每个块通过不同的Channel发送接收端再重新拼装起来。这个机制写起来不算复杂但对性能的提升非常直接尤其是在节点数不多、单条网络带宽成为瓶颈的情况下。还要注意多路径和拓扑识别的配合。如果拓扑识别没做好两块网卡可能都挂在同一个CPU socket上那么数据从对端socket跨NUMA访问网卡反而会引入额外延迟。推荐的做法是每个GPU优先绑定“离它最近”的网卡这样跨节点通信时数据不需要跨NUMA。这个类似“就近原则”的优化很多时候比单纯加带宽更有效。4. 实操踩坑与调优心法4.1 通信启动慢、卡顿多半是初始化问题通信库实际使用中第一步就容易出事——初始化。以MPI为例MPI_Init本身不慢但如果你在一个几千核的集群上同时启动所有进程并且所有进程都在初始化阶段尝试互相建立连接网络设备可能会扛不住瞬间的大量连接请求导致初始化时间暴涨甚至超时。解决方案一般有两个方向。一是“分阶段初始化”让进程按组建立连接而不是全体同时握手二是“提前预连接”也就是说在计算阶段开始之前就预先建立一个通信组后续的通信直接复用这些连接。有些通信库还支持“Lazy Initialization”——第一次通信时才实际建立连接。这个选项在节点数非常大时能有效缩短启动时间如果你觉得应用启动慢得离谱可以排查一下是不是初始化阶段把所有连接一次性全建了。另外如果你在容器里跑通信库要特别注意共享内存和IPC锁的问题。NCCL在同一节点内的GPU间通信会使用共享内存和NVLink容器默认的IPC命名空间限制可能导致进程间无法正常使用共享内存表现出来就是初始化失败或者性能下降。解决方法是在启动容器时加上--ipchost如果有GPU还要加上--gpus all并确保NVIDIA容器工具包配置正确。4.2 带宽上不去从环境变量和参数配置入手通信库的性能调优很大程度上是环境变量的调优。很多工程师觉得调参太低端其实参数调优是通信库这个领域最实用、见效最快的技能。拿NCCL来说常用环境变量包括NCCL_IB_DISABLE是否禁用InfiniBand默认情况是自动检测如果硬件上没配好自动检测失败时可能回退到TCP性能大减。你可以先显式设置为0强制启用IB确认是否生效。NCCL_NET_GDR_LEVEL是否启用GPUDirect RDMA让GPU显存直接跟网卡DMA不经过CPU内存中转。这个对跨节点通信性能提升非常大但要求网卡支持BAR1映射且驱动配置正确。NCCL_BUFFSIZE通信缓冲区大小默认通常够用但如果你在消息大小很大的场景下遇到性能波动适当调大缓冲区可以减少同步等待。NCCL_MAX_NCHANNELS控制通信通道数量。通道数太少会限制并行度但太多也可能造成资源竞争。一般建议从默认值开始用nvidia-smi topo -m查看拓扑结构判断该用多少通道。更通用一点MPI这边也有几个重要参数。OpenMPI的btlByte Transfer Layer和pmlPoint-to-Point Management Layer参数决定了它用什么协议传输比如btl^openib代表禁用InfiniBand如果你确认网络支持IB却走得慢可以检查是不是这个参数被设了OMPI_MCA_btl_tcp_if_include可以指定用哪些网络接口避免跨机器时意外走了管理网络这个坑我踩过——通信库把数据发到了管理网口带宽只有1Gbps整个训练慢如蜗牛。我的建议是做性能调优前先拉一张集群网络拓扑图确认哪些网卡是高性能计算专用网、哪些是管理网、哪些是存储网。然后在通信库参数里显式指定高性能计算网卡而不是让它自动选择。自动选择在复杂网络环境下经常会翻车直接指定最稳妥。4.3 死锁与超时通信库的隐形杀手通信死锁是个老生常谈但永远在犯的问题。最典型的场景是两个进程都在等对方先发送结果两边都不发直接僵住。你写代码时可能觉得逻辑没问题但数据量一大、消息一多某个同步点的时序错位就会引发死锁。为了避免这种问题设计通信逻辑时一定要遵循“同序收发”原则——所有进程按相同的顺序发起通信操作。比如进程0先给进程1发数据、再从进程1收结果那进程1也必须是先收进程0的数据、再给进程0发结果。如果进程0和进程1的收发顺序不一致就可能出现双方都在等待的僵局。通信库层面有时会提供超时设置来兜底。比如UCX的UCX_RDMA_TIMEOUT、NCCL的NCCL_TIMEOUT实际上很多版本不支持直接设置需要通过环境变量或上层框架控制。超时设计是双刃剑设得太短正常的慢速通信会被误杀设得太长故障恢复遥遥无期。我的经验是把超时设为比正常通信耗时高一个数量级既能兜底又不至于频繁误触发。4.4 通信性能问题排查速查表这里整理一份我自己排查通信性能问题时经常对照的清单虽然不能覆盖所有情况但能解决大多数“莫名其妙慢”的问题。现象可能原因排查/解决动作跨节点通信带宽上不去走了TCP而非RDMA/IB检查通信库日志确认传输层类型强制启用IB并验证连通性GPU利用率周期性掉零通信与计算没有重叠同步开销大开启通信与计算异步流水线用CUDA Stream让通信并行执行多机性能远低于单机网络拓扑感知未开启流量走了低带宽链路检查拓扑识别结果确认通信通道绑定到正确网卡通信延迟抖动大交换机关闭流控或拥塞控制配置不当检查网络设备的PFC、ECN配置必要时跟网络团队协作排查初始化失败/进程崩溃容器IPC命名空间限制、共享内存不足容器加--ipchost调大/dev/shm8卡机上部分GPU通信慢NUMA亲和性差数据跨socket访问绑定GPU和网卡到同一NUMA节点调整线程亲和性4.5 通信与计算重叠让流水线转起来最后这个问题我想单独说一说因为它太重要了——通信和计算的重叠。很多跑分布式训练的人性能上不去不是因为通信库慢而是因为通信和计算是串行执行的GPU先算完一个forward和backward然后开始通信通信期间GPU在“干等”通信完了才算下一个batch。这个“干等”时间就是白白浪费的算力。解决思路是把通信操作放进独立的CUDA Stream里让它在计算Stream执行的同时异步进行。PyTorch的DDP其实已经做了类似的事——在backward过程中梯度计算完一部分就立刻同步一部分但如果你是手动实现分布式逻辑就需要自己设计这种流水线。大致的做法是把数据切分成多个分片对每个分片分别计算梯度、发起通信这样在等待通信返回的同时另一个分片的计算已经在跑了。这个优化如果做到位端到端性能提升20%~50%都很常见。通信库本身也提供了一些底层支持比如NCCL的“Split”通信操作允许把一个Allreduce拆成若干个子操作配合Stream来和计算流水线交错执行。你如果能理解这一层你就不只是在“用通信库”而是在“设计通信流程”了。这也是从普通用户走向高性能计算工程师的关键一步。5. 如何从零选型与封装一套通信中间件5.1 选型开源库 vs 自研怎么权衡如果你在考虑给团队搭建一套通信基础设施第一个问题肯定是直接拿开源库用还是自己写一层封装我的建议是绝大多数情况下直接把成熟的通信库作为底层引擎然后在上面做业务层封装。NCCL、OpenMPI、UCX这些项目经过了无数生产环境的打磨单点性能、稳定性、异常处理都做得非常完善你自己从零写一套投入巨大且性能大概率还不如人家。但有一个场景可以考虑自研——你的业务有非常特殊的通信模式比如不规则的点对点通信、动态的节点加入退出或者需要跟自研的调度器深度集成。这时候直接在通信库上层加一个“适配层”是更合理的选择底层仍用NCCL或MPI处理数据和GPU通信上层封装你自己的协议、语义和调度逻辑。这种分层设计既能享受到开源的性能红利又能保留业务灵活性。选型时还要考虑生态兼容性。比如你做的是AI训练PyTorch生态默认集成NCCL你用MPI来做Allreduce反而要多一层转换你做的是传统科学计算MPI是绝对主流再往上加NCCL就没有必要。先想清楚应用场景再选库别反过来先定库再找场景。5.2 封装通信库时的接口设计要点如果你决定做上层封装我建议接口设计上注意几点提供“进程组”抽象通信操作默认绑定到一个进程组上这样不同业务可以使用不同的通信域互不干扰。区分“集合通信”和“点对点通信”接口把高频使用的Allreduce、Broadcast、Allgather做得足够简单最好调用时只需要传入数据张量、目标根节点等必要参数。引入“通信组”的概念把通信参与者按需划分成多个子组通信组内部的通信不会影响其他组。这在高性能计算里叫communicator拆分在AI训练里则类似NCCL的group概念。支持异步策略在所有通信调用上提供异步版本调用方可以自行决定是否等待结果。这个对性能流水线至关重要。还有一个小建议封装时要考虑异常回调机制。通信库底层偶尔会出现网络断连、设备错误等运行时异常如果上层没有感知程序可能直接挂起或产生错误结果。预留一个错误处理回调让业务层能及时感知并触发重连或降级策略这在长时间运行的训练任务里非常重要。5.3 是否需要支持动态拓扑分布式计算场景里动态拓扑是个常被忽略的需求。普通单次训练任务节点固定、通信关系固定静态拓扑就够了。但如果你做的是资源池化——多个任务共享一批节点或者有任务在运行过程中需要扩容缩容那通信库就要支持“动态创建和销毁通信组”。动态拓扑对通信库的挑战在于新建通信组时现有通信组的传输不能被中断销毁通信组时要确保所有相关通信操作都已经结束否则可能引发数据损坏。实现上通常需要引入版本号或handshake机制。如果你不确定是否需要动态拓扑可以先不做把它留成扩展接口等业务需要时再实现——毕竟动态拓扑的复杂度会显著拉高通信库的维护成本。6. 实测心法一个典型Allreduce优化案例前面讲了太多理论这一节我拿一个真实遇到的案例来串一下。之前帮一个团队优化分布式训练现象是8节点、每节点8张V100 GPU跨节点Allreduce只跑到预期带宽的40%左右。我们做了三件事性能逐渐恢复正常。第一件事是检查传输层。看通信日志发现跨节点通信走的是TCP而不是IB因为节点上的IB驱动没有正确加载通信库自动回退到了TCP。我们把驱动装好、确认ibstatus正常后通信库自动切回IB带宽立刻从40%提升到70%——注意是立刻代码一行没动。这里有个经验通信库的自动检测有时候过于保守一旦检测到设备不完全正常就会回退而回退之后又不会主动做二次探测。你可以通过日志或API显式确认实际使用的传输层。第二件事是多路径。把IB驱动修好后我们发现虽然走的是IB但只用了两块IB网卡中的一块。打开拓扑日志确认通信库没有检测到第二块网卡可用。排查原因是网卡的IP地址配置不完全匹配——通信库只识别特定网段的IP我们第二块网卡配了个不同网段的地址导致它被忽略。把IP配到同一网段/子网后通信库自动启用了多路径带宽从70%提升到90%左右。第三件事是调整通道数。多路径启用后我们继续观察性能发现在小消息场景下延迟还偏高。通过调整通信通道数让更多的小消息并行发送延迟降低了约30%。这里要说明通道数不是越大越好太大的通道数在某些环境下反而会加剧竞争需要根据实际消息大小分布做调参。我们最终是跑了一个小范围的网格搜索选了当前场景下的最优值。这个案例想说明的其实就是一点通信库的性能问题多数时候不是某一个环节错了而是多个环节叠加导致的。排查顺序很关键我的建议永远是“先硬件、再协议、再拓扑、再参数”。硬件没通就先调协议调半天也是白费。7. 一些你可能会忽略的经验写到最后分享几个比较零散、但实际工作中帮了我很大忙的经验。第一个是日志和profile工具的运用。很多通信库都提供了详细的运行时日志和profiling接口比如NCCL的NCCL_DEBUGINFO和NCCL_DEBUG_FILEOpenMPI的ompi_info。遇到问题第一件事不是改代码而是把详细日志打开看看通信到底走了哪条路径、用了哪种协议、建立了多少连接。很多时候日志里直接写着答案——例如“NET/IB : Could not open RDMA device”这直接告诉你是RDMA设备没有正确映射而不是通信库本身的问题。第二个是小心多进程的CPU绑核问题。通信库的线程通常也需要绑定CPU核心尤其是使用RDMA的场景。如果通信线程和计算线程抢同一个核心性能会明显下降。推荐的做法是给通信线程单独留出核心或者至少把通信线程绑定到网卡所在NUMA节点上的核心。第三个是版本兼容性问题。通信库的版本跟CUDA版本、GPU驱动版本、网卡驱动版本之间经常存在兼容矩阵。升级任何一个组件时都要先确认通信库官方文档里的支持情况。我见过不止一次因为升级CUDA导致的通信库性能回退问题——不是通信库坏了而是性能和新的CUDA版本没有经过完全调优。第四个是很反直觉的有时候“更小的缓冲区”反而更快。缓冲区大意味着可以承载更大的突发流量但也可能降低了数据切分的粒度导致流水线无法充分利用多个通道的并行能力。如果你观察到性能随缓冲区大小增加先升后降说明你的消息切分逻辑需要配合缓冲区大小同步优化单纯调大缓冲区并不总是好事。8. 从一个库到一个系统通信库之外的事做高性能计算通信库哪怕你自己没有那个精力去写底层协议也要有系统的眼光去理解它在上层架构中的位置。通信库不是孤立的它跟任务调度器、存储系统、网络配置、硬件选型、上层框架紧密耦合。举一个例子任务调度器决定了你的进程被分配到哪些机器上这个分配结果直接决定了通信拓扑——如果调度器把两个通信频繁的进程分到了物理上很远的不同机柜那延迟和带宽都会受影响。你在做资源调度策略时如果不理解通信库的拓扑感知逻辑很难做好“通信感知调度”。这也是为什么现在大厂做训练集群都会专门有“topology-aware scheduling”的需求。再举一个例子存储系统和网络通信经常抢带宽。如果训练过程中需要频繁写checkpoint而存储网络和高性能计算网络没有隔离那么checkpoint写入就可能影响同网络上的通信流量。我在一个项目里遇到过训练每个epoch之后性能突然掉一大截的情况最终定位到是checkpoint的异步写把网络打满了。解决思路就是把存储流量和高性能计算流量规划到不同的物理网络或者在存储写入时做流量限速避免影响通信。所以我的一个看法是通信库的性能优化最终比拼的是对整个硬件和系统stack的理解。通信库本身是工具但你要拿它做多少事情取决于你对这个工具所处生态系统的掌控程度。这篇文章从通信原理聊到工程实践再聊到系统观整体已经覆盖了高性能计算通信库的核心面貌。如果你正在做一个跟通信库相关的项目希望这些内容对你有所启发如果你还没碰到通信瓶颈也希望这能帮你在设计之初就避开那些后来很难改的问题。
返回列表