跳转至内容
  • 版块
  • 最新
  • 标签
  • 热门
  • 用户
  • 群组
皮肤
  • 浅色
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • 深色
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • 默认(LCZ-Blue)
  • 不使用皮肤
  • LCZ-Green
  • LCZ-Blue
  • LCZ-Black
折叠
品牌标识

抡锤者

首页 版块 标签
硬件
装备秀
AI 广场 App
J

juntucoo

@juntucoo
体面乡绅
取消关注 关注
关于
帖子
12
主题
4
分享
0
群组
1
粉丝
0
关注
0

帖子

最新 最佳 有争议的

  • 给 DGX Spark 写了个零依赖实时监控面板:1 个 Python 文件 + 1 个 HTML 文件
    J juntucoo
    AI Agent dgxspark 本地模型

    @williamlouis 目前设备是DGX SPARK 不知道如何加这个副屏,而且还得学习一下副屏的调试。


  • 蓝宝石 RX 7900 XTX 24G BLOWER 刷完固件后弹「系统设置更改」、BIOS 乱码,重装 Win11 后消失
    J juntucoo
    AI硬件 7900xtx bios amd

    蓝宝石 RX 7900 XTX 24G BLOWER 刷完固件后弹「系统设置更改」、BIOS 乱码,重装 Win11 后消失

    起因:新入手一块蓝宝石(Sapphire)RX 7900 XTX 24G BLOWER 涡轮版,到货后在现有 Win10 上装驱动、
    跑 3DMark 压力测试通过率 98.4%,一切正常。
    后来手贱去官网下了固件更新程序刷了一次固件——从此系统开始弹「系统设置更改」,
    BIOS 里主显示输出被自动改成独显,BIOS 界面还有部分文字乱码。
    重装 Win11 后提示确实没了,但固件那一版回不去了,现在想找同型号的旧固件备份都找不到。
    在线等大佬支招。

    [系统设置更改提示]
    01-system-changed-prompt.jpg


    目录

    • 事情经过
    • 刷完固件后出了什么问题
    • 已经试过的排查
    • 现在的状态
    • 求助
    • 硬件与环境
    • 几个可能的技术解释
    • 踩坑清单(实战)

    事情经过

    楼主最近入手一块蓝宝石 RX 7900 XTX 24G BLOWER 涡轮版。到货后没有直接上生产力,先在现有的
    Windows 10 专业版 22H2 系统里装好官方驱动,用 3DMark 跑了压力测试,通过率 98.4%,
    当时显卡表现一切正常,没看出任何毛病。

    之后我想到蓝宝石官网有官方的固件更新程序,就下载下来给显卡更新固件。更新过程本身还挺顺利,
    前后一共进安全模式刷了两次固件,两次都没报错、没花屏、没黑屏。

    问题出在刷完之后。

    刷完固件后出了什么问题

    一共三个现象:

    1. 系统弹「系统设置更改」

      您的硬件设置已更改。请重新启动计算机,使这些更改生效。

      进系统就弹,重启之后继续弹。

    2. BIOS 里的主显示输出被自动改了

      我原本设的是主板板载核显作为主显示输出。刷完固件进 BIOS 一看,这一项已经变成
      7900 XTX 直连输出了——不是我改的,是刷完固件自己变的。

    3. BIOS 设置界面部分文字乱码

      这个当时没拍照,是我的失误。后来把显示输出切回板载核显,乱码就消失了,
      所以现在也没法复现,只能靠描述。

    [固件更新器:当前固件与是否需要更新]
    02-firmware-updater.jpg

    已经试过的排查

    # 手段 结果
    1 多次重启电脑 ❌ 「系统设置更改」照弹
    2 卸载并重装 AMD 官方驱动 ❌ 无效
    3 BIOS 里手动把主显示改回板载核显 ⚠️ BIOS 乱码消失了,但「系统设置更改」依旧在
    4 联系厂家客服 💬 答复两条路:要么返厂,要么自己备份旧固件重刷回去

    现在的状态

    从刷完固件到决定重装系统,中间隔了大约一天时间。后来我换了一块 NVMe 固态,
    全新安装 Windows 11,装好官方驱动之后,那个烦人的「系统设置更改」提示没有再出现过。

    在 Win11 下又跑了 2 轮 3DMark 压力测试,都能正常通过,通过率 97.9%
    (比刷固件前的 98.4% 略低,属正常波动区间)。

    现在打开 AMD Radeon 固件更新器,检测到的当前固件版本是 113-X4257W-NB6,
    「需要更新」一栏显示 No——也就是官网上的最新版本。

    [硬件详细信息:固件版本与设备 ID]
    03-hardware-details.jpg

    [软件和驱动程序详细信息]
    04-driver-details.jpg

    [整机信息:GPU / 显存 / CPU / 内存]
    05-system-info.jpg

    求助

    主要诉求:想请坛里正好在用蓝宝石 RX 7900 XTX 24G BLOWER 这块卡、并且还没更新过固件
    (或还停留在更新前旧版本)的朋友,帮忙备份一份旧版固件(.rom 文件)给我,我打算按厂家的第二条路
    尝试回刷。版本越接近出厂原版越好。

    顺便请教几个问题:

    1. 「系统设置更改」这个提示到底是什么触发的?有没有办法在不重装系统的前提下彻底关掉它?
    2. BIOS 界面文字乱码,到底是不是显卡新固件(带 GOP 字体)引起的?有没有类似案例?
    3. 显卡固件这种更新到底有没有必要?如果版本差别不大,值不值得冒险?
    4. 各位平时都是怎么备份显卡固件的?有没有推荐的工具或方法?

    硬件与环境

    项目 参数
    显卡 SAPPHIRE AMD Radeon RX 7900 XTX GAMING BLOWSER 24GB
    型号标识 SKU 11322-05 / PN 588-1E487-0005A
    显卡固件(当前) 部件号 113-X4257W-NB6,版本 022.001.002.045,日期 2026/09/10 04:39
    显存 24560 MB (24GB) GDDR6,20.00 Gbps / 960 GB/s
    核心频率 / 总线 2070 MHz / PCI Express 4.0 x16
    设备 ID 744C,修订 C8,厂商 1002 (AMD),子系统 E487,子系统厂商 1DA2 (蓝宝石)
    CPU 13th Gen Intel Core i7-13700,16 核 24 线程,2.11 GHz
    内存 32 GB
    操作系统 Win10 Pro 22H2(刷固件前)→ Win11(重装后)
    驱动 AMD Software Adrenalin 26.20.15.12-261023a1-205499C
    驱动版本 AMD Windows 驱动 32.0.32015.12012 / 2D 驱动 8.1.1.1634
    图形 API DirectX 12.1 / Vulkan 1.4.359 / OpenCL 2.0 / OpenGL 不可用
    FSR 2.4.0.4541
    压力测试 3DMark:刷固件前 98.4% → 重装 Win11 后 97.9%

    几个可能的技术解释

    以下纯属楼主个人猜测,欢迎大佬指正:

    1. 「系统设置更改」更像是 Windows 在请求重启,而不是故障本身。
      显卡固件 / 驱动更新后触发这个提示很常见,所以重装系统后消失是说得通的。

    2. BIOS 乱码大概率不是主板的锅。
      BIOS 界面在主显示走独显时,用的是显卡 ROM 里自带的 GOP 字体渲染的——
      新固件带的 GOP 一变,部分字形就可能串码。这也能解释「切回核显输出后乱码立刻消失」。

    3. 显卡本身应该是好的。
      Win11 下 3DMark 两轮都能过,说明固件更新没有把核心算力刷坏,
      目前的矛盾主要集中在「固件版本 + 旧系统状态」的兼容性上。

    踩坑清单(实战)

    这几条都是真踩过的,写出来省得别人也踩一遍。

    1. 刷固件前没有备份原版 .rom,代价就是只能返厂。
    厂家客服的原话是「要么返厂,要么自己有备份固件就重刷旧固件」。
    所有教程都会说「先备份」,但没人强调不备份的代价是整卡变砖风险自担。

    2. 关键证据没拍照,永久丢失。
    BIOS 乱码当时没拍,等改回核显输出后乱码消失了,再也复现不了。
    排障现场的第一动作应该是拍照,而不是先动手改设置。

    3. 在主力系统上直接刷固件,排障时说不清是谁的锅。
    刷完固件后的驱动状态和旧 Win10 系统里残留的驱动状态纠缠在一起,
    「系统设置更改」到底是固件引起还是驱动安装残留,根本分不开。
    固件刷写最好放在干净的系统环境里做。

    4. 3DMark 通过率 98.4% 不等于显卡没问题。
    通过率只是压力测试下的稳定性参考,98.4% 和 97.9% 都在「勉强可接受」区间,
    不能拿来当「硬件健康证明」,也别拿它当刷固件前后的对比结论。

    5. 重装系统让故障「消失」,不代表故障被修好了。
    重装 Win11 后提示不再出现,很容易误判成「已解决」,其实只是 Windows 侧的状态被清掉了,
    固件那一版还老老实实待在卡上。

    6. 官网更新器显示「需要更新:No」≠ 你手上就是出厂版。
    No 的含义是「你当前版本已经是官网发布的最新版」,
    刷之前那一版(更早的出厂固件)已经找不回来了——除非有人提前备份过。

    7. BIOS 设置项被固件静默改掉,是刷完固件后最容易漏掉的一类问题。
    「主显示输出」变成独显这一条,是靠第一次进 BIOS 才注意到的。
    刷完固件应该逐项核对一遍 BIOS 关键设置,别默认它还是原来那样。


  • 给 DGX Spark 写了个零依赖实时监控面板:1 个 Python 文件 + 1 个 HTML 文件
    J juntucoo
    AI Agent dgxspark 本地模型

    给 DGX Spark 写了个零依赖实时监控面板:1 个 Python 文件 + 1 个 HTML 文件

    起因:在 DGX Spark 上跑大模型时,想随时看清 CPU / GPU / 统一内存 / 磁盘 / 网络 / 推理吞吐的真实状态,
    以及推理引擎(推理服务)到底跑得怎么样。官方 Dashboard 看不了推理细节,nvtop/btop 又看不到
    LLM 侧的指标,索性自己写了一个。

    约束:零第三方依赖——后端只用 Python 标准库,前端单文件 HTML + 原生 JS,不引任何 CDN。
    拷过去 python3 monitor.py 就能跑。

    [整体效果]
    01-overview.png


    目录

    • 它有什么
    • 架构
    • 值得抄的 6 个实现细节
    • 部署
    • 踩坑清单
    • 文件清单
    • 已知限制

    它有什么

    17 个面板,全部可拖动、可缩放、可换位置,布局存在浏览器本地,导出一段 JSON 就能在别的机器上复现。

    顶部 9 张 KPI 卡带迷你走势线;中间 6 张曲线图支持鼠标悬停出十字线和数值气泡,Y 轴单位会在
    B/s → KB/s → MB/s 之间自动切换。

    [LLM 运维区]
    02-llm-ops.png

    上排是 推理引擎(running/waiting、解码速度、TTFT、TPOT、KV Cache 分池占用、MTP 接受率)、
    容器 llm(CPU / 内存 / net / block IO)、一键测速(发一次真实对话,按 usage 计数算吞吐)。

    下排是硬件明细:CPU 每核负载(20 核 GB10)、温度传感器 / 风扇(带过热状态染色)、
    磁盘 I/O、网络接口(含错误/丢包计数)。

    [硬件表格区]
    03-tables.png

    再往下是 进程 Top、引擎指标明细表、当前生效配置(直接读容器里的环境变量,一眼看到
    TF_SOLO_ROWS / TF_SPILL_GIB 这些实际生效的参数)、容器日志尾部。

    [进程 / 引擎指标 / 生效配置]
    04-detail.png

    交互细节

    鼠标悬停在曲线上,十字线定位到具体时刻,气泡给出该时刻的各序列数值:

    [悬停交互]
    05-hover.png

    拖卡片标题栏换位置,拖右下角的小三角改大小。布局可以导出成 JSON:

    [布局导出]
    06-layout.png

    复制这段 JSON,粘到另一台机器上点「应用」,就是一模一样的排布。


    架构

    monitor.py    ~34 KB   Python 3 标准库,无第三方依赖
      ├─ 采样线程   1 Hz 写环形缓冲(deque(maxlen=...))
      ├─ HTTP 服务  ThreadingHTTPServer
      └─ API
          /api/snapshot   当前快照(含 host/cpu/memory/gpu/sensors/disk/network/processes/engine)
          /api/series     历史序列,?window=60|300|900|1800|3600
          /api/stats      snapshot + 容器 stats + uptime
          /api/config     容器镜像/状态/环境变量(docker inspect)
          /api/logs       容器日志尾部 ?tail=200
          /api/probe      发一次真实对话,测 TTFT / decode 速度
          /api/key        设置 API Key
          /api/healthz
    
    index.html    ~49 KB   单文件:HTML + CSS + JS,无 CDN
    

    为什么服务端采样? 因为磁盘/网络的速率本质上就是「两次采样之间的差值」,没法在 HTTP 请求发生的
    那一刻凭空算出来。所以有一个后台线程固定 1 Hz 采样写进 deque,前端只是来取。


    值得抄的 6 个实现细节

    1. 速率只能用 delta 算,不能在请求时重新采样

    这是最容易踩的坑。直觉写法是「收到请求 → 读一次 /proc/diskstats → 和上次比」,但**「上次」存在哪**
    是问题:如果请求比采样线程更频繁,就会拿两个几乎同时刻的采样点作差,差值被摊薄成一个极小的时间窗,
    算出来的速率要么是 0,要么抖得没法看。

    正确做法是:后台线程独占采样,HTTP 只返回缓存的结果。

    def disk_info(prev, dt):
        """prev 是上一次采样的 /proc/diskstats 快照,dt 是两次采样之间的时间差。"""
        for name, v in cur.items():
            old = (prev or {}).get(name)
            if old and dt > 0:
                d["read_bps"]  = round((v[2] - old[2]) * 512 / dt, 1)   # 扇区数 × 512 = 字节
                d["write_bps"] = round((v[6] - old[6]) * 512 / dt, 1)
                d["read_iops"] = round((v[0] - old[0]) / dt, 2)
    

    后台循环里 dt 用真实经过时间:

    def sample_once():
        now = time.time()
        dt = max(0.5, now - STATE["prev"].get("ts", now - SAMPLE_INTERVAL))
        STATE["prev"]["ts"] = now
    

    2. 统一内存架构下,nvidia-smi 的显存字段是 [N/A]

    GB10 的 CPU 和 GPU 共享同一块内存(标称 128 GB,系统可见约 122 GiB),
    nvidia-smi 对显存总量/占用直接返回 [N/A]:

    $ nvidia-smi --query-gpu=memory.total,memory.used --format=csv
    [N/A], [N/A]
    

    所以面板里的「统一内存」读的是 /proc/meminfo,而不是显存字段;GPU 面板只取利用率/温度/功耗。
    另外 power.limit、fan.speed 在这台机器上也是 [N/A],别指望它们。

    顺带一个有用的取法:逐进程显存是可以拿到的(--query-compute-apps),把它求和就得到
    「模型常驻显存」:

    rc, so, _se = run(["nvidia-smi", "--query-compute-apps=pid,used_gpu_memory,process_name",
                       "--format=csv,noheader,nounits"])
    out["model_gpu_mib"] = round(sum(p["mem_mib"] for p in procs), 1)
    

    3. 用 12 栅格显式定位,而不是 auto-fit

    最初用 grid-template-columns: repeat(auto-fit, minmax(330px, 1fr)),结果卡片宽度随窗口变化,
    而且没法留空位、没法叠放。改成显式坐标后什么都解决了:

    .grid{display:grid;grid-template-columns:repeat(12,minmax(0,1fr));
          grid-auto-rows:44px;gap:10px}
    .card{grid-column:span var(--w,3);grid-row:span var(--h,5)}
    

    每张卡片存 {x, y, w, h}(单位是栅格格数),JS 直接写:

    el.style.gridColumn = (c.x + 1) + " / span " + c.w;
    el.style.gridRow    = (c.y + 1) + " / span " + c.h;
    

    显式坐标才能表达「第二行右边留空」和「磁盘 I/O 叠在网络接口下面」这种排布——自动排布是做不到的。

    4. 卡片被压住时「就近挪开」,而不是跳到页面另一头

    拖动时如果落点压住了别的卡片,需要把被压的挪走。朴素的实现是「从左上角扫描找第一个空位」,
    结果卡片会莫名其妙飞到页面最上面。这里改成收集所有空位,再按离原位的距离排序:

    function findSpot(w, h, exceptId, prefer){
      const free = [];
      for (let y = 0; y < 400; y++)
        for (let x = 0; x <= GRID.cols - w; x++){
          const cand = {x, y, w, h};
          let ok = true;
          for (const [id, c] of Object.entries(state)){
            if (id === exceptId) continue;
            if (overlaps(cand, c)){ ok = false; break; }
          }
          if (ok) free.push({x, y});
        }
      if (!free.length) return {x: 0, y: 0};
      if (prefer)   // 就近安置:离原位越近越优先
        free.sort((a, b) => (Math.abs(a.x - prefer.x) + Math.abs(a.y - prefer.y))
                          - (Math.abs(b.x - prefer.x) + Math.abs(b.y - prefer.y)));
      return free[0];
    }
    

    5. canvas 曲线:nice tick + 自动单位 + 悬停十字线

    不用图表库,纯 canvas 画。三点值得注意:

    Y 轴刻度取「好看」的步长,否则会出现 7.4993 这种刻度:

    niceStep(range){
      const raw = range / 4, mag = Math.pow(10, Math.floor(Math.log10(raw) || 0));
      const n = raw / mag;
      return (n <= 1 ? 1 : n <= 2 ? 2 : n <= 2.5 ? 2.5 : n <= 5 ? 5 : 10) * mag;
    }
    

    单位自动切换:网络速率可能是 500 B/s 也可能是 200 MB/s,固定单位必然有一头显示成
    0.00 MB/s 或 123456789 B/s。所以按量级挑单位:

    if (this.opts.autoUnit){
      const m = Math.max(Math.abs(vmin), Math.abs(vmax));
      if      (m >= 1048576){ this._scale = 1048576; this._unit = "MB/s"; }
      else if (m >= 1024)   { this._scale = 1024;    this._unit = "KB/s"; }
      else                 { this._scale = 1;       this._unit = "B/s"; }
    }
    

    悬停十字线:鼠标位置换算成时间,吸附到最近的采样点:

    onMove(e){
      const g = this._geo;
      const x = e.clientX - this.cv.getBoundingClientRect().left;
      this.hover = (x - g.padL) / g.pw;
      this.draw();                      // 重画时画十字线
      const t = g.t0 + (g.t1 - g.t0) * this.hover;
      for (const s of this.series){
        const p = this.nearest(s.data, t);   // 线性找最近点
        ...
      }
    }
    

    6. 布局持久化 + JSON 导出/导入

    位置存 localStorage,再提供导出/导入,这样「我摆好的版面」可以固化成一段文本:

    const LAYOUT_KEY = "sparkmon_layout_v3";
    function readLayout(){ return {layout: JSON.parse(JSON.stringify(state)), win: WIN}; }
    function saveLayout(){ localStorage.setItem(LAYOUT_KEY, JSON.stringify(readLayout())); }
    

    导出的 JSON 长这样,一眼就能看出每张卡片的格子坐标:

    {
      "layout": {
        "card-cpu":    { "x": 0,  "y": 0,  "w": 2, "h": 5 },
        "card-engine": { "x": 0,  "y": 5,  "w": 6, "h": 5 },
        "card-logs":   { "x": 0,  "y": 24, "w": 12, "h": 6 }
      },
      "win": 300
    }
    

    部署

    # 1. 放到机器上
    scp -r dgx-monitor <user>@<SPARK_IP>:~/
    
    # 2. 一键安装(注册 systemd 服务 + 自检)
    cd dgx-monitor && bash install.sh
    

    install.sh 做的事:把文件装到 ~/dgx/monitor/、用 sed 替换 systemd 单元里的
    User= / WorkingDirectory= / MONITOR_PORT=、daemon-reload、enable --now,
    最后 curl 一下首页确认真的起来了。

    自检脚本检查这几项,任何一项不过会明确指出:

    $ bash verify.sh
      PASS  服务 spark-monitor active
      PASS  首页 200(48958 字节)
      PASS  API /api/stats 200
      PASS  新版前端已生效(找到栅格卡片)
      PASS  快照字段齐全(gpu/sensors/disk/network)
      PASS  /api/config 200
      PASS  /api/logs 200
      PASS  /api/healthz 200
      PASS  llm      :8888 /health ok
    

    也可以不用 systemd,直接前台跑:

    MONITOR_PORT=8890 python3 monitor.py
    

    踩坑清单(实战)

    这几条都是真踩过的,写出来省得别人再踩一遍。

    1. 一个没定义的函数,能让半张页面变成空白。
    前端调了 setBar() 但从没定义过它,ReferenceError 直接把 loadSnapshot() 从中间打断,
    结果 GPU、传感器、磁盘、网络、进程、容器、引擎表全部没渲染,而页面看起来只是「没数据」。
    教训:前端的渲染要分段,别让一个异常连坐后面所有模块;排查时先看 console 报错。

    2. 同名函数声明会互相覆盖。
    布局管理里有个 function render() 画栅格,数据渲染里也有 function render(s) 画面板——
    JS 里函数声明会被提升,后定义的那个赢,于是数据渲染被静默顶掉,页面全空但不报错。
    后来把布局那个改名 paintLayout() 才解决。

    3. 轮询打爆后端日志。
    监控自己每秒去拉推理引擎的 /metrics,但没带 API Key,结果后端日志里刷了 1000 多条 401。
    加了 API Key 还不够,又加了失败退避:

    if resp.status == 401:
        self._engine_blocked_until = now + 300.0    # 401 就安静 5 分钟
    

    4. 单位约定不一致,数值会离谱 1000 倍。
    Prometheus 的 time_to_first_token_seconds 是秒,但另一套采集里换算成了毫秒,
    两边混用就会看到「TTFT 均值 105952.685 s」。贴指标前先确认单位,表头也要写清楚。

    5. Y 轴标签被裁掉。
    padL: 48 放不下 87.81 MB/s,首字符被切掉变成 7.81 MB/s,看起来像数据错了。
    标签宽度要按「最长刻度 + 单位」算。

    6. install.sh 用 enable --now 不会重启已在跑的服务。
    enable --now 对已运行的服务是 no-op,改完代码重新安装,线上跑的还是老版本。
    正确做法是 systemctl --user enable 之后显式 restart。

    7. systemd 单元里的 User= 是写死的。
    别人拿去用就会因为用户名不同而起不来。安装脚本里用 sed 替换成当前用户。


    文件清单

    dgx-monitor/
    ├── monitor.py              后端(标准库,零依赖)      ~34 KB
    ├── index.html              前端(单文件,无 CDN)      ~49 KB
    ├── spark-monitor.service   systemd 单元模板
    ├── install.sh              一键安装
    ├── verify.sh               部署后自检
    └── layout.test.js          布局引擎单元测试
    

    layout.test.js 是给布局逻辑写的单元测试(纯逻辑,Node 里跑,浏览器无关),
    校验默认版面不重叠、关键排位、碰撞推挤、就近安置、持久化往返:

    $ node layout.test.js
    == 1. 默认版面(17 张卡片)自身不重叠 ==
      PASS  全部卡片互不重叠
      PASS  状态里有 17/17 张卡片
    ...
    == 5. findSpot 返回真正空的位子 ==
      PASS  空位 {"x":0,"y":30} 无冲突
      PASS  带 prefer 取位不更远:{"x":8,"y":30}(距离 21 ≤ 扫描序 29)
    全部通过 ✅
    

    怎么拿到源码

    源码就上面这 7 个文件,没有构建步骤、没有依赖清单,全量 84 KB。几种给法:

    • 贴到 gist / 仓库:只有 7 个文件,直接建个仓库传上去最省事
    • 打包成 tar.gz:tar czf dgx-monitor.tar.gz dgx-monitor/,随帖附上
    • 从帖子直接抄:本文已经把最关键的 6 段实现贴出来了,照着写也能复现个七七八八

    如果你想给别人的是「换个样式 / 换数据源」的版本,改 index.html 里的 CHARTS / DEFAULT_LAYOUT
    两个常量就够了,数据源在 monitor.py 的 sample_once() 里。

    源码里的占位符

    发布版把和具体环境绑定的部分换成了占位符,拿到后改这几处即可:

    占位符 在哪 改成
    <ENGINE_PREFIX> monitor.py(Prometheus 指标前缀,约 20 处) 你引擎的前缀,例如 vllm:
    <model-name> monitor.py 模型名;留空则自动从 /v1/models 发现
    <user> spark-monitor.service 不用手改,install.sh 会自动替换成当前用户名

    已知限制

    • 面板不绑定任何推理后端。引擎相关的部分靠读 /metrics(推理服务 / vLLM 都行),
      没起容器时那几块是空的,其余面板照常工作。
    • API Key 只存在于内存或容器环境变量里,面板本身不落盘、不外传。
    • 布局存在浏览器 localStorage,换浏览器要靠「布局…」里的 JSON 搬运。
    • 采样精度受限于 1 Hz:突发写入(几百 MB 的 dd)能抓到,持续小流量会被平均掉。
    • 只做了 Linux/aarch64,其它平台的采集函数(/proc、hwmon)需要改。

    本文配图与源码均已做脱敏处理:模型名、容器镜像 tag、引擎名、用户名、主机名、IP、API Key
    均已替换为占位符或打码;面板本身也从不显示 API Key 的值。

    dgx-monitor-post.zip


  • DGX Spark + TensorFold/SparkFold 跑 Qwen3.8-Flash-Next 完整实战:EXL3 4.05bpw 由 18 个补丁到中文 draft 词表,decode 64.7 tok/s(附全套 benchmark)
    J juntucoo
    LLM讨论区 dgxspark gb10 qwen

    微信图片_2026-11-02_163349_639.png
    为了方便在内网查看设备的实时是使用情况,让DSH写了一个网页。效果还不错。


  • DGX Spark + TensorFold/SparkFold 跑 Qwen3.8-Flash-Next 完整实战:EXL3 4.05bpw 由 18 个补丁到中文 draft 词表,decode 64.7 tok/s(附全套 benchmark)
    J juntucoo
    LLM讨论区 dgxspark gb10 qwen

    @terry 收到,下次注意。


  • 7900XTX选择困难症
    J juntucoo
    随便聊聊 7900xtx amd

    @terry 谢谢大佬提醒!店家说是管保,也查了官网,是有这家店的。


  • 求助帖!各位大神7900XTX的AMD公版卡可以入手吗?
    J juntucoo
    AI硬件 7900xtx amd

    那么蓝宝石的涡轮卡有没有均热板呢?


  • 7900XTX选择困难症
    J juntucoo
    随便聊聊 7900xtx amd

    我准备在淘宝下单时发现买完了,就里面问客服,追了好一会才又放出来。上一次7000没下单,这次7200才下单,真系嫌钱腥。


  • DGX Spark + TensorFold/SparkFold 跑 Qwen3.8-Flash-Next 完整实战:EXL3 4.05bpw 由 18 个补丁到中文 draft 词表,decode 64.7 tok/s(附全套 benchmark)
    J juntucoo
    LLM讨论区 dgxspark gb10 qwen

    DGX Spark + TensorFold/SparkFold 跑 Qwen3.8-Flash-Next 完整实战:EXL3 4.05bpw 由 18 个补丁到中文 draft 词表,decode 64.7 tok/s(附全套 benchmark)

    沿着 dgx-spark-llm-serving-main 仓库 lanes/exl3-sparkfold 这条路线,我在 DGX Spark 上从零跑了一遍完整 setup(2026-10-29 部署完成,服务在跑),顺便做了全套 benchmark 和中文 draft 词表的 A/B 实测。有几个发现(尤其中文词表那 part)想还回来给社群。

    一、硬件

    • DGX Spark:GB10(sm_121a)、128 GB 统一内存、aarch64,Docker 带 NVIDIA runtime
    • 根分区 3.7 T,这条 lane 共占 173 G:
    ~/models/qwen3.8-flash-next-exl3-4.05bpw    101 G   权重
    ~/.cache/tensorfold-sparkfold               967 M   扩展缓存 + 视觉权重
    ~/tensorfold-src                             25 M   打补丁的源码树
    ~/src                                       ~70 M   上游配方 + TensorFold tarball
    /var/lib/docker                             ~70 G   镜像
    
    • 前置条件(01-healthcheck.sh 只读体检,不要跳过):可用统一内存 ≥ 121 GiB、磁盘可用 ≥ 200 GiB(权重 100 + 缓存 + spill 最多 48)、docker info 能看到 NVIDIA runtime。

    二、软件栈和安装

    • 引擎:TensorFold 0.6.5 + SparkFold 806b345 + 仓库 18 个补丁。这条 lane 的全部价值来自那 18 个补丁——仓库记录过未打补丁时英文 decode 42.6 tok/s vs 打完 62.9,不要用未经补丁的 SparkFold 跑。
    • 镜像:tensorfold-qwen38:v0.3.6.3(MiaAI-Lab 封装)再叠一层 xgrammar(response_format / 结构化输出)→ tensorfold-qwen38:v0.3.6.3-xgrammar(36.9 GB,tf.patches=c1f5d72f8d16)。
    • 部署脚本全部做成幂等,失败重跑即可;都支持 DRY_RUN=1 打印将执行的命令。
    cd ~/dgx-spark-deploy && chmod +x *.sh
    
    bash 01-healthcheck.sh        # 只读体检,先做
    bash 02-build-tree.sh         # SparkFold 806b345 + 18 补丁 → ~/tensorfold-src
    bash 03-build-image.sh        # 两层镜像(v0.3.6.3 → v0.3.6.3-xgrammar)
    bash 04-download-pack.sh      # 权重 99.94 GiB:钉 commit sha + 逐文件 size + SHA-256 校验
    bash 05-vision.sh             # 视觉权重转换(可选,VISION=0 就跳过)
    bash 05b-draft-vocab-zh.sh    # 构造中文 draft 词表(中文场景建议做,见第七节)
    bash 06-start.sh              # 启动(封装仓库的 start.sh,不重新实现启动逻辑)
    bash 07-smoke.sh              # 冒烟 + 中英文基准(RUN_BENCH=1 附带仓库的 bench_en.py)
    

    全新机器先跑 bash 00-bootstrap.sh:检查并补齐 Docker / NVIDIA Container Toolkit / hf CLI,已装的一律跳过,最后一步跑 GPU 容器冒烟,确认容器里真能看到 GB10。
    02-build-tree.sh 末尾应显示 spill.py 在位(补丁 0005)。
    MiaAI-Lab 的 prepare.sh 第 3、4 步会下载该封装自己的 MLX checkpoint,本 lane 用不到;照跑是为了与上游保持一致。

    三、两个必改的关键配置(今次分享重点之一)

    3.1 内存地板 6 GiB —— 不是随便定的

    TensorFold 0.6.5 的 stream cache 规则:只有当宿主机 MemAvailable 高于 max(4 GiB, RAM/10)(本机 = 12.2 GiB)再加 2 GiB 时才允许增长,否则直接丢掉一条空闲对话的整个状态。而 Spark 服务这个模型时空载只有约 15 GiB 可用——于是一条长对话会把另一条挤掉,每一轮都变成冷 prefill。

    仓库的对照实验(三条对话轮流,16 token 回复):

    内存地板 后面几轮从零重新 prefill 的次数
    12.2 GiB(引擎默认) 8 轮里 7 轮(丢了 409 s 的 prefill)
    6 GiB(TENSORFOLD_MEMORY_RESERVE_GIB=6) 9 轮里 0 轮

    代价:到 earlyoom SIGTERM 线(RAM 的 3% = 3.6 GiB)的余量从约 11 GiB 降到约 5 GiB。所以不要把 n-gram 表全锁住——仓库记录过 TENSORFOLD_PIN_EXTRA_GIB=12(锁 36 GiB)会让 earlyoom 直接 SIGKILL 掉服务。当前配置 PIN_EXTRA_GIB=-6.2,让锁页量维持在 20-25 GiB。

    3.2 NVMe spill —— 救 evicted 的对话,不是加速

    TF_SPILL_DIR=/cache/spill,只写 ≥ 16384 token 的状态,目录上限 48 GiB,LRU 淘汰。仓库实测:100k token 的状态约 1.5-1.8 GiB,写 0.30-0.40 s,读 0.26-0.45 s。

    它只在对话被挤掉时救命。内存够时它什么都不做,也不带来加速。仓库明确写:只在受控重放里验证过,没有在真实流量上验证过——当成便宜的保险,不要当成实测收益。

    四、模型

    turboderp/Qwen3.8-Flash-Next-exl3,分支 4.05bpw_h6_ng6,EXL3 4.05 bpw,125B 总参 / 6B 激活,99.94 GiB。

    本机校验结果:26 个文件的 size + SHA-256 与 Hub 逐个一致,实下 100.08 GiB(trunk 62.9 GiB / n-gram 表 36.36 GiB / 视觉 0.52 GiB,与仓库记录逐项吻合)。

    为什么必须逐文件校验:仓库的 vLLM lane 明确记录过——大小对但内容截断的 shard 能正常加载、报告出合理的 shape、产出量级正确的激活值,然后生成通顺但完全错误的输出。不崩溃,不报错,只是不对。有人为这个丢了一天。

    另两个硬坑(与网络无关,但必须钉住版本):

    1. 上游封装仓库(MiaAI-Lab)的 main 已换成 Zig 原生引擎,与本 lane 的 Python 引擎不兼容。必须用 commit 38da375e5f4a0be0ed4c065d1014f61088e0a9e4(2026-09-29,最后一个 Python 引擎 + TensorFold v0.3.6.3 版本)。这个 commit 是对的,有硬证据:它的补丁集 hash 是 c1f5d72f8d16,与仓库 README 记录的镜像标签 tf.patches=c1f5d72f8d16 一字不差。
    2. 04-download-pack.sh 会先把分支名解析成 commit sha 再下载,钉住版本、可复现,并逐文件比对 size + SHA-256——照做就行。

    五、生产启动配置(全套)

    06-start.sh 透传给仓库 start.sh:

    变量 默认 说明
    PROFILE spark safe = 旧解码策略(A/B 对照用);bare = 引擎默认值
    SPILL 1 NVMe spill。SPILL=0 关掉
    VISION 1 多模态。VISION=0 关掉
    PARALLEL 5 并发流数
    CONTEXT 262144 上下文长度
    KV_DTYPE int8 KV 精度
    PORT 8888 端口
    BIND 127.0.0.1 监听地址。BIND=(空)= 所有网卡
    KNOBS — 追加任意 TF_*,如 KNOBS="TF_KEEP=32"
    KNOBS="TF_DRAFT_VOCAB=draft_vocab_zh.txt" bash 06-start.sh   # 中文词表(推荐)
    PROFILE=safe bash 06-start.sh            # 对照组
    VISION=0 SPILL=0 bash 06-start.sh        # 纯文本、不落 NVMe
    BIND= bash 06-start.sh                   # 对外提供服务(服务没有 API key,不要暴露到不可信网络)
    

    启动日志里应该看到这四行:

    lone-stream graph slot: 65536 rows
    spill: N stored states adopted
    ... GiB of pages locked            <- 本机实测 "22.0 GiB of it locked"(仓库记录 20-25 GiB)
    serving qwen3.8-flash-next ... loaded in ~90s
    

    首次启动要编译 CUDA/Triton 扩展(本机 260 s),之后重启 73.8 s。脚本会等到 /health 有响应(最多 15 分钟)。服务在 127.0.0.1:8888。

    常用操作:

    bash 07-smoke.sh                              # 冒烟 + 中英文基准
    docker logs -f llm                            # 看日志
    docker exec llm env | grep TF_DRAFT_VOCAB     # 确认实际生效的词表
    

    日志目录 ~/.cache/tensorfold-sparkfold/logs/。仓库的 start.sh 会 docker rm -f 旧容器、日志随之消失,所以 06-start.sh 现在重启前会先把旧日志备份进去。

    六、Benchmark(本机 2026-10-29 vs 仓库基线 2026-10-21)

    Decode 单流: 英文 64.7 tok/s(69.12 / 68.72 / 55.50 / 65.54 四条提示均值)vs 仓库 62.9——同一套构建,吻合。中文装词表 53.4、不装 38.9(见第七节);仓库韩文基线 54.1。

    并发: 仓库 sgbench 端到端 1 / 2 / 4 流 = 66.9 / 92.1 / 131.1 tok/s;llama-benchy decode(深度 0)1 / 2 / 4 流 = 61.7 / 89.5 / 112.2 tok/s。本机只测了单流,多流并发没有测。

    Prefill(冷启动): 1.9k-49k token 真实文本 1,830-2,067 tok/s(仓库)。

    Spill 还原: 100k 对话被挤掉后,冷启 40-50 s vs 从 NVMe 还原 0.8-2.3 s(仓库)。

    工具调用: tool-eval-bench 90/100(装 xgrammar 后,仓库)。

    关键校验(本机):

    • 权重:26 个文件 size + SHA-256 逐个一致,100.08 GiB
    • 源码树:18 个补丁提交全在,draft_vocab_ko.txt 86,232 行(与仓库记录一字不差)
    • 镜像:tf.patches=c1f5d72f8d16(与仓库 README 记录一致)
    • 引擎启动:22.0 GiB locked、84 个图、spill 目录 48 GiB、视觉塔 0.84 GiB

    没测的(诚实清单): 中文质量没有基线(仓库对韩文质量和长工具上下文质量也明确没测过,速度追平 ≠ 质量追平,需要自己评估);多流并发;视觉输入(权重转换好了、引擎起来了,但没实际发过图片)。

    七、中文 draft 词表 A/B 实测(新发现)

    背景:MTP 投机解码的 drafter 只能从一张候选 token 列表里挑下一个 token。引擎自带的那张列表来自 CPython 标准库和 id < 65,536:

    覆盖 比例
    代码 / Markdown token 99.3-99.5%
    英文散文 token 93.9%
    韩文 token 47.5%

    中文比韩文更糟。 这张表基本全是 ASCII,而 Qwen 分词器里绝大多数汉字 token 的 id 都 ≥ 65,536——它们根本不在候选表里。drafter 看不见中文 token,中文的投机接受率会很低,而 decode 速率基本就是"不投机"的速度。

    上游其实已经做了中文版(MiaAI-Lab 的语言补丁带 draft_vocab_zh.txt,22,088 个纯汉字 token id),但那是替换语义——上游 README 明写 "English and code get a little slower with it"。本 lane 的 TF_DRAFT_VOCAB 是并集语义(仓库补丁 0009 的韩文表就是这么做的,补齐后英文贪心回复逐字节不变)。所以 05b-draft-vocab-zh.sh 取的是 并集:引擎默认表 ∪ 上游汉字 id = 101,679 个 id(默认 79,591 + 汉字 22,088)。中文拿到全部候选,英文和代码不受影响。

    A/B(同一套构建、同一批中文提示、同一份 server 配置,只换 TF_DRAFT_VOCAB):

    词表 ZH-HIST ZH-SCI ZH-ADV 均值
    draft_vocab_ko.txt(仓库默认,不含汉字) 34.38 42.80 39.52 38.90
    draft_vocab_zh.txt(默认表 ∪ 汉字) 50.40 55.96 53.68 53.35

    +37.1%。 仓库测韩文时是 42 → 49(+17%),中文的增幅更大——因为默认表里汉字的覆盖率比谚文还低。旁证:每 chunk 的 token 数从 1.20-1.59 升到 1.88-2.11,也就是 MTP 接受率上去了,这正是 draft 词表该起的作用。对照仓库韩文基线 54.1:中文词表装上之后,中文追平韩文。

    基准方法(tools/bench_zh.py,与仓库 bench_ko.py 同构):走 /v1/chat/completions,不覆盖采样参数(用服务端默认),thinking 打开,三条中文长句提示(历史散文 / 科学解释 / 现实建议),600 token 是测量窗口不是服务上限,流式测量、用首末 chunk 之间的时间把 decode 从 prefill 里分出来。

    复现:

    cd ~/dgx-spark-deploy
    # A:仓库默认(不含汉字)
    KNOBS="TF_DRAFT_VOCAB=draft_vocab_ko.txt" bash 06-start.sh
    BENCH_MODEL=qwen3.8-flash-next BENCH_URL=http://127.0.0.1:8888/v1/chat/completions \
      python3 tools/bench_zh.py
    # B:中文并集表
    KNOBS="TF_DRAFT_VOCAB=draft_vocab_zh.txt" bash 06-start.sh
    BENCH_MODEL=qwen3.8-flash-next BENCH_URL=http://127.0.0.1:8888/v1/chat/completions \
      python3 tools/bench_zh.py
    

    要注意的取舍:

    • 只影响速度,不影响质量。 draft 出来的 token 要经过验证才被采纳,换词表不会改变回复内容(仓库对韩文验证过"英文贪心回复逐字节相同")。
    • 一次只认一个词表。 TF_DRAFT_VOCAB 是一个文件名,韩文表和中文表不要同时用;中文表取的是并集,换过去不会丢掉英文/代码的覆盖。
    • 06-start.sh 会把仓库默认的韩文表和 KNOBS 一起传给 docker,同名变量以最后一个为准;用 docker exec llm env | grep TF_DRAFT_VOCAB 确认实际生效值。

    八、陷阱清单

    • 未打补丁的 SparkFold 千万别跑:英文 decode 42.6 vs 打完补丁 62.9,差一半。
    • 权重必须逐文件 SHA-256 校验:截断的 shard 不崩溃、不报错,只是生成"通顺但完全错误"的输出。
    • n-gram 表千万别全锁:TENSORFOLD_PIN_EXTRA_GIB=12(锁 36 GiB)→ earlyoom 直接 SIGKILL 服务。
    • set -e + pipefail 会让脚本静默死掉:grep 没匹配 → 退出 1 → 管道非 0 → 脚本被杀,什么错误信息都没有。07-smoke.sh 就这么死过一次(引擎的锁页日志是 "22.0 GiB of it locked",不是仓库旧版的 "pages locked")。凡是 grep ... | ... 形式的输出行,后面都要 || true。
    • 上游封装仓库的 main 已换成 Zig 引擎:必须钉 commit 38da375e…(补丁集 hash c1f5d72f8d16 对得上镜像标签,是硬证据)。
    • 仓库 start.sh 会 docker rm -f 旧容器,日志随之消失——06-start.sh 已改成先把日志备份到 $CACHE/logs/ 再重启。
    • 第一条回复特别慢是正常的:另一个 graph 槽位首次解码要多花 0.6-1.6 s,第二次就正常。
    • 本 lane 不主打 prefix caching:重复前缀不保证命中,与 vLLM lane 不同。
    • 服务没有 API key:BIND= 对外监听只可以在可信局域网里用。
    • 对话每轮都重新 prefill 多半是内存地板问题:看日志里 memory gate evicted ...,确认 TENSORFOLD_MEMORY_RESERVE_GIB=6。

    致谢

    dgx-spark-llm-serving 仓库(lanes/exl3-sparkfold)的前辈记录、turboderp 的 EXL3 权重、MiaAI-Lab 的封装与上游语言补丁、TensorFold / SparkFold。中文质量评估如果有人焗到更深,欢迎交流。


  • 7900XTX选择困难症
    J juntucoo
    随便聊聊 7900xtx amd

    @909 是参考价格吗?闲鱼想找个靠谱的不容易啊,好东西不太容易找。


  • 7900XTX选择困难症
    J juntucoo
    随便聊聊 7900xtx amd

    PDD店家说这个3年保修是标错的,都是统一1年店保没有官保。随后果断淘宝,淘宝2年的是官保。


  • 7900XTX选择困难症
    J juntucoo
    随便聊聊 7900xtx amd

    7900.png
    7900-1.png

    本人目前的硬件配置是:CPU 为 i7-13700,主板为微星 PRO B660M-A WIFI DDR4,内存 32G DDR4 3200,显卡为 TESLA P4 8G。计划先入手一张 7900 XTX,再增加内存,用于本地部署,借此多学习、提升技能。想请教各位大佬:淘宝目前 7200 元、保修两年,拼多多 7400 元、保修三年,选哪个更好?

  • 登录

  • 登录或注册以进行搜索。
  • 第一个帖子
    最后一个帖子
0
  • 版块
  • 最新
  • 标签
  • 热门
  • 用户
  • 群组