Ray多机启动实战:大模型推理GPU集群调度与排障
最近在做一套多机大模型推理服务模型权重分散在几台GPU机器上头一回用Ray往多个节点拉起进程的时候我犯了个很低级的错误只在head节点执行了ray start --head然后在另一台机器上敲了半天ray start --address...结果dashboard里始终只有一个节点模型的请求全部压在head这一台上GPU利用率没法看。排查了一整个下午才发现是网络端口和启动参数没对齐。这类问题在做多机Ray集群的人身上太常见了。很多人以为“多机启动”就是多执行几遍启动命令实际上一旦涉及大模型推理进程发现、资源上报、模型切分、NCCL通信这些环节都会咬合在一起任何一个环节错位整个集群看起来活着但推理就是不生效。这篇文章我会从Ray多机启动的底层机制聊起用一套完整的命令和验证脚本把流程串起来再讲大模型推理场景里怎么把模型进程真正调度到多张GPU上最后复盘几个我实际踩过的坑和完整的定位链路。1. 推理场景下为什么偏偏用Ray做多机进程调度1.1 单机推理卡在哪显存放不下吞吐上不去先说个最直接的场景。一个70B量级的稠密模型光FP16权重就有大概140GB就算做INT8量化也需要70GB左右。单机就算插满8张80GB的GPU想同时放下权重、KV cache和推理中间激活几乎不可能。这时候要么做张量并行把权重切到多卡上要么把模型拆成多个流水段放到多台机器上本质上都必须走向多机多卡。另一种更普遍的情况是并发问题。推理服务上线之后请求QPS一旦上来单机GPU的算力就变成瓶颈。我不可能为了抗住流量无限堆单机高配更合理的做法是同一份模型在多台机器上各放一个副本流量通过调度层分到不同节点。这里面绕不开一个多机器之间进程如何编排的问题。1.2 Ray解决的并不只是“多几张卡”看到这里你可能会说那我用Kubernetes或者直接用裸机上的systemd拉起多个进程不也一样确实可以但区别在于动态性和资源统一视图。大模型推理服务有两个很现实的诉求一是不同模型的流量有波峰波谷我想在某个时间点把A模型的3个副本缩成1个同时把B模型的副本从1个扩到4个这个过程最好不需要人工SSH到某台机器上敲命令二是集群里的GPU、CPU、内存资源需要被统一统计和调度否则很容易出现某个节点GPU闲置、另一个节点任务排队的情况。Ray这套框架在这一层做得比较顺手。它把整个集群抽象成一个资源池head节点负责全局调度每个worker节点定期上报本机资源用户代码通过ray.remote标注某个函数或类需要几张GPU、多少个CPU调度器会自动寻找满足条件的节点并且在运行的时候把节点IP、GPU ID等信息暴露给程序。对大模型推理来说这个抽象几乎是现成的。1.3 多机启动要解决的核心问题提炼一下多机启动本质上要解决三件事进程发现每台机器上的Ray进程如何知道彼此存在建立一个统一的集群视图。这靠head节点暴露一个固定端口worker节点主动连上来注册。资源上报每台机器上有多少GPU、多少CPU、多少内存必须准确汇报给调度器否则任务无法落到正确的节点。作业分发用户提交的推理任务通常是若干actor如何被拆分到不同节点的raylet进程上由raylet在本机拉起业务进程。这里有个容易混淆的点也是一开始困扰我的地方Ray多机启动拉起的是“Ray运行时进程”不是“模型推理进程”。Ray运行时进程包括每台机器上的raylet、object store等它们负责通信、存储和调度。模型推理进程是你后续提交流程里由Ray调度的业务actor。只有先把Ray运行时铺到所有机器上后续的推理任务才能被调度到不同节点。2. 启动多机Ray集群前先搞清楚这些角色2.1 head节点控制面、对象存储和Dashboard都在这台机器上在Ray的架构里head节点承担了全局控制服务GCS的作用所有节点的注册信息和资源信息都汇聚到这里。它同时还跑着Dashboard服务和对象存储服务。也就是说head节点不仅仅是“第一台启动的机器”它是整个集群的中枢。所以head节点的稳定性很重要。如果head挂了整个集群的调度就瘫痪了即使业务进程还在各节点上跑着也无法再接收新的任务。这也是很多人做生产级推理服务时会考虑给head单独留一台高可靠机器或者用容器化方式把它托管起来的原因。2.2 worker节点是如何“入群”的worker节点本身不承担全局调度职责它的核心进程是raylet。raylet负责管理本机资源、执行分配的task并且维护本机的对象存储。当你执行ray start --addresshead_ip:6379的时候worker节点上的raylet会向head的GCS发起注册请求完成握手之后把自己这台机器的CPU、GPU、内存等资源上报上去。此时你再回到head节点执行ray status就能看到集群节点数增加了。有一个参数值得多说一句如果你发现worker一直连不上head先别急着改业务代码去head机器上执行一下ss -lntp | grep 6379确认GCS端口监听在0.0.0.0而不是127.0.0.1。我遇到过双网卡机器启动时选了错误IP导致GCS只监听在内网回环地址上worker当然永远连不上。2.3 启动过程里到底起了哪些进程在head节点执行完ray start --head之后你可以用ps aux | grep ray看到这一堆进程gcs_server、raylet、dashboard、agent等。gcs_server是集群元数据中心raylet是本机资源管理和任务执行器dashboard提供Web界面。在worker节点执行ray start --address...之后主要看到的是raylet和agent。这里有个容易想当然的地方head节点本身也计算资源可用。ray start --head默认会在这台机器上也启动一个raylet也就是head节点既做控制面也参与计算。如果你不想让head节点跑推理任务需要在后续的ray.remote里通过资源约束把它排除比如给head节点的raylet设置--num-cpus0。3. 从零拉起多机进程完整命令与验证脚本3.1 准备阶段网络、版本、存储三项检查多机启动的准备工作其实比启动本身更重要我习惯按下面顺序检查网络连通性两台机器之间先互相ping通再用nc -vz head_ip 6379确认GCS端口通。如果有多网卡一定要确认业务网卡是哪个避免走管理网卡导致通信超时。版本一致性Ray对版本一致性要求非常严格。head节点是2.9.3worker节点是2.10.0启动大概率失败而且报错信息很隐晦。建议在每台机器上执行ray --version核对或者用同一份依赖lock文件安装。模型存储路径多机加载同一个模型文件时最好用NFS或并行文件系统挂载到各节点相同路径。如果只能本地放那就要保证每台机器上的模型路径完全一样比如统一放到/data/models/llm-70b否则不同节点拉起进程时会出现“有的节点加载成功、有的节点文件找不到”的诡异问题。3.2 在head节点启动控制面假设head节点IP是192.168.1.108张GPU物理内存256GB我建议这么启动ray start --head \ --port6379 \ --dashboard-host0.0.0.0 \ --dashboard-port8265 \ --num-gpus8 \ --object-store-memory30000000000这里几个参数分别说明一下--port6379是GCS端口worker节点后续要用这个端口连过来所以不要随意改动如果改了记得保持一致。--dashboard-host0.0.0.0很关键。默认Dashboard可能只绑定在本地回环地址你从浏览器访问head机器IP的8265端口会失败。显式设置成0.0.0.0之后就可以从任意机器的浏览器打开http://192.168.1.10:8265。--num-gpus8是告诉Ray这台机器有8张GPU。正常情况Ray能自动探测到但我遇到过容器环境里探测不准的情况手动指定更稳。--object-store-memory30000000000是对象存储内存上限我给了30GB。默认值通常是物理内存的一部分但大模型推理时每台节点还要加载权重如果对象存储占太多内存容易把节点拖死。这个值需要根据物理内存和模型加载需求调整原则是给模型加载和系统运行留足空间。3.3 在worker节点加入集群假设worker节点IP是192.168.1.11也是8张GPU执行ray start --address192.168.1.10:6379 --num-gpus8这里不需要再指定--port因为端口是head那边统一管理的。worker节点只需要知道head的地址和GCS端口剩下的资源上报、通信建立都会自动完成。启动之后回到head节点执行ray status如果输出里能看到两个节点的IP和各自的GPU资源就说明集群已经建立成功了。3.4 用一段脚本验证任务真的落到多机了很多人觉得启动命令执行完没有报错就万事大吉其实不一定。我见过“集群两个节点都Alive但所有任务全跑在head节点”的情况原因是调度时GPU资源不够或者代码里写入的节点约束不对。所以建议用一段很小的脚本验证调度是否真正分散import ray import time ray.remote(num_gpus1) def whoami(): time.sleep(1) return ray.util.get_node_ip() if __name__ __main__: ray.init(addressauto) results ray.get([whoami.remote() for _ in range(16)]) print(results)在head节点所在环境执行这个脚本ray.init(addressauto)会自动连到当前集群。如果调度正确输出里会同时出现两台机器的IP而不是只有head节点的IP。这里有个注意点addressauto只适用于已经在Ray集群节点上执行脚本的场景。如果你是从一台未加入集群的运维机器上提交任务就要用ray job submit --address http://192.168.1.10:8265 -- python test.py这种方式。3.5 停止集群时的顺序问题停集群最忌讳乱杀。我建议先停worker节点每个worker节点执行ray stop最后停head节点。如果进程卡死可以加--force参数。直接kill -9很容易留下残留的socket文件和锁导致下次启动时报端口占用或临时目录冲突。如果遇到重启后6379端口起不来多半是旧raylet进程没杀干净。执行ps aux | grep ray把残留进程处理掉再把/tmp/ray下对应session的临时目录清掉基本就能恢复。4. 模型推理任务如何真正分布到多机多卡4.1 用ray.remote封装模型worker集群建立只是第一步大模型推理业务进程怎么利用多机资源才是重点。我常用的方式是把一个模型推理服务封装成Ray actorimport os import ray ray.remote(num_gpus1, max_restarts1) class LLMWorker: def __init__(self, model_path: str, rank: int): self.rank rank # 拿到Ray分配给这个actor的GPU ID并绑定到当前进程可见设备 gpu_ids ray.get_gpu_ids() if gpu_ids: os.environ[CUDA_VISIBLE_DEVICES] ,.join(str(g) for g in gpu_ids) self.model self._load_model(model_path) def _load_model(self, model_path): # 这里调用具体的推理引擎加载模型传入rank等环境信息 pass def generate(self, prompt: str): return self.model.generate(prompt)这里有一个很多人忽略的细节Ray的num_gpus1只是给调度器看的资源约束它不会自动帮你设置CUDA_VISIBLE_DEVICES。如果不显式从ray.get_gpu_ids()里读取并设置环境变量actor里的推理框架很可能会去探测宿主机上的全部GPU导致多个actor共用同一张卡或者出现CUDA OOM。4.2 多机并行时模型切分和通信交给谁这里要把Ray的职责边界说清楚。Ray负责的是“哪台机器、哪张GPU上拉起哪个进程”但它不做模型张量并行或流水并行的计算图切分。真正的切分和跨节点NCCL通信由推理引擎自己完成。所以在多机推理场景里通常是这样协作的Ray启动N个actor每个actor代表一个模型分片或一个模型副本引擎初始化时通过环境变量比如MASTER_ADDR、MASTER_PORT、RANK、WORLD_SIZE建立NCCL通信域。如果模型必须跨节点张量并行head节点的IP通常会被当成MASTER_ADDR端口需要固定并且防火墙上开放。这里最常见的坑就是MASTER_ADDR填成了127.0.0.1导致多机之间的NCCL初始化卡住。4.3 用Ray Serve包装成HTTP服务如果要把多机推理暴露成在线服务我建议直接用Ray Serve的Deployment封装而不是自己起Flask再对接Rayfrom ray import serve import ray serve.deployment( num_replicas4, ray_actor_options{num_gpus: 1} ) class Inference: def __init__(self, model_path: str): self.model self._load(model_path) async def __call__(self, request): prompt request.query_params[prompt] return self.model.generate(prompt) serve.run(Inference.bind(model_path/data/models/llm-70b))num_replicas4会创建4个副本Ray会把它们分散到集群中满足num_gpus1的节点上负载均衡和健康检查由Serve自动处理。我在实践里比较推荐这个方案因为它把“多机启动、多副本调度、HTTP入口”这几个环节整合到了一套API里。4.4 资源绑定和节点分布的验证通过Serve部署之后我一般会在Dashboard的Actors页面确认每个副本所在的节点IP和GPU ID也可以写一行脚本遍历所有actor打印出节点分布from ray.serve import get_replica_context # 实际运行时在Replica内部可以通过get_replica_context获取当前副本信息这一步非常值得做。多机部署最大的风险不是“部署不上”而是“你以为在跑多机实际所有副本都挤在了一台机器上”。一旦确认分布正确再压流量才有意义。5. 多机启动过程中的经典故障与定位链路5.1 worker节点始终Alive不了从netstat到gRPC握手现象head节点正常worker节点执行启动命令也不报错但Dashboard里节点数不变。我的排查链路是这样的在head机器执行ss -lntp | grep 6379确认GCS监听地址。如果看到127.0.0.1:6379基本可以断定head启动时绑错了网卡。解决办法是重新用ray stop清理然后指定对外网卡启动ray start --head --node-ip-addresshead对外IP --port6379。在worker机器执行nc -vz head_ip 6379确认基本网络通。如果端口通还连不上检查两台机器的Ray版本是否一致。有一次我把worker的Ray升到2.10.0head还是2.9.3结果worker一直处于Registration状态日志里反复报协议不匹配。再看系统时间是否一致。Ray内部gRPC握手对时钟漂移敏感如果两台机器时间差太大认证会失败。用ntpdate同步一下时间再重试。5.2 模型初始化时NCCL卡死现象提交多机推理任务后日志一直停在Waiting for rendezvous所有GPU利用率都为0。这个坑我踩过不只一次。根因几乎总是出在跨节点通信环境变量上。多机分布式进程组初始化需要各个rank都能访问到MASTER_ADDR:MASTER_PORT这个地址必须是所有节点都能访问的对外IP不能是localhost。另外NCCL默认会选择它认为合适的网卡通信如果服务器有多个网卡比如一个业务网卡一个存储网卡NCCL可能选错。解决办法是在每个节点启动推理进程之前显式指定export NCCL_SOCKET_IFNAMEeth0eth0换成你实际业务网卡的名字。这一步能解决很多“明明IP能通却初始化卡死”的问题。5.3 对象存储内存占用过高导致节点OOM大模型推理时有人会把模型权重直接作为Ray对象传递比如对某个大tensor做ray.put。这其实是非常危险的操作。Ray对象存储默认基于共享内存跨节点传输几十GB的权重会瞬间占满对象存储空间触发eviction甚至让节点内存耗尽。我的建议是模型权重永远不要通过Ray对象存储传。正确做法是把模型放在共享文件系统或者各节点本地磁盘actor初始化时从路径加载。Ray只负责传字符串路径这种小对象大对象传输不仅慢还容易引发连锁故障。如果确实有中间结果需要传大对象那就需要精确调大--object-store-memory同时留意物理内存余量否则很容易把节点搞挂。5.4 明明有8张GPU任务却排队等资源现象ray status显示集群总共16张GPU但提交num_gpus2的任务却一直Pending资源池显示GPU为0/16。先看ray status里每个节点的GPU是不是0/8。如果节点显示0张GPU多半是Ray没探测到GPU检查启动时是否忘了--num-gpus或者NVIDIA驱动在容器里没有被正确映射。如果GPU显示正常但总是Pending那就要看是否已有其他actor占用了资源。我有一次就是因为上一个任务异常退出但actor没有释放GPU导致后续任务全部排队。这时候去Dashboard看Actor列表把僵尸actor删掉或者干脆重启整个Ray集群问题就解决了。还有一种情况是资源声明和实际不匹配。比如每台机器只有8张GPU但某个actor声明了num_gpus1同时因为代码里设置CUDA_VISIBLE_DEVICES失败导致进程实际占用了多卡后续任务自然就等不到资源了。所以每台节点上都要做一次“资源声明与实际占用”的对照确认没有偏差。5.5 建议养成的排查习惯多机Ray集群排障最重要的不是记住某个具体错误码而是养成一套标准动作。我的习惯是启动后先执行ray status保存资源快照提交任务后去Dashboard看每个Actor的节点分布日志优先看/tmp/ray/session_latest/logs/下的raylet.out和python-core-driver日志代码里在actor初始化时打印一行node_ip gpu_ids便于确认进程实际落在哪张卡上。这套动作帮我排查掉了很多看起来很玄学的问题大部分所谓“偶发失败”其实都是资源绑定或网络配置没对齐。多机启动Ray本身不难难的是每一步都验证到位。大多数启动失败并不是Ray框架的问题而是网络端口、版本一致性、GPU资源声明这些工程细节。在做大模型推理服务化的时候我逐渐形成了一个习惯任何多机启动之前先写一个只包含端口探测和版本核对的检查脚本把90%的启动问题挡在前面。如果你也在做类似的事情建议先把这两步固定成流程剩下的再交给Ray去调度。

