新闻详情

新闻详情

首页 / 资讯中心 / 详情

深入理解Python GIL:多线程性能瓶颈与高效并行方案

发布时间:2026/9/29 1:33:45来源:尧图网络
深入理解Python GIL:多线程性能瓶颈与高效并行方案
写这篇文章的念头其实源于我刚入行时的一次“社死”现场我拍了胸脯跟组里说用 Python 多线程把那个 CPU 密集型的计算模块加速三倍结果一跑四核机器 CPU 总占用愣是没超过 100%单线程多少时间多线程还是多少时间。当时我对并发只有半吊子理解第一反应是代码写得不对折腾了一晚上锁和队列最后同事瞟了一眼说“你这是被 GIL 卡住了。”从那之后我花了很长时间去翻 CPython 源码里的 ceval.c去看 threads 相关的文档也踩过不少自以为绕开了 GIL、结果反而更慢的坑。现在再回头看GIL 这个东西其实没有网上传的那么玄乎它就是 CPython 在内存管理和解释器实现之间做的一个历史性妥协。搞懂它为什么存在、它到底卡在哪个环节、以及哪些方案能真正绕开它比单纯记住“别用多线程算 CPU 任务”这个结论要有用得多。这篇文章我打算从 GIL 的来历、底层机制、性能影响到现实中可落地的替代方案和排查方法完整讲一遍希望能帮你省下我当年那些弯路。1. GIL 的诞生背景保护内存的锁为什么一锁就是二十多年1.1 GIL 到底锁的是什么很多人第一次听到“Python 全局解释器锁”会下意识觉得它锁住了整个 Python 进程好像什么并发都做不了。从实际效果上讲确实有点这个味道但从 CPython 的视角看GIL 真正保护的并不是“Python 代码”本身而是解释器内部那些全局共享的内存状态。CPython 做内存管理核心是引用计数。每个 Python 对象头部都有一个 ob_refcnt 字段记录这个对象被引用了多少次归零就立刻回收内存。这个设计简单、高效但也有一个隐患如果有两个线程同时在执行字节码同时对同一个对象的引用计数做加减那这个计数就乱了可能导致对象被提前释放或者永远不释放内存泄漏还只是小事直接崩溃都完全可能。你可能会说那就给每个对象加一把独立的小锁呗理论上可以但代价极其恐怖。Python 里每次变量赋值、函数传参、返回值传递都要修改引用计数这意味着“给对象加锁”这个操作会发生在几乎所有指令里性能会差到没法用。于是 CPython 的作者们选择了一个更简单粗暴的办法整个解释器同一时刻只允许一个线程执行字节码这样引用计数操作天然就是原子的不需要给每个对象维护锁。1.2 一个全局锁省了多少事有了 GIL 之后CPython 不仅仅省去了对象级锁的维护成本很多其他内部数据结构也不需要再额外加锁了。比如内置类型 dict、list 的底层操作解释器内部的异常状态、线程状态对象、内存分配器的部分状态都因为“同一时刻只有一个线程在跑”而变得相对安全。这里要澄清一个常见的误解有 GIL 不代表 Python 的所有操作都是线程安全的。GIL 保证的只是“解释器执行字节码的原子性”但两个线程之间如果共享同一个可变对象A 线程读一个属性B 线程在同一时刻修改同一个属性中间依然可能插入线程切换。最典型的例子就是 list.append 和 list.pop 这种组合操作单看每一步是安全的但两个线程交错执行完整的“判断-操作”逻辑时依然会出问题。所以 GIL 不是线程安全的免死金牌它只是把“内存管理”这一层的并发问题压下去了高层的数据竞争该存在还是存在。1.3 为什么这么多年都没去掉GIL 在 CPython 的历史里几乎是“元老级”的存在。早在 1992 年发布的 1.x 版本里GIL 就已经在解释器内部了。这二十多年间不是没人尝试去掉它最著名的要数 Larry Hastings 在 Python 3.2 时期提出的 GIL 改造方案以及后来的 Gilectomy 项目。这些尝试最后都面临同一个天花板去掉 GIL 之后引用计数就必须有其他机制来保护。你可以在对象层面加细粒度锁也可以改成类似 Java 的垃圾回收机制但无论哪条路都会让单线程程序的性能明显下降。要知道Python 那么多应用场景里绝大多数脚本是单线程跑的如果为了多线程的“可能性”牺牲所有单线程程序的性能这笔账怎么算都不划算。CPython 的决策者一直把这个兼容性和性能包袱背在身上直到 3.13 版本才开始以实验特性提供 free-threaded 构建这件事才算真正破冰。2. 性能账本同样是多线程为什么有的飞快有的原地踏步2.1 I/O 密集任务GIL 其实很“识趣”先说结论凡是涉及到网络请求、文件读写、数据库查询、sleep 等待这类 I/O 密集型的任务Python 多线程是能实打实带来收益的而且收益往往还不小。原因在于GIL 并不是一直死死霸占着不放手当线程执行到阻塞式 I/O 操作时它会主动释放 GIL让其他线程去执行。拿一个最简单的例子来说你用 ThreadPoolExecutor 开 10 个线程同时去请求 10 个不同的 HTTP 接口。每个线程发完请求之后要等网络返回这段时间网络栈是内核在管Python 这边根本不需要 CPU。如果线程不主动放锁其他线程就只能干等着那效率确实会变成串行但实际实现中线程在进入系统调用之前就会释放 GIL等 I/O 完成再重新获取。所以网络等待的时间被完美重叠了10 个请求的耗时理论上约等于最慢那一个请求的耗时。这个特性非常关键。很多人只记住了“Python 多线程是假的”于是遇到所有并发场景都去上多进程结果进程数量一大堆内存涨得厉害。其实对于 Web 爬虫、API 调用、文件批处理这种场景threading 模块就是够用且高效的选择完全没有必要上 multiprocessing。2.2 CPU 密集任务真相就是这么残酷一旦任务变成 CPU 密集型比如复杂计算、大量字符串处理、图像像素遍历、加密哈希计算GIL 就会变成实打实的瓶颈。原因很简单这些任务在计算期间几乎不释放 GIL线程 A 一直在跑线程 B 一直等着操作系统定时器到了CPython 会强制切换 GIL 给线程 B但线程 B 刚切进来下一个切换点又到了又切回去。整个过程看起来像是“多个线程在轮流干活”但物理上只有一个 CPU 核心在真正工作。用一个直观的数字来说假设你有一台 8 核机器用 Python 开 8 个线程去跑纯 CPU 计算最终的总耗时和单线程基本一样CPU 整体占用率在 100% 左右而不是 800%。这个反差是很多 Python 新手崩溃的根源。我在团队里做过一个小测试用多线程并行做大数的质因数分解线程数从 1 加到 32预计耗时曲线几乎是一条水平线偶尔还会因为线程切换开销上升一点点。2.3 别把所有性能差都甩锅给 GIL需要提醒的是GIL 只是“多线程 CPU 密集任务没有加速比”的一个原因但不是唯一原因。即使某天 GIL 彻底消失了多线程并行跑纯 Python 对象操作也可能遇到其他瓶颈比如多个线程同时访问同一个共享对象真锁竞争照样存在。线程创建和销毁本身有开销任务粒度太小的话线程调度成本可能大于并行收益。内存带宽和 CPU 缓存竞争即使解释器层面全部并行物理资源还是有限的。所以分析性能问题的时候别一上来就“肯定是 GIL 的锅”。正确姿势是先用工具确认 CPU 占用率再确认任务类型最后再考虑是不是 GIL 的问题。后面我会专门讲一套排查链路。3. 底层机制拆解GIL 是如何被获取、持有和释放的3.1 从字节码到线程切换CPython 执行 Python 代码时会先把源码编译成字节码然后交给虚拟机一条一条执行。这个虚拟机的中枢函数是 _PyEval_EvalFrameDefault是一个巨大的循环。GIL 的获取和释放就发生在这个循环里的关键节点上。当一个线程想要执行 Python 字节码它必须先拿到 GIL。拿到之后解释器会在一个“开关间隔”switch interval内持续执行字节码默认大约 5 毫秒。这个值可以通过 sys.setswitchinterval 修改。每隔 5 毫秒解释器会检查是否有其他线程在等待 GIL如果有当前线程就释放 GIL切换到等待队列里的下一个线程。你可能会觉得 5 毫秒很长一个普通函数可能只需要几微秒就执行完了。这确实意味着正常情况下线程会连续执行很久而不是每执行一条指令就切换一次。只有当线程进入阻塞 I/O、调用某些会释放 GIL 的 C 扩展或者时间片用尽时才会发生切换。这种设计保证了单线程情况下几乎不会因为 GIL 检查付出额外代价。3.2 GIL 竞争背后线程调度与“轮流执政”GIL 的竞争模型在不同版本里有一些微调。Python 3.2 之后改用了基于“等待线程数”的机制当没有其他线程在等 GIL 时当前线程不会主动让出这就让单线程程序几乎零开销一旦有其他线程等待当前线程就会在切换点让出 GIL。这个机制是当时 GIL 优化里非常关键的一步。还有一种常见的误解是“GIL 会让 Python 进程卡死”。其实不会因为操作系统仍然会调度线程GIL 的等待是让线程进入休眠状态而不是忙等待。每个线程在被强制切换 GIL 之前至少能运行一个切换间隔。所以整个进程不会“死锁”只是并行度被限制成了近似 1。3.3 为什么 C 扩展既能帮忙又能添乱GIL 不只是解释器内部的概念它对 C 扩展的编写者来说也非常重要。Python 的 C API 提供了一对宏Py_BEGIN_ALLOW_THREADS 和 Py_END_ALLOW_THREADS。C 扩展里如果有一段耗时操作用不到 Python 对象就可以在这段代码前后加上这对宏在完美时机释放 GIL让其他 Python 线程趁机运行。有名的科学计算库就是这么干的。numpy 在进行大规模矩阵运算时核心计算用的是 BLAS/LAPACK 这些原生代码计算过程中会主动释放 GIL所以 numpy 的多线程计算是能真正利用多核的。如果你自己写了一个纯 Python 循环处理百万级数据那 GIL 全程在场很难有加速。反过来如果 C 扩展没有正确处理 GIL问题也会很严重要么是持锁时间过长导致其他线程被饿死要么是错误地在没有 GIL 的情况下操作 Python 对象直接崩溃。像 cython 编写的扩展默认情况下是会持有 GIL 的如果你在 cython 里跑了一个重循环不主动释放 GIL效果和纯 Python 几乎一样。3.4 无 GIL 的 Python 是什么状态2023 年底PEP 703 被正式接受CPython 的 free-threaded 构建成为实验特性并在 Python 3.13 里提供了可安装的版本。这个构建删除了 GIL让多个线程真正并行执行 Python 字节码。听起来很美好但代价也明显单线程性能下降约 10% 左右下说明文free-threaded 构建里每个 Python 对象都需要额外的内存来维护线程安全相关的状态整体内存占用也会上升。所以短期之内大多数生产环境还是会用传统的 GIL 版本。free-threaded 更适合那些“多线程 CPU 密集 对内存不敏感”的场景而且很多 C 扩展还没有针对无 GIL 模式做适配兼容性需要谨慎验证。对于普通业务开发者与其等 GIL 移除不如把现有的绕行方案用好这反而是收益最高的路径。4. 绕开 GIL 的实用路线不是只有 multiprocessing 一条路4.1 方案一多进程——最朴素也最有效既然 GIL 只锁解释器进程内部那直接多开几个进程每个进程有自己独立的解释器和独立的 GIL不就能真正并行了吗这正是 multiprocessing 模块的核心思路。你可以用 multiprocessing.Pool 或 concurrent.futures.ProcessPoolExecutor 把任务拆给多个进程执行。每个进程跑在独立的 CPU 核上互不干扰。这是目前做 CPU 密集任务最稳妥的 Python 方案。但多进程也有三个需要提前接受的成本进程启动开销比线程大得多picking 和 fork 都要时间。任务如果本身就非常轻量比如单个任务只需几毫秒那进程切换和通信的成本可能超过并行收益。数据传递要序列化。传给子进程的参数、子进程返回的结果都需要 pickle 序列化。如果数据很大这块耗时不容小觑。内存是独立的共享状态非常麻烦。虽然可以用 Manager 或共享内存但一般来说是重度囚笼。所以我的建议是多进程适合“任务量较大、数据量适中、CPU 密集”的场景不适合频繁调用小函数的场景。下面给一个典型的使用写法from concurrent.futures import ProcessPoolExecutor def heavy_compute(n): # 模拟一个 CPU 密集型任务 total 0 for i in range(n): total i * i return total if __name__ __main__: tasks [10_000_000, 20_000_000, 30_000_000] with ProcessPoolExecutor(max_workers3) as executor: results list(executor.map(heavy_compute, tasks)) print(results)注意 multiprocessing 在 Windows 上要注意 ifname main 保护因为子进程在 Windows 下是通过重新导入模块的方式来创建的没有这个保护会无限递归启动进程。4.2 方案二asyncio——单线程里把并发拉满很多人会忽略 asyncio 和 GIL 的关系。其实 asyncio 根本不依赖多线程它是在单线程内部通过事件循环和协程切换来实现并发。因为始终只有一个线程GIL 反而不构成任何阻碍。所有“等待”都发生在 await 点上协程把控制权主动交还给事件循环让其他协程运行。它的优势很明显不用创建大量线程/进程内存开销极小可以轻松支撑几万个并发连接。没有锁竞争、没有上下文切换的系统调用开销性能往往比多线程 I/O 还要好。代码是同步风格的异步写法可读性不差。但它也有自己的适配范围适合 I/O 密集、尤其是高并发的网络服务场景不适合 CPU 密集计算。如果协程里有一段纯 CPU 的重计算它会阻塞整个事件循环导致所有其他协程卡住。遇到这种混合场景常规做法是把重计算部分丢进线程池或进程池再用 run_in_executor 包一层。4.3 方案三让计算发生在 C 层面这是很多性能优化文章不会细聊但实际效果极好的一条路线。GIL 管的是 Python 字节码的执行而很多 C 扩展在运行时会主动释放 GIL把线程释放出来。典型代表有numpy/pandas大规模数值计算执行时释放 GIL。图像处理、加密、压缩类库大多通过 C 实现内部能并行时尽量并行。numba通过 JIT 编译把 Python 函数转换成机器码部分场景下可以释放 GIL。如果你有性能瓶颈在纯 Python 循环上又不想把整个架构改成多进程那用 numpy 向量化、numba 加速或者写一小段 C 扩展通过 ctypes/cffi/Cython把热点逻辑下沉往往比换并发模型更直接。这里给一个粗浅的思路如果你的逻辑是“对一个大列表里的每个元素做某种数学运算”先别急着上多线程/多进程先看能不能用一行 numpy 表达式完成。能的话GIL 相关的问题就自动消失了因为 numpy 底层不受 GIL 限制。4.4 方案四线程 进程混合架构真实业务里很少是纯 CPU 或者纯 I/O往往两者混合。比如一个 Web 服务既有大量网络请求处理又有少量计算密集任务。这种时候单一方案就不够用了。我常用的架构是主流程用 asyncio 或线程池处理 I/O。计算密集的部分通过 ProcessPoolExecutor 提交给子进程然后把 future 接回主流程。子进程之间不做复杂通信只处理独立计算任务结果通过返回值传递。这个组合可以灵活应对混合负载。但这套架构的复杂度上来了进程间通信的序列化、错误处理、关闭时的资源回收都要考虑。非必要不追求极致并行先保证功能正确再谈性能。4.5 关于 free-threaded Python 的现状前面提到 Python 3.13 的 free-threaded 构建是新时代的变量。如果你使用的是纯 Python 生态、没有依赖太多 C 扩展那可以尝试这个构建体验一下真正的多线程并行。但我个人建议至少在生产环境再等等等主流 C 扩展numpy、pandas、pydantic 等都适配了无 GIL 模式并且你的性能瓶颈确实严重到多进程方案救不了再来评估也不迟。当前阶段多进程和混合架构依然是绕开 GIL 最成熟、最可控的路线。5. 实战排查记录如何确认你的程序真的被 GIL 拖垮了5.1 第一步看 CPU 总占用率GIL 影响的最直接表现就是“多线程没有利用到多核”。所以排查第一步很简单开一个多线程程序跑起来在另一个终端用 top 或 htop 看 CPU 占用率。如果你的程序是 CPU 密集型的并且开了 4 个线程CPU 总占用率在 100% 左右而不是接近 400%那基本就是 GIL 在起作用。这个信号非常直观甚至不需要任何高级工具就能判断。但反过来如果 CPU 总占用率已经跑到 380% 以上那就说明程序大概率已经绕开了 GIL瓶颈可能不在并发而在其他方面比如内存、磁盘、网络带宽。5.2 第二步对比单线程与多线程的耗时光看 CPU 占用率还不够严谨。有可能你的代码虽然 CPU 占用率只有 100%但多线程版本确实比单线程快因为任务里有一部分的 I/O 等待。所以更可靠的验证方法是做一份相同的任务分别用单线程和多线程跑一遍记录耗时。一个可复制的测试模板大概是这样的import time from concurrent.futures import ThreadPoolExecutor def work(n): return sum(i * i for i in range(n)) nums [5_000_000] * 8 # 单线程 start time.perf_counter() results1 [work(n) for n in nums] elapsed_single time.perf_counter() - start # 多线程 start time.perf_counter() with ThreadPoolExecutor(max_workers8) as executor: results2 list(executor.map(work, nums)) elapsed_multi time.perf_counter() - start print(f单线程耗时: {elapsed_single:.3f}s) print(f多线程耗时: {elapsed_multi:.3f}s) print(f多线程/单线程 加速比: {elapsed_single / elapsed_multi:.2f})如果输出显示加速比在 0.9~1.1 之间说明 GIL 让多线程完全没有收益。如果明显大于 1.5说明任务中有隐藏的 I/O 或者 C 扩展释放了 GIL这时候可以深入任务内部找原因。5.3 第三步用 py-spy 看线程到底在干嘛top 和 perf_counter 能确认结果但不能直接告诉你线程卡在哪。这时候 py-spy 是利器。py-spy 是一个采样式 profiler不需要修改代码也不需要重启进程可以直接对运行中的 Python 进程 attach 并输出每个线程当前的调用栈。典型用法pip install py-spy py-spy top --pid python_pid主要看两个信息每个线程的名字、当前执行的函数栈。如果多个线程的栈都停留在同一个 Python 函数上而且这个函数是纯 CPU 计算那就进一步确认了 GIL 限制。如果线程栈显示大量线程都在等待事件那瓶颈可能不是 GIL而是锁竞争或 I/O 等待。5.4 第四步区分 GIL 和真锁竞争这是最容易踩的坑。多线程慢不一定全是 GIL 的锅。如果你在代码里用了 threading.Lock 来保护共享数据而且多线程频繁竞争这把锁那即使没有 GIL性能也可能很差。区分方法也简单把共享数据访问去掉改成每个线程只做独立计算重新测耗时。如果独立计算后依然没有加速那是 GIL 的问题如果独立计算后加速比明显提升那你的瓶颈其实是自己的锁设计不是 GIL。我在实际项目里遇到过类似情况一个任务队列处理程序多个 worker 线程从同一个队列里取任务一开始以为慢是因为 GIL后来用 py-spy 一看所有线程都卡在 queue.get() 的锁等待上。换成无锁设计后速度立刻上来了。所以说GIL 是“原罪”这个观念要放下先做科学的排查。5.5 一个我踩过的教训线程池开太多反而更慢有段时间我处理一个常见的批处理任务无脑把线程池的 max_workers 设成 64结果性能比 8 个线程还差。当时很困惑后来分析发现任务本身是 CPU 密集的线程多了以后每个线程频繁切换 GIL切换带来的上下文开销反而显著增加了总耗时。这个现象在 GIL 存在的情况下非常典型。因为线程越多GIL 的切换频率越高每个线程的有效执行时间占比下降。所以如果你确认了程序是 CPU 密集还在用 ThreadPoolExecutor 硬撑即使线程数远大于 CPU 核心数也不会得到任何收益反而会有反向效果。这时候要么减到 1 个线程等于不用多线程要么换 ProcessPoolExecutor而不是去堆线程数量。6. 个人选型清单我在实际项目中的并发决策参考6.1 一张表帮你快速定位我平时给团队做技术方案时经常用一个简化的判断表。这里分享出来任务类型典型场景推荐方案不推荐网络 I/O 密集爬虫、API 调用、消息消费asyncio / ThreadPoolExecutorProcessPoolExecutor除非单任务特别重文件/数据库 I/O 密集读写大量小文件、批量 SQLThreadPoolExecutor / asyncio单纯用多进程纯 CPU 计算数值计算、图像处理、加解密ProcessPoolExecutor / C 扩展numpy、numbaThreadPoolExecutor混合负载Web 服务 计算接口asyncio 主流程 ProcessPoolExecutor 处理重计算全局都用线程或者都用进程任务极轻量高频几毫秒内完成的函数调用单线程 微优化 / asyncio线程池、进程池调度开销占大头这张表不是我凭空编的是踩过坑之后总结出来的。最典型的反例就是把一个轻量函数丢进 ProcessPoolExecutor 批量调用结果进程启动、pickle 序列化、结果回传的时间远超函数本身执行时间整体效率反而比单线程循环差了一个数量级。6.2 一些常被忽略的细节如果你决定用 ProcessPoolExecutor有几个隐藏坑值得注意。第一个是任务的可序列化性。子进程是独立内存参数和返回值都要通过 pickle 传输如果函数是闭包、lambda 或者绑定了某些无法 pickle 的对象就会直接抛异常。解决办法是尽量把需要传的数据做成普通数据或者用云 pickle 库临时顶一下但长期来看还是得避免。第二个是 fork 和 spawn 的差异。Linux 上 multiprocessing 默认用 fork子进程会继承父进程的内存快照启动快Windows 和 macOS 新版本默认用 spawn会重新导入模块启动慢但更安全。如果你的代码里在 fork 之后还要创建线程容易发生死锁所以多进程和多线程混用时要格外注意启动方式。第三个是资源上限。进程池开几个 worker不是越多越好。每个进程都有独立的 Python 解释器和内存空间开 8 个进程可能吃掉 8 倍的内存。如果任务本身内存占用大反而会因为内存不足触发 swap性能暴跌。6.3 再说一次不是所有并发问题都要用“绕开 GIL”来解决写这篇文章的时候我在想网络上关于 GIL 的讨论太多了但大多数都停留在“GIL 是万恶之源”这个层面。真正到了项目里你首先要回答的问题不是“怎么绕开 GIL”而是“我的性能瓶颈到底是什么”。动手做一个简单的 profiling比脑补 GIL 重要一百倍。你可以先用 cProfile 或 py-spy 看函数级别的耗时分布再用 top 看 CPU 和内存再决定要不要上并发。很多时候你会发现瓶颈根本不在 CPU 而在于一个糟糕的数据库查询、一个没有加索引的表、或者反复读盘的代码。我在实际优化中见过不少团队花了一两周时间把线程改成进程把进程改成协程结果性能提升只有 10%根子上的问题却一直没发现。所以说工具和技术方案重要但定位问题的思路更重要。6.4 如果你还在纠结试一下这些组合拳基于我目前的经验如果遇到一个典型的 Python 性能问题我会按这个顺序做先用 cProfile 和 py-spy 定位热点函数确认瓶颈类别CPU、I/O、锁等待。如果是 I/O优先用 asyncio 把等待时间压掉如果项目太大改造成本高再用 ThreadPoolExecutor。如果是 CPU先看有没有现成的 C 扩展库可以替代纯 Python 计算比如 numpy、pandas、numba、pydantic-core、orjson。如果必须用自定义 Python 逻辑做 CPU 密集计算再上 ProcessPoolExecutor并且注意任务粒度不能太细。如果进程间通信过于复杂考虑用 Redis、消息队列等外部组件做任务分发而不是硬写 multiprocessing。这套组合拳几乎覆盖了我见过的大部分 Python 并发场景。当然它不绝对但至少能帮你在 GIL 这个问题上少走弯路。回到开头那个“社死”的案例我后来用 multiprocessing 替换了多线程其实也就改了几行代码CPU 占用率从 100% 变成了接近 300%耗时降了接近一半。那次经历给我的教训一直留到现在GIL 不是 Python 的缺陷而是 CPython 在设计取舍里做出的选择。理解它承认它的边界然后用对的工具解决对的问题这才是 Python 并发性能优化的正确姿势。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

