资讯动态

cgminer 3.1.1 Windows:OpenCL老卡验证与调优避坑

发布时间:2026/10/25 22:06:58 来源:尧图企业网站定制
简介cgminer 3.1.1 Windows 版是一套面向比特币及其衍生币挖矿的多线程、多矿池挖矿程序支持 ATI GPU 监控、超频与风扇转速调节并兼容 FPGA、ASIC 设备适合需要在 Windows 环境下搭建或调试矿机的进阶用户。压缩包共 43 个文件约 6.83MB包含 txt 说明文档、dll 运行库、bit/bin 与 ncd FPGA 配置文件、cl OpenCL 内核以及 exe 可执行程序、conf 示例配置和 php/java/class/c 形式的 API 示例覆盖运行、设备适配与接口调用等环节。已有 559 人学习下载。包内提供 cgminer.exe 与 cgminer-nogpu.exe 两种入口并附 README、API 说明和多种 scrypt 内核便于读者快速完成本地部署、对照配置参数、排查设备识别与算力异常也可作为理解矿机软件目录结构和二次开发的参考。1. 四十兆的老包为什么还留在硬盘里先说结论cgminer 3.1.1 windows 这个包是 OpenCL 显卡计算时代少数几个解压就能跑、不用装框架的现成环境。你在 Windows 上想验证一张老卡到底能不能被 OpenCL 正确调用、内核编译要多久、显存被吃满时驱动是什么反应从头搭一套工具链要折腾半天而这个包里 exe、依赖 dll、内核源码、示例配置全齐双击目录里那个 bat 就能看到实时界面。它适合三类人手里还留着老卡想榨干最后一滴算力的人、做 OpenCL 负载与调度实验的人、需要复现十几年前软件行为的人。不适合指望它跑新卡的人——3.x 之后内核调度逻辑变过新卡上去大概率是花屏式报错。下面按解压、配置、监控、排错、验收的顺序讲中间会翻几次车。2. 解压之后先别双击依赖链、内核文件与 --ndevs 自检绝大多数人拿到这个包的第一反应是双击 cgminer.exe然后看到一个黑窗口闪一下就没了于是认为包是坏的。实际上它没坏只是启动链路里某一环没接上而 Windows 控制台程序退出得又太快连报错都来不及看清。这一章先把谁依赖谁讲清楚再用三条命令把问题定位到具体那一层避免后面调参数时把驱动问题误判成配置问题。2.1 exe、dll 与 .cl 内核缺了谁会报什么cgminer 主体是纯 C 写的控制台程序在 Windows 上用 MinGW 交叉编译出来静态部分很少运行时严重依赖同目录下的几个动态库。它的挖矿后端分两类一类走网络协议stratum、getwork一类走设备驱动OpenCL、串口矿机。网络侧依赖 libcurl 和 OpenSSL 的库做 HTTP 与签名线程侧依赖 pthread 的 Windows 移植版。这些库必须和 exe 放在同一层目录系统 PATH 里有没有都不算数因为程序是按相对路径找的。另一块容易漏的是内核文件。cgminer 把真正跑在显卡上的计算逻辑写成 OpenCL C 源码扩展名 .cl 文件放在 exe 同级的一个子目录里程序启动时才调用驱动现场编译。也就是说显卡驱动同时扮演了运行库和编译器两个角色。目录缺失、路径含中文、路径里有空格都可能让编译阶段直接失败而失败信息往往只写一行 Failed to load kernel看不到具体是哪个文件。组成职责缺失或异常时的现象cgminer.exe主循环、设备调度、协议解析无法启动pthread 运行库线程池与锁启动即报找不到入口点窗口一闪而过libcurl / OpenSSL 库矿池 HTTP 通信与签名能进界面但连不上池日志里是连接失败zlib 库部分协议数据压缩偶发解析错误长连接后被断开.cl 内核目录GPU 计算逻辑源码提示内核加载失败或设备列表为空cgminer.conf参数持久化每次启动都要手敲一长串命令行我第一次拆这个包时就栽在路径上。当时图省事解压到了桌面一个带中文的文件夹--ndevs能列出显卡但一加载内核就报错日志里翻半天只有一句内核编译失败。换到D:\cgm311这种纯英文短路径后同样的参数直接跑通。这件事说明一个道理这类老程序的路径处理没有做宽字符适配任何非 ASCII 字符和空格都是雷。2.2 OpenCL 的三层对应驱动、ICD 注册表与 32 位进程要理解为什么驱动装了但 cgminer 说找不到设备得把 Windows 上 OpenCL 的调用链拆成三层。最上面是应用层也就是 cgminer.exe中间是 ICD loader就是系统目录里那个 OpenCL.dll它本身不含任何实现只负责按注册表里的厂商列表去加载真正的实现库最下面是显卡驱动提供的运行时负责把内核源码编译成机器码并调度到计算单元上。关键在于cgminer 3.1.1 的 Windows 版本是 32 位程序。32 位进程只能加载 32 位的实现库读的也是注册表的 32 位视图也就是HKLM\SOFTWARE\Wow6432Node\Khronos\OpenCL\Vendors这个分支。现在很多新驱动默认只装 64 位组件结果是 64 位程序一切正常32 位程序死活看不到设备。这种情况不是 cgminer 的锅是运行时没装全。判断方法很直接用 reg query 看 32 位视图下有没有厂商条目有的话再看--ndevs能不能枚举出设备名和显存。如果注册表条目存在但枚举失败问题在驱动版本与老程序的兼容性如果条目根本不存在先把 32 位 OpenCL 运行时补上再谈其他。这一步不做后面所有参数调优都是空转。提示不要用第三方运行库合集去补 OpenCL 组件那些包里的版本往往和显卡驱动不匹配装上之后 ICD 加载到错误实现报错反而更隐蔽。老老实实装对应显卡的官方运行时。2.3 三条命令跑通首次自检下面这段是每次拿到新机器我都会走一遍的流程从建目录到枚举设备三步之内就能判断这个包在当前环境能不能跑。命令用 PowerShell 写因为要读注册表和批量解压比 cmd 省事。# 1) 落到纯英文短路径避免中文与空格导致内核加载失败 New-Item -ItemType Directory -Force -Path D:\cgm311 | Out-Null Expand-Archive -Path .\cgminer-3.1.1-windows.zip -DestinationPath D:\cgm311 -Force # 2) 查 32 位 OpenCL ICD 是否注册cgminer 是 32 位进程必须看 Wow6432Node reg query HKLM\SOFTWARE\Wow6432Node\Khronos\OpenCL\Vendors # 3) 枚举设备这一步不依赖任何矿池纯本地自检 Set-Location D:\cgm311 .\cgminer.exe --ndevs第一段只是把包解到一个干净路径-Force保证重复执行不会因为文件已存在而中断。第二段的输出正常情况下会列出若干条厂商实现的路径每条对应一个OpenCL实现库如果返回系统找不到指定的注册表项说明 32 位运行时确实没装先解决这个。第三段是核心--ndevs会打印设备编号、设备名称等基本信息不连接网络、不提交任何任务是最安全的验证方式。如果--ndevs输出了设备说明 exe、dll、OpenCL 三层都通了接下来才轮到挖矿参数。如果它输出了List of devices:但下面是空的通常是驱动把这张卡标记成了不支持计算或者卡正被别的进程独占。如果直接报平台初始化失败回到第二段去查注册表。这三步的顺序不要颠倒先证链路再证设备最后才证业务。设备确认之后可以用一条最小命令做端到端连通性验证。注意这里的矿池地址是占位符换成你自己的即可参数含义逐个说明echo off cd /d %~dp0 cgminer.exe -o stratumtcp://pool.example.com:3333 ^ -u worker1 -p x ^ -I 13 -g 2 -w 256 --thread-concurrency 8192 ^ --scrypt -T -L cgm.log-o指定矿池地址stratumtcp://前缀告诉程序走 stratum 协议-u和-p是工作名与口令很多池的口令可以随便填-I 13是强度scrypt 算法下常用的起点值-g 2表示每张卡起两个线程-w 256是内核的局部工作组大小--thread-concurrency控制单卡拉起的线程总数直接吃显存--scrypt切换算法分支不加这个参数会按 SHA-256 走算力数字会完全不同-T强制文本界面避免在无桌面会话里卡住-L把日志落到文件后面排错全靠它。第一次跑建议把强度压到 8 左右只观察三十秒看到界面上有算力输出、设备温度在动再往上加。上来就拉满强度很容易在驱动层触发超时重置屏幕上出现一闪而过的花屏然后设备号消失那种情况下你根本分不清是配置问题还是硬件问题。3. 把参数写进 cgminer.conf强度、worksize 与 thread-concurrency 的换算命令行跑通之后下一步是把参数固化下来。理由很实际这套参数动辄十几个还带显卡电压、风扇曲线这种容易被手误改错的项每次开机手敲一遍迟早出事。cgminer 支持用一个 JSON 文件承载全部配置启动时-c指过去就行配置文件里的键名和命令行参数一一对应但写法上有几个必须注意的细节写错了程序会静默忽略而不是报错。3.1 配置文件骨架pools 数组与全局段配置文件是标准 JSON顶层两个部分pools数组放矿池其余键是全局参数。矿池数组里每个对象至少要有url、user、pass三个字段第二个及以后的池子默认作为故障转移候选。全局段里所有数值型参数在配置文件里都要写成字符串这是 cgminer 的解析习惯写成数字反而可能读不到布尔型参数才写 true/false。{ pools: [ { url: stratumtcp://pool.example.com:3333, user: worker1, pass: x }, { url: stratumtcp://backup.example.com:3333, user: worker1, pass: x } ], failover-only: true, intensity: 13, worksize: 256, thread-concurrency: 8192, gpu-threads: 2, scrypt: true, queue: 1, scan-time: 1, expiry: 30, no-submit-stale: true, api-listen: true, api-port: 4028, temp-target: 72, temp-overheat: 82, temp-cutoff: 88, auto-fan: true }failover-only设为 true 表示只有主池彻底不可用时才切备用池避免两个池来回横跳导致算力统计被劈成两半。queue在 scrypt 下建议设 1队列越深延迟越大反而拉高过期份额比例。scan-time和expiry控制任务的有效期判断scan-time 1让程序更频繁地检查新任务。no-submit-stale是省钱的关键开关过期份额直接丢弃不提交减少无效请求。api-listen打开本地 JSON 接口下一章专门讲。temp-target、temp-overheat、temp-cutoff三个温度阈值必须按顺序递增写反了程序的行为会很怪temp-target是自动风扇的目标温度temp-overheat触发降频temp-cutoff直接退出保护硬件。这三个值不要照抄风道差的机器把 cutoff 设到 88 度等于没有保护。注意改完配置先别急着跑长任务用cgminer.exe -c cgminer.conf -T启动看第一屏打印出来的参数是不是你写的那些。cgminer 遇到不认识的键会直接跳过一个拼写错误能让整段配置白写。3.2 强度、worksize、thread-concurrency 的三角关系这三个参数是最容易被抄错的因为它们之间存在资源约束不是一个一个独立调的。thread-concurrency是单卡同时展开的线程总数每个线程在 scrypt 算法下要占一块显存做中间状态所以它和显存容量是硬绑定关系worksize是这些线程被切成多大的工作组交给显卡调度必须是 2 的幂多数卡在 256 附近表现最好intensity决定每个线程内部循环的展开程度强度越高单次内核执行时间越长显卡被占用的时间片也越长。调参的纪律是一次只动一个动完看三个数算力、拒绝率、温度。三个数里任何一个变差就退回去。我见过太多人一次性把强度、线程数、工作大小全改一遍跑出来算力涨了百分之五就以为找到了最优解实际上拒绝率也涨了一截净收益是负的只是界面上那个大数字好看。参数常见起点调大的收益调过头的症状thread-concurrency8192算力上升显存占用线性增长分配失败、Error -4、设备从列表里消失worksize256工作组调度更充分算力不升反降日志里出现内核执行错误intensity13单次内核执行更饱满桌面卡顿、拒绝率上升、驱动超时重置gpu-threads2提高设备利用率显存被吃穿两个线程互相抢资源显存这块给一个粗略的换算经验scrypt 下每 1024 个并发线程大约要预留 128 MB 级别的显存做中间缓冲区所以 2 GB 的卡把 thread-concurrency 顶到 16384 已经很紧张还要留出系统与桌面合成的余量。稳妥的做法是从 8192 起步每次加 2048加到算力不再明显增长或者出现分配错误为止然后退回上一档。这个搜边界的过程比抄别人的参数表可靠得多因为同一型号的卡显存颗粒批次不同能顶到的上限也不一样。worksize的调整空间其实很小128 和 256 两个值就能覆盖绝大多数情况。它本质上是告诉驱动这批线程按多大的小组去抢计算单元小组太小调度开销大太大则尾部的空闲线程多。判断方法很简单固定其他参数只改 worksize看十秒平均算力的抖动幅度选抖动最小的那个。抖动比均值更能说明问题均值高但抖得厉害说明内核执行时间不均匀长跑下去容易出现超时。3.3 批处理启动与日志落盘配置固化之后还需要一层进程守护。这类长时间跑 GPU 的程序遇到驱动重置、显存碎片、网络闪断都可能自己退出无人值守的机器上退出就等于白跑一整晚。批处理里套一个循环退出后等十几秒再拉起是最省事的做法比装一堆监控服务轻量得多。echo off setlocal enabledelayedexpansion cd /d %~dp0 set LOGDIR%~dp0logs if not exist %LOGDIR% mkdir %LOGDIR% :loop rem 用当前时间拼日志名避免多次重启互相覆盖 set TS%date:~0,4%%date:~5,2%%date:~8,2%_%time:~0,2%%time:~3,2% set TS!TS: 0! cgminer.exe -c cgminer.conf -T -L %LOGDIR%\cgm_!TS!.log rem 退出后等 15 秒再拉起给驱动释放显存的时间 timeout /t 15 /nobreak nul goto loopcd /d %~dp0把工作目录切到脚本所在位置这一步不能省因为 cgminer 找内核目录是按当前工作目录算的用计划任务开机自启时默认目录是系统目录内核会找不到。enabledelayedexpansion配合!TS!是为了在循环体内取到实时更新的变量值用%TS%会一直取到第一次展开的结果日志名全一样。日志按时间戳分文件的好处是排错时能精确对上几点几分掉了一次卡。单个日志文件不宜太大跑一天下来几十兆很常见定期清理或者按天归档别让磁盘被日志吃满磁盘满导致的退出最难查因为日志本身也写不进去了。timeout那 15 秒不是随便定的。驱动重置后显存释放有延迟立刻重启常常会拿到一个设备存在但分配失败的状态多等十几秒能显著提高重启成功率。如果你的机器掉卡频繁把这个值加到 30 秒顺便去查第 5 章里关于驱动超时的部分。4. 拿下 4028 端口API 命令集、轮询脚本与温度联动界面上看到的数字是给人看的要做事得让程序把数据吐出来。cgminer 内置一个 JSON 接口默认监听本地 4028 端口一条 TCP 连接发一个 JSON 命令服务端回一个 JSON 结果。这个接口的价值在于它把算力、温度、风扇转速、每个池的接受与拒绝计数全部结构化输出你可以直接接到自己的采集脚本里不用再对着屏幕截图识别数字。4.1 API 命令集与返回结构接口是纯文本协议请求体就是{command:xxx}返回是一段 JSON 后跟一个空字符结尾。常用命令不多记住下面这几个就够日常用命令作用关键返回字段summary整体运行状态MHS av、Accepted、Rejected、Elapseddevs每张卡的明细Temperature、Fan Speed、MHS av、Device Elapsedpools各矿池连接状态Stratum Active、User、Diff、Stratum Difficultygpu显卡引擎与显存频率GPU Clock、Memory Clock、Vddcswitchpool切换主池参数带池编号返回切换结果restart重启挖矿进程返回状态quit退出程序返回状态summary里的MHS av是全程平均算力单位是兆哈希每秒看瞬时值意义不大因为 scrypt 算法的算力天然是锯齿状的采样间隔越短抖得越厉害。devs里的温度是驱动读回来的传感器值和第三方监控软件偶尔会差一两度属于正常现象。pools里的Stratum Difficulty很关键池子调整难度时这个值会变难度变了之后本地的拒绝率统计才有可比性。接口默认只允许本地访问远程访问要额外开--api-network并配合白名单这个开关别乱开一个没有认证的裸接口暴露在网络上后果自己掂量。4.2 一个能直接用的轮询脚本下面这段 Python 干三件事连上去取一次汇总、取一次设备明细、把关键指标打到一行里。写法上注意两点一是连接建立后服务端只处理一条命令就关闭所以每次查询都要新建连接二是返回数据尾部有空字符解析前要剥掉否则 json 解析会直接抛异常。import json import socket import time def ask(cmd, host127.0.0.1, port4028, timeout3.0): 发一条 API 命令返回解析后的 dict失败返回空 dict。 try: with socket.create_connection((host, port), timeouttimeout) as s: s.sendall((json.dumps({command: cmd}) \n).encode(utf-8)) raw b while True: chunk s.recv(4096) if not chunk: # 服务端发完就关连接 break raw chunk # cgminer 的返回以 \x00 结尾必须先剥掉再解析 text raw.decode(utf-8, ignore).strip(\x00 \r\n) return json.loads(text) if text else {} except (OSError, json.JSONDecodeError) as e: print(f[api] {cmd} 失败: {e}) return {} def snapshot(): s ask(summary).get(SUMMARY, [{}])[0] d ask(devs).get(DEVS, []) temps /.join(str(x.get(Temperature, ?)) for x in d) fans /.join(str(x.get(Fan Speed, ?)) for x in d) print( fMHS{s.get(MHS av, 0):.2f} f接受{s.get(Accepted, 0)} 拒绝{s.get(Rejected, 0)} f温度{temps} 风扇{fans} ) if __name__ __main__: while True: snapshot() time.sleep(10)ask里用with管理连接保证异常时也能关掉不会在长时间轮询里堆积半开连接。recv循环读到空字节为止是因为接口不支持长连接单次请求的数据量很小一般一次就收完但网络抖动时可能分包循环读更稳。strip(\x00 \r\n)这一句是血泪经验最初没剥空字符json.loads一直报Expecting value排查了半小时才反应过来是结尾那个不可见字符。snapshot只取每张卡的第一条汇总数据如果机器上有多张卡DEVS数组会逐条返回温度和风扇拼成斜杠分隔的字符串方便一眼扫。实际接入监控系统时建议把这段改成返回结构化 dict再由上层决定告警阈值别把判断逻辑写死在采集端。4.3 温度、风扇与自动降频的联动边界cgminer 自己带了一套温度保护超过temp-overheat就降频超过temp-cutoff就直接退出。这套机制在多数场景下够用但有两个边界必须知道。第一自动风扇依赖驱动上报的风扇控制接口部分型号的卡在 Windows 下这个接口是残的auto-fan打开后风扇转速纹丝不动这时候要么用--gpu-fan写死一个固定百分比要么交给显卡厂商自己的控制面板。第二降频动作有延迟温度是几秒采样一次积热快的卡在两次采样之间就可能冲到危险值所以temp-cutoff要比你心理预期低三到五度。--auto-gpu打开后程序会在超温时自动下调引擎频率代价是算力掉一截需要手动或重启才能恢复。我的建议是把自动降频当作最后一道保险日常靠固定频率加良好风道控制温度让保护机制永远不触发。真正需要精细化温控的机器用 4.2 那个脚本读到温度后由外部逻辑调用 API 做切换和启停比依赖程序内部逻辑可控得多。还有一个容易忽略的点多卡机器上devs返回的温度顺序和物理卡槽顺序不一定一致。第一次部署时用--ndevs输出的设备编号和 PCI 位置对一遍把映射关系记下来否则你会盯着卡 1 温度 90 度去拆机箱结果发现过热的是藏在后面的卡 3。5. 避坑Windows 上跑 3.1.1 最容易翻的五个车这一章全是踩过的坑按看到什么现象、为什么、怎么解决三句话写清楚。每一条我都至少遇到过一次有的是环境问题有的是这个版本本身的限制分清楚能省很多时间。5.1 双击就闪退命令行能看到窗口但瞬间关闭现象资源管理器里双击 cgminer.exe黑窗口一闪而过什么信息都留不下。原因控制台程序退出太快报错信息来不及看更常见的是同目录缺运行库进程加载阶段就失败了任务管理器里连进程名都抓不到。解决永远不要双击用 cmd 或 PowerShell 进到目录里执行.\cgminer.exe --ndevs让输出留在窗口里。如果这时报找不到 xxx.dll把缺失的库补到同目录注意必须和 exe 位宽一致32 位程序塞 64 位库会报入口点错误。补库之后还闪退的用-T强制文本模式再跑一次排除界面渲染问题。5.2 --ndevs 只列出 CPU 或者干脆列表为空现象显卡驱动明明装好了设备列表里只有一个处理器设备或者显示List of devices:之后什么都没有。原因32 位 OpenCL 运行时没装全或者注册表 32 位视图下的厂商条目缺失。新驱动默认只装 64 位组件32 位程序读不到实现库自然枚举不出设备。解决先reg query HKLM\SOFTWARE\Wow6432Node\Khronos\OpenCL\Vendors确认条目存在再补装对应显卡的 32 位运行时。装完重启重新跑--ndevs。如果条目在、设备还是空去设备管理器看显卡是否被标记为异常以及有没有别的程序独占显卡。5.3 启动后算力恒为 0日志里出现 Error -4 或 Error -5现象程序正常启动设备也识别了但算力一直是 0日志里反复刷错误码。原因这两个错误码对应显存分配失败和资源不足说白了就是--thread-concurrency开得太大显存被吃穿。另外就是路径含中文或空格导致内核编译产物写不进去。解决先把 thread-concurrency 砍半从 8192 降到 4096 试能正常出算力了再一档档加回去。同时确认目录路径是纯英文、无空格、不在受保护目录下。如果减半后仍然报错把强度也降下来排除两个参数叠加超限的可能。5.4 跑几分钟算力突然归零设备从列表里消失现象稳定跑了五到十分钟算力曲线突然断崖式归零界面上设备数量少了一个过一会儿自动恢复循环往复。原因Windows 的显示驱动超时检测机制在起作用。GPU 连续满载单次内核执行时间超过了系统默认的两秒阈值系统认为驱动卡死强制重置重置期间设备不可用。解决两条路一是降低强度缩短单次内核执行时间从 13 降到 11 或 10二是调高系统的超时阈值。注册表HKLM\SYSTEM\CurrentControlSet\Control\GraphicsDrivers下新建 DWORD 值TdrDelay十进制设成 8 到 10重启生效。第二种方式会让真正卡死的驱动也拖更久才恢复机器上有其他图形任务时慎用。改注册表之前先导出备份这条没有后悔药。5.5 文件被杀软直接删掉或隔离现象解压完没过多久exe 或某个 dll 不见了或者双击报文件已损坏。原因这个包的年代久远打包方式与某些启发式规则高度重合被误判是常事。老版本没有数字签名申诉也没用。解决把整个目录加到杀软的排除列表然后在解压后先核对文件完整性记下每个文件的哈希之后每次异常先对哈希确认是不是文件被动过。别从二手渠道重新下载补文件来源不明的二进制比误报危险得多。6. 验证算力不是虚的三点对账法与长跑采样跑起来不等于跑对了。界面上那个算力数字是本地统计出来的包含所有提交尝试甚至包括最终被池子拒绝的那部分。要让这个数字可信得做三件事本地算力与池端算力对账、接受率与拒绝原因分类、连续采样看波动。这一章给一套可以照着做的验收流程顺便说说我怎么判断一台机器到底能不能长期跑。6.1 三点对账本地、池端、时间对账需要三个数据源cgminer 的summary接口、矿池后台显示的算力、以及程序已运行的时长。三个数放一起看能立刻暴露大部分问题。本地MHS av是全程平均池端显示的通常是滑动窗口平均两者天然会有几分钟的相位差所以对账要挑运行满一小时之后的时间点。正常情况下两者差距在百分之五以内算正常超过百分之十就要查。如果本地明显高于池端说明大量提交没被接受去看拒绝原因如果本地明显低于池端多半是池端的窗口算法把早期低算力时段平滑掉了等半小时再看。拒绝原因是关键信息。日志里Rejected后面通常跟一句原因最常见的是过期份额和难度不匹配。过期份额多说明网络延迟高或者scan-time设得太大把scan-time调到 1、expiry调到 30能明显改善。难度不匹配说明本地提交的份额低于池子当前难度通常是强度太低导致单次计算量不够往上加一两档强度再看。6.2 长跑采样脚本与判读标准单点数据没有说服力要做的是连续采样然后看分布。下面这段在 4.2 的基础上加了统计跑十分钟输出均值、标准差和最大最小温度标准差除以均值就是波动率这个指标比均值更能说明机器跑得稳不稳。import statistics import time from collections import defaultdict from api_poll import ask # 复用 4.2 里的 ask() def sample(minutes10, interval10): mhs, temps [], defaultdict(list) t_end time.time() minutes * 60 while time.time() t_end: s ask(summary).get(SUMMARY, [{}])[0] mhs.append(float(s.get(MHS av, 0))) for i, d in enumerate(ask(devs).get(DEVS, [])): temps[i].append(float(d.get(Temperature, 0))) time.sleep(interval) avg statistics.mean(mhs) sd statistics.pstdev(mhs) print(f算力均值 {avg:.2f} MHS标准差 {sd:.2f}波动率 {sd/avg*100:.1f}%) for idx, t in temps.items(): print(f卡{idx} 温度 最低{min(t):.0f} 最高{max(t):.0f} 均值{statistics.mean(t):.0f}) return avg, sd if __name__ __main__: sample()interval设 10 秒是折中太短会被算法的锯齿干扰太长又抓不到瞬时过热。波动率这个指标我一般按三档判读百分之五以内算跑得很整齐五到十之间属于正常抖动超过十就要查了常见原因是worksize和卡的架构不匹配或者有别的进程在抢显卡。温度那一行看的是最高值而不是均值最高值逼近temp-overheat就说明散热余量不够长时间跑必然触发降频。6.3 一套固定的验收流程基于上面这些我现在验收一台机器固定走五步第一步--ndevs确认设备枚举正常第二步用低强度跑五分钟看日志里有没有内核编译错误第三步把强度加到目标值跑十分钟用 6.2 的脚本采一轮看波动率第四步跑满一小时做一次三点对账确认拒绝率在可接受范围第五步拔掉网络三十秒再插回看程序能不能自己重连、算力能不能恢复。最后这一步最容易被跳过但它是唯一能验证故障恢复能力的测试无值守机器上这一项不过关前面四项全白做。有个习惯我保持了很久每次改完参数都把配置文件复制一份带日期后缀存起来同时在日志目录里留一条备注说明改了什么、为什么改。这套参数调优本质上是个试错过程两周后你只会记得当时调过 thread-concurrency绝不会记得是从 8192 调到 12288 还是反过来。留档这件事看起来笨但在我第三次因为参数回滚不到位而重跑一整晚之后就再也没省过。希望这些能帮你少走点弯路尤其是路径和运行时那两关卡在那里的人最多。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