相关新闻

Bootstrap 3 侧边导航栏生产级实现方案

Bootstrap 3 侧边导航栏生产级实现方案

简介:本资源是一份基于Bootstrap 3框架实现的响应式侧边导航栏完整示例,面向前端初学者与Web开发人员,解决在传统网页中快速构建结构清晰、适配多端(尤其移动端折叠交互)的垂直导航结构问题。压缩包共9个文件&#xff…

2026/10/17 3:24:49 阅读更多 →
OpenCV文档图像增强实战:从光照不均到高精度OCR预处理

OpenCV文档图像增强实战:从光照不均到高精度OCR预处理

1. 文档图像增强到底在解决什么问题做过文档扫描、拍照存档或者OCR识别的人,大概率都遇到过这样的场景:手机拍了一张纸质合同,光线不均匀,左边亮右边暗,中间还有一道阴影;或者用扫描仪扫出来的老文档&#…

2026/10/17 3:24:49 阅读更多 →
桌面端微信接入实战:用Claw中间件打通个人微信消息自动化

桌面端微信接入实战:用Claw中间件打通个人微信消息自动化

身边不少折腾过微信自动化的朋友,最后都卡在同一个地方:手机端的机器人方案要么要求系统环境特殊,要么长期挂着不稳定;云端方案又拿不到个人微信的完整会话数据,用起来总觉得隔了一层。我自己的需求其实很朴素——想把…