构建企业级AI知识库:从文档解析到语义检索的完整实践指南 2026/9/29 5:59:13

构建企业级AI知识库:从文档解析到语义检索的完整实践指南

我没有收到具体的项目信息。请按这个格式提供输入内容,我才能基于你的项目标题拆解并生成一篇完整的博文:项目标题: [标题] 项目正文: [对项目的零散描述、技术点或场景说明] 关键词: [关键词1, 关键词2, ...] 摘要描述: [一句话简介]收到后我会直接产出…

阅读更多 →
最大质因子序列:用筛法思想批量维护因子信息的经典例题 2026/9/29 5:59:06

最大质因子序列:用筛法思想批量维护因子信息的经典例题

信息学奥赛一本通的1410题,在OpenJudge上对应的是1.13章节的第21题,题目名叫“最大质因子序列”。这道题在两类题库里都收录了,属于学会筛法之后“顺手就能做”的典型题目。可奇怪的是,很多初学者卡在这里,不是因为不会…

阅读更多 →
如何装好硬件监控:LibreHardwareMonitor 完整上手指南 2026/9/29 5:59:00

如何装好硬件监控:LibreHardwareMonitor 完整上手指南

如何装好硬件监控:LibreHardwareMonitor 完整上手指南 【免费下载链接】LibreHardwareMonitor Libre Hardware Monitor is free software that can monitor the temperature sensors, fan speeds, voltages, load and clock speeds of your computer. 项目地址: h…