2026/10/17 3:24:49 阅读更多 →

最新新闻

Python计算机二级题库全解析:考纲、刷题技巧与备考误区

Python计算机二级题库全解析:考纲、刷题技巧与备考误区

简介:面向全国计算机二级Python备考人群,这份题库将近年常考知识点与真题题型整理为可直接刷练的练习集,覆盖选择题、操作题等常见考核模块,并配套参考答案与解析,帮助考生在考前快速定位薄弱环节、掌握得分要点。压缩…

2026/10/17 4:03:00 阅读更多 →
AHA-WAM世界模型实战:从RoboTwin数据到Wan权重部署

AHA-WAM世界模型实战:从RoboTwin数据到Wan权重部署

1. 项目概述:为什么“世界模型”不是玄学,而是可落地的机器人认知基座最近在工业自动化和具身智能圈子里,“世界模型”这个词出现频率高得有点吓人——不是那种被PPT反复咀嚼的空泛概念,而是真有人在产线边缘设备上跑通了AHA-WAM推…

2026/10/17 4:03:00 阅读更多 →
PyTorch实现FPN+ResNet:多尺度特征融合的工程实践指南

PyTorch实现FPN+ResNet:多尺度特征融合的工程实践指南

1. 项目概述:为什么FPNResNet这个组合值得深挖“基于PyTorch的ResNet的FPN”——这短短十个字,背后其实是一条被工业界反复验证、在目标检测与实例分割任务中稳坐主力位置的技术路径。我从2018年开始在某高校实验室做遥感图像分析项目时第一次完整复现FP…