阅读更多 →
Apache Beam Go SDK 实战:使用 ParDo2 实现 Additional Outputs 多路输出 2026/9/29 5:59:00

Apache Beam Go SDK 实战:使用 ParDo2 实现 Additional Outputs 多路输出

【免费下载链接】beam Apache Beam is a unified programming model for Batch and Streaming data processing. 项目地址: https://gitcode.com/gh_mirrors/beam18/beam 点击查看 免费下载 导读 本文基于 Apache Beam Go SDK 的 Code Katas 教程中 "Additio…

阅读更多 →
(论文速读)DI-CDM:微调条件扩散模型在结构健康监测中的损伤成像 2026/9/29 5:59:00

(论文速读)DI-CDM:微调条件扩散模型在结构健康监测中的损伤成像

论文题目:Damage imaging in structural health monitoring with fine-tuned conditional diffusion model(微调条件扩散模型在结构健康监测中的损伤成像)期刊:Mechanical Systems and Signal Processing摘要:图像成像…

阅读更多 →
Firstmate Scout 完成与晋升(Promotion)实战指南:调查报告、完成门控与实施交付 2026/9/29 5:59:00

Firstmate Scout 完成与晋升(Promotion)实战指南:调查报告、完成门控与实施交付

【免费下载链接】firstmate Talk to one agent. Ship with a crew. 项目地址: https://gitcode.com/gh_mirrors/fi/firstmate 点击查看 免费下载 导读:本指南围绕 firstmate 仓库中 scout-completion 技能(.agents/skills/scout-completion/…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