2026/10/17 4:03:00 阅读更多 →
基于MP2642GR-Z与STM32F429NI的两串电芯被动均衡BMS设计实战

基于MP2642GR-Z与STM32F429NI的两串电芯被动均衡BMS设计实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 4:03:00 阅读更多 →
Codex正价方案性价比表:用TaoToken统一Key做多模型成本对照

Codex正价方案性价比表:用TaoToken统一Key做多模型成本对照

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 4:03:00 阅读更多 →
环境变量全攻略:从原理到实战,避开PATH与配置那些坑

环境变量全攻略:从原理到实战,避开PATH与配置那些坑

说实话,我见过太多人在环境变量上栽跟头了。明明代码逻辑一点问题没有,换台机器跑就报错,最后折腾半天发现是环境变量没配对。环境变量这东西,说简单,十分钟就能学会怎么用;说复杂,它能让你在深…

2026/10/17 4:02:00 阅读更多 →

日新闻

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

简介:《DeepSeek使用方法.pdf》是一份面向DeepSeek入门及进阶用户的完整使用指南,重点围绕V3与R1两款模型的能力差异与适用场景展开,帮助读者根据任务类型与成本选择合适的模型。资源共1个PDF文件,压缩包大小约311KB,篇…

2026/10/17 0:00:25 阅读更多 →
200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

简介:这是一份聚焦DeepSeek提示词优化的《200Deepseek润色指令》PDF文档,共收录两百余条可直接套用的润色指令,涵盖语法修正、风格统一、逻辑梳理、表达精炼等维度,并针对商务写作、学术论文、广告文案等场景给出差异化建议。文档…

2026/10/17 0:00:25 阅读更多 →
OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

简介:本资源是一份基于OpenCV的本科课程设计完整报告,面向计算机视觉初学者、图像处理学习者及高校通信/信息类专业学生,解决物体智能计数与检测结果结构化记录的实际问题。项目覆盖图像预处理、轮廓检测、边界框绘制、轨迹栏交互式参数调节、…

2026/10/17 0:00:25 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/16 21:35:51 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/17 1:44:59 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/16 15:04:24 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 21:54:38 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 3:49:43 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 14:23:36 阅读更多 →