Skip to content

docs: add /ci-queue-times command for per-cluster CI queue latency / 新增 /ci-queue-times 命令:按集群查看 CI 排队延迟#2270

Open
JordanNanos wants to merge 4 commits into
mainfrom
claude/ci-queue-times-command
Open

docs: add /ci-queue-times command for per-cluster CI queue latency / 新增 /ci-queue-times 命令:按集群查看 CI 排队延迟#2270
JordanNanos wants to merge 4 commits into
mainfrom
claude/ci-queue-times-command

Conversation

@JordanNanos

Copy link
Copy Markdown
Collaborator

Description

Adds a new .claude/commands/ci-queue-times.md slash command — /ci-queue-times [history-run-limit] — for checking CI queue times across all GPU clusters.

GitHub has no queue-metrics API for self-hosted runners, so the command derives queue time from the Actions API (queue time = job started_atcreated_at, cluster = job runner label; pool mapping from configs/runners.yaml). It bundles three verified queries:

  1. Live queue — currently queued jobs (including queued matrix jobs inside in-progress sweep runs) with wait-so-far, cluster label, and run ID.
  2. Historical per-cluster latency — jobs / avg / p50 / max queue minutes over the last N runs (default 150), with re-run artifacts filtered (q >= 0) and cluster:* label normalization.
  3. Runner availability per pool — total / online / busy runners per pool, i.e. the "why" behind queue times.

Caveats are documented in the file: the SLURM second queue on *-dgxc / *-nv pools (check via squeue -u <runner-user>), canary-gate exclusion, and label-shape handling.

None of the existing .claude/commands/ covers this — the PR-status commands only see GitHub check states, and klaud-pr-status-html's queue-aware ETA is a pessimistic pool-pressure estimate scoped to claude/* PRs, not measured per-cluster queue latency.

All three queries were executed against live Actions data during development. This is an agent-instruction file → English-only per the bilingual-docs exception in AGENTS.md.

Related Issue

N/A

Type of Change

  • Bug fix
  • New feature
  • Configuration change
  • Documentation update
  • Other (please describe)

Checklist

  • I have tested my changes locally (all three embedded queries run against the live Actions API)
  • I have updated documentation if necessary (the command file is the doc; agent-instruction files are English-only per AGENTS.md)
  • If I changed a container image or config, I have already updated perf-changelog.yaml — N/A, no image/config change
  • Before merging via reuse ... /reuse-sweep-run ... — N/A, no benchmark sweep needed (no sweep label applied; nothing here affects benchmark results)

中文说明

新增 .claude/commands/ci-queue-times.md 斜杠命令 —— /ci-queue-times [历史窗口] —— 用于查看所有 GPU 集群的 CI 排队时间。

GitHub 没有针对自托管 runner 的排队指标 API,因此该命令通过 Actions API 推导排队时间(排队时间 = 任务 started_atcreated_at,集群 = 任务的 runner 标签;池与 runner 的映射见 configs/runners.yaml)。包含三个已验证的查询:

  1. 当前队列 —— 正在排队的任务(包括进行中的扫描工作流里尚未调度到 runner 的矩阵任务),显示已等待时长、集群标签和 run ID。
  2. 按集群统计的历史排队延迟 —— 最近 N 个运行(默认 150)内的任务数 / 平均 / P50 / 最大排队分钟数;已过滤重跑导致的异常负值(q >= 0),并对 cluster:* 标签做归一化。
  3. 按 runner 池统计的可用性 —— 每个池的总数 / 在线 / 忙碌 runner 数,用于解释排队背后的原因。

文件中已注明注意事项:*-dgxc / *-nv 池存在 SLURM 二级队列(需在集群上用 squeue -u <runner-user> 查看)、金丝雀门禁(canary gate)不计入排队时间、以及标签格式的处理方式。

现有 .claude/commands/ 均不覆盖此场景 —— PR 状态类命令只能看到 GitHub check 的状态,而 klaud-pr-status-html 的排队 ETA 只是面向 claude/* PR 的悲观池压力估算,并非实测的按集群排队延迟。

三个查询在开发过程中均已对仓库的 Actions 数据实际执行验证。本文件属于 agent 指令文件,按 AGENTS.md 的双语文档例外规则仅提供英文版本。

其他:无镜像或配置变更,无需更新 perf-changelog.yaml;未添加扫描(sweep)标签,本变更不应触发任何 GPU 基准测试。

…latency

Adds a .claude/commands shortcut with the three gh-API queries for checking
CI queue times across all GPU clusters: live queued jobs with wait-so-far,
historical per-cluster queue latency (started_at - created_at, re-run
artifacts filtered), and per-pool runner availability. Includes the
cluster:* label normalization and SLURM second-queue caveats.

中文:新增 /ci-queue-times 命令,用于查看所有 GPU 集群的 CI 排队时间。包含三个基于
gh API 的查询:当前正在排队的任务及已等待时长、按集群统计的历史排队延迟
(started_at − created_at,已过滤重跑导致的异常值),以及按 runner 池统计的
可用性。命令中已处理 cluster:* 标签归一化,并注明 SLURM 二级队列的注意事项。

No PR opened per request; branch only.
@JordanNanos

Copy link
Copy Markdown
Collaborator Author

Sample output of /ci-queue-times, focused on the H200 cluster (run 2026-07-18 ~15:05 UTC).

Historical queue latency — window: scanned runs newest→oldest until ≥25 H200 samples were collected (486 GPU jobs total). H200 rows:

cluster        jobs  avg_min  p50_min  max_min
h200           4     0        0.1      0
h200-dgxc      22    1.7      0.1      13

For contrast, the busiest pool in the same window was b200-dgxc (62 jobs, p50 133.5 min, max 654 min).

Runner availability, H200 pools (live):

pool               total_runners  online  busy
h200               16             16      8
h200-cw            2              2       0
h200-dgxc          14             14      8
h200-dgxc-slurm    14             14      8
h200-multinode     3              3       1
h200-multinode-p1  1              1       1
h200-nb            1              1       0
h200-p1            4              4       1

(Pools overlap: h200-dgxc / h200-dgxc-slurm are the same 14 physical runners carrying multiple labels, and the h200 pool label spans the dgxc + cw machines.)

Live queue: zero H200 jobs queued right now — the current queue is entirely gb200-nv (9 jobs, ~567 min waiting), gb300-nv (~319 min), and b200-dgxc (~331 min).

Takeaway: H200 has no meaningful CI queue — p50 wait ≈ 6 seconds, worst case 13 min, half the pool idle. If a sweep is stuck, H200 is not the bottleneck; b200-dgxc and the gb*-nv multi-node pools are.

中文:以上为 /ci-queue-times 命令针对 H200 集群的示例输出(运行时间 2026-07-18 约 15:05 UTC)。历史排队延迟窗口:按时间从新到旧扫描运行记录,直到收集到 ≥25 个 H200 样本(共 486 个 GPU 任务)。结果显示 H200 的 P50 排队时间约 0.1 分钟(约 6 秒),最差 13 分钟,基本无排队;runner 可用性方面 16 台全部在线、仅 8 台忙碌,且当前实时队列中没有任何 H200 任务 —— 排队全部集中在 gb200-nv(约 567 分钟)、gb300-nv(约 319 分钟)和 b200-dgxc(约 331 分钟)。注意各池标签有重叠:h200-dgxch200-dgxc-slurm 是同一批 14 台物理 runner。结论:如果某个扫描(sweep)卡住,瓶颈不在 H200,而在 b200-dgxcgb*-nv 多节点池。

… queued jobs

Drop the historical per-cluster latency analysis in favor of a single
live-snapshot pass: per-pool active/queued summary, active jobs with
runtime-so-far, and queued jobs with wait-so-far. Adds an optional pool
filter regex argument, a total_count coverage check, and a caveat for the
0-active-but-queued case (offline/stuck/org-scoped-busy runners).

中文:将 /ci-queue-times 命令改为实时快照模式,聚焦当前正在运行的任务和排队队列,
移除按集群统计的历史排队延迟分析。新流程单次扫描即可输出:按池统计的
活跃/排队任务数、活跃任务及已运行时长、排队任务及已等待时长。新增可选的
池过滤正则参数、total_count 覆盖度校验,以及“活跃为 0 但排队堆积”场景
(runner 离线、状态卡死或被组织内其他仓库占用)的排查说明。
@JordanNanos

Copy link
Copy Markdown
Collaborator Author

Reworked per review feedback: the command no longer does historical analysis — it now takes a single live snapshot and reports (1) per-pool active/queued summary, (2) active jobs with runtime-so-far, (3) queued jobs with wait-so-far, plus an optional pool-filter argument. Fresh sample output from the new version:

pool       active  queued
b200-dgxc  0       10
gb200-nv   3       9
gb300-nv   3       7
h200-dgxc  8       0
b300-nv    2       0

中文:已按反馈意见重写该命令:不再做历史分析,改为单次实时快照,输出(1)按池统计的活跃/排队任务数、(2)活跃任务及已运行时长、(3)排队任务及已等待时长,并支持可选的池过滤参数。上方为新版本的最新示例输出。

…mmary

Join the runners API into the Step 2 summary so it shows runners_online,
runners_busy, jobs_active, jobs_queued per pool. Documents the one-job-per-
runner-agent invariant and the diagnostic patterns it enables (saturated,
pool-down, stuck/org-scoped-busy runners, snapshot skew), plus the
pool-label overlap note. All-zero rows are filtered as noise.

中文:为 /ci-queue-times 的汇总表新增 runner 维度列:将 runners API 的数据并入
第二步汇总,按池展示 runners_online、runners_busy、jobs_active、jobs_queued。
注明“每个 runner agent 同一时刻只运行一个任务”的基本约束,以及由此得出的
诊断模式(池饱和、池宕机、runner 状态卡死或被组织内其他仓库占用、快照误差),
并说明池标签重叠会导致按行求和重复计数。全零行作为噪音过滤。
Comment thread .claude/commands/ci-queue-times.md Outdated
Comment on lines +19 to +24
```bash
{ gh api "repos/SemiAnalysisAI/InferenceX/actions/runs?status=queued&per_page=50" --jq '.workflow_runs[].id'
gh api "repos/SemiAnalysisAI/InferenceX/actions/runs?status=in_progress&per_page=50" --jq '.workflow_runs[].id'
} | sort -u | while read -r RUN; do
gh api "repos/SemiAnalysisAI/InferenceX/actions/runs/$RUN/jobs?per_page=100" --paginate \
--jq '.jobs[] | select(.status=="queued") | {labels: [.labels[] | sub("^cluster:";"") | select(test("^(self-hosted|Linux|X64|ARM64|slurm)$|_\\d+$") | not)], name, created_at, run_id}'

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Step 1's two runs-listing calls (.../actions/runs?status=queued and status=in_progress, lines 20-21) omit --paginate, so each status is silently capped at the first 50 results — inconsistent with line 23's jobs call, which does paginate. Since the API returns runs newest-first, a busy period (>50 concurrent in_progress runs across sweeps/canary/e2e/lint) would silently drop the oldest, longest-waiting runs from the live-queue table with no error or truncation indicator. Fix: add --paginate to both calls on lines 20-21.

Extended reasoning...

The bug: Step 1 lists candidate run IDs to scan for queued matrix jobs with:

gh api "repos/SemiAnalysisAI/InferenceX/actions/runs?status=queued&per_page=50" --jq '.workflow_runs[].id'
gh api "repos/SemiAnalysisAI/InferenceX/actions/runs?status=in_progress&per_page=50" --jq '.workflow_runs[].id'

Neither call passes --paginate. Without it, gh api fetches exactly one page of the "list workflow runs" endpoint, and per_page=50 sets that page's size to 50 — below the endpoint's actual max of 100. So each of status=queued and status=in_progress is capped at 50 runs, silently: no error, no truncation marker, the table just renders as if it were complete.

Why this is an inconsistency, not an intentional cap: The very next call in the same step, three lines down, fetches jobs for each run and correctly appends --paginate:

gh api "repos/SemiAnalysisAI/InferenceX/actions/runs/$RUN/jobs?per_page=100" --paginate

Step 2 also avoids this pitfall by using gh run list --limit "$LIMIT", where the gh CLI internally paginates run listings up to the requested limit. So the omission on lines 20-21 looks like an oversight specific to those two calls, not a deliberate design choice.

Why it matters here specifically: The GitHub Actions runs endpoint returns results newest-first. If more than 50 runs share a status, the calls silently drop the oldest matches — which, for in_progress, are exactly the runs that have been running (and hence queuing matrix jobs) the longest. This repo's whole premise for Step 1 is scanning in_progress runs because their matrix jobs may still be queued waiting for a runner (the sweep fan-out). Every in_progress workflow run counts toward that total, not just GPU sweep runs — lint, canary, e2e, recipe-reminder, and any concurrent PR/cron sweeps all contribute. During a busy period it's plausible for in_progress alone to exceed 50, at which point the longest-waiting sweep's queued jobs are dropped from the "live queue" table entirely, with the report looking complete.

Step-by-step proof:

  1. Suppose at query time there are 60 in_progress workflow runs across the repo (a mix of sweeps, canary, e2e, lint, cron jobs), sorted newest-first by the API.
  2. gh api ".../runs?status=in_progress&per_page=50" (no --paginate) returns only the first page — the 50 most recently started in_progress runs. The 10 oldest in_progress runs (positions 51-60) are never returned.
  3. Suppose one of those 10 dropped runs is a large matrix sweep that started earliest and still has several matrix jobs sitting queued waiting for a free GPU runner — the longest-waiting jobs in the whole queue.
  4. That run's ID never enters the sort -u | while read -r RUN loop, so gh api ".../runs/$RUN/jobs" --paginate is never called for it, and its queued jobs never appear in the final jq -s output.
  5. The command still prints a clean table via column -t, with no indication that 10 in_progress runs (and their queued jobs) were never scanned — the operator sees an apparently complete "who is waiting right now" report that is actually missing the longest-waiting jobs.

Fix: add --paginate to both calls on lines 20-21, matching line 23:

gh api "repos/SemiAnalysisAI/InferenceX/actions/runs?status=queued&per_page=50" --paginate --jq '.workflow_runs[].id'
gh api "repos/SemiAnalysisAI/InferenceX/actions/runs?status=in_progress&per_page=50" --paginate --jq '.workflow_runs[].id'

(Optionally also raise per_page to 100, the endpoint max, to reduce round trips.)

Severity rationale: This only manifests under unusually high concurrent CI load, and the failure mode is an incomplete (not incorrect) diagnostic table in an agent-instruction slash command — no production or benchmark path is affected. It's a real, trivially-fixable inconsistency with the rest of the same file, so worth flagging, but not blocking.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in a355cdd — both runs-listing calls now use --paginate, so busy periods no longer drop the oldest/longest-waiting runs. / 已在 a355cdd 修复:两个列出工作流运行的请求都加上了 --paginate,繁忙时段不会再静默丢弃最老、等待最久的运行。

Comment on lines +58 to +66
```bash
gh api "repos/SemiAnalysisAI/InferenceX/actions/runners?per_page=100" --paginate \
--jq '.runners[] | . as $r | [.labels[].name | select(test("^(cluster:)?(b200|b300|h100|h200|gb200|gb300|mi300x|mi325x|mi355x)")) | sub("^cluster:";"") | sub("_\\d+$";"")] | unique | .[] | {c: ., status: $r.status, busy: $r.busy}' \
| jq -s -r 'group_by(.c) | map({c: .[0].c, total: length,
online: ([.[]|select(.status=="online")]|length),
busy: ([.[]|select(.busy==true)]|length)}) | sort_by(.c) | .[]
| [.c, (.total|tostring), (.online|tostring), (.busy|tostring)] | @tsv' \
| (printf "pool\ttotal_runners\tonline\tbusy\n"; cat) | column -t -s$'\t'
```

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Step 3's runner-availability query fans out over ALL matching normalized labels (unique | .[]) instead of picking one canonical pool label per runner, so a single runner with multiple qualifying labels (pool, cluster:* alias, multi-node subset, and its own per-runner name label) gets counted in 3–4 different pool rows in the output table. This inflates total/online/busy counts and fabricates bogus rows (e.g. h100-dgxc-slurm) that don't correspond to any real pool; fix by picking a single canonical label per runner (e.g. first // empty, as Step 2 already does).

Extended reasoning...

The bug: Step 3's jq pipeline computes, per runner, the set of all normalized labels that match the broad prefix regex ^(cluster:)?(b200|b300|h100|h200|gb200|gb300|mi300x|mi325x|mi355x), then does unique | .[] — emitting one {c, status, busy} record for every surviving label rather than choosing a single canonical pool label. The subsequent group_by(.c) then treats each of those records as an independent runner-in-a-pool, so one physical runner ends up counted in several different "pool" rows of the final table.

Why this actually happens: configs/runners.yaml shows real runners are registered with multiple simultaneous labels — a pool label (h100), a multi-node subset label for some runners (h100-multinode), a cluster alias (cluster:h100-dgxc), and the runner's own unique name label (h100-dgxc-slurm_16). All of these pass the regex above because it's a substring/prefix test, not a full match. After the two sub() normalizations (sub("^cluster:";""), sub("_\\d+$";"")), these collapse to four distinct strings for the same runner: h100, h100-dgxc, h100-dgxc-slurm, and h100-multinode. Two of those (h100-dgxc and h100-dgxc-slurm) are not real pool names at all — they're artifacts of stripping the cluster: prefix and the runner's numeric suffix.

Step-by-step proof (using runner h100-dgxc-slurm_16, which is online and carries labels h100, h100-multinode, cluster:h100-dgxc, h100-dgxc-slurm_16 per configs/runners.yaml):

  1. .labels[].name yields: h100, h100-multinode, cluster:h100-dgxc, h100-dgxc-slurm_16 (plus default labels like self-hosted which fail the regex and are dropped).
  2. select(test(...)) keeps all four SKU-prefixed labels.
  3. sub("^cluster:";"") turns cluster:h100-dgxc into h100-dgxc.
  4. sub("_\\d+$";"") turns h100-dgxc-slurm_16 into h100-dgxc-slurm.
  5. unique now holds 4 distinct strings: ["h100", "h100-dgxc", "h100-dgxc-slurm", "h100-multinode"].
  6. .[] | {c: ., status: $r.status, busy: $r.busy} emits 4 separate records for this single physical runner.
  7. After jq -s | group_by(.c), this one runner contributes +1 to the total/online count in FOUR rows of the output table: h100, h100-dgxc, h100-dgxc-slurm, and h100-multinode — two of which (h100-dgxc, h100-dgxc-slurm) are not real pools in configs/runners.yaml at all.

I reproduced this exact behavior by piping the runner's label set through the Step 3 jq expression, confirming it yields 4 rows for one runner.

Contrast with the rest of the file: Step 1 (line 24) explicitly filters out per-runner name labels via select(test("...|_\\d+$") | not). Step 2 (line 42) picks a single canonical label per job via | first // empty. Step 3 is the outlier — it neither filters out the per-runner name label nor reduces to one label, so it's the only one of the three queries that multi-counts. This also directly contradicts the file's own Caveats section (lines 71-75), which states the sub() calls exist to "normalize" label shapes, not to multiply-count a runner across several pool buckets.

Impact: Step 3 is described as "the why behind queue times" — its whole purpose is giving an operator accurate total/online/busy counts per pool to diagnose queue pressure. As written, it will, on every invocation, inflate counts for any runner carrying more than one qualifying label (which per configs/runners.yaml is most runners — anything with a cluster:* alias or multi-node subset label) and fabricate nonexistent pool rows like h100-dgxc-slurm. That's actively misleading for its stated diagnostic purpose.

Fix: Change unique | .[] to pick one canonical label per runner, e.g. mirror Step 2's | first // empty, or add the same per-runner-name-label exclusion Step 1 uses (select(test("_\\d+$") | not)) before taking first.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in a355cdd — runner bucketing now comes from configs/runners.yaml pool membership (matched by runner name) instead of label fan-out: one runner counts once per configured pool, bogus rows like h100-dgxc-slurm are gone, and all configured pools now appear. / 已在 a355cdd 修复:runner 侧的池归属改为以 configs/runners.yaml 的成员配置为准(按 runner 名称匹配),不再按标签扇出 —— 同一 runner 只按配置计入对应池,h100-dgxc-slurm 之类的伪池行已消除,所有已配置的池都会显示。

@JordanNanos

Copy link
Copy Markdown
Collaborator Author

The Step 2 summary now includes runner capacity alongside job counts, so saturation vs pool-outage is visible at a glance. Fresh sample (note the b200* fleet currently has 0 runners online while 10 jobs sit queued — a pool-down situation, not a slow queue):

pool       runners_online  runners_busy  jobs_active  jobs_queued
b200-dgxc  0               0             0            10
gb200-nv   3               3             3            9
gb300-nv   3               3             3            7
h200-dgxc  14              8             8            0
b300-nv    17              2             2            0

(All-zero rows are filtered as noise.) Interpretation rules are documented in the command file: a self-hosted runner agent runs exactly one job at a time, so busy == online + queued > 0 = saturated pool; online == 0 + queued > 0 = pool down; busy > active = stuck/org-scoped runners.

中文:第二步汇总表现已加入 runner 容量维度,可一眼区分“池饱和”与“池宕机”。上方为最新示例 —— 注意 b200* 集群当前 0 台 runner 在线,却有 10 个任务在排队,这属于池宕机而非排队缓慢。判读规则已写入命令文件:每个自托管 runner agent 同一时刻只运行一个任务,因此 busy == onlinequeued > 0 表示池饱和;online == 0queued > 0 表示池宕机;busy > active 表示 runner 状态卡死或被组织内其他仓库占用。全零行已过滤。

…nate run lists

Address review feedback on PR #2270:

- Add --paginate to the runs-listing calls (previously silently capped at
  the first page, dropping the oldest/longest-waiting runs in busy periods).
- Bucket runners by configs/runners.yaml pool membership (matched by runner
  name) instead of fanning out over every matching label: one runner no
  longer counts toward 3-4 pool rows, and bogus rows derived from per-runner
  name labels (e.g. h100-dgxc-slurm) can no longer appear. This also surfaces
  every configured pool (mi300x-tw, mi325x-tw, h100-multinode, *-disagg, ...).
- Document that gh api --jq does not pass jq --arg, the demand-vs-capacity
  bucketing split, and the shared-membership reading of busy > active.

中文:处理 PR #2270 的评审意见:

- 为列出工作流运行的请求补上 --paginate(此前只取第一页,繁忙时段会静默
  丢弃最老、等待最久的运行)。
- runner 侧的池归属改为以 configs/runners.yaml 的成员配置为准(按 runner
  名称匹配),不再按标签扇出:同一 runner 不会被重复计入 3-4 个池行,
  由 runner 名称标签衍生的伪池行(如 h100-dgxc-slurm)也不会再出现。
  同时所有已配置的池(mi300x-tw、mi325x-tw、h100-multinode、*-disagg 等)
  都会显示。
- 补充说明:gh api --jq 不支持透传 jq --arg、需求侧(任务标签)与容量侧
  (runners.yaml 成员)的分桶口径,以及共享成员池下 busy > active 的解读。
@JordanNanos

Copy link
Copy Markdown
Collaborator Author

Sample output of /ci-queue-times (run 2026-07-18 16:18 UTC, commit a355cdd):

Step 2 — per-pool summary:

pool            runners_online  runners_busy  jobs_active  jobs_queued
b200-multinode  0               0             0            12
gb200-nv        3               3             3            9
h200-dgxc       14              14            14           4
mi355x-amds     9               8             6            4
gb300-nv        3               3             3            3
b200-dgxc       8               8             8            2
mi355x-disagg   3               2             2            2
b200            8               8             0            1
b300-nv         17              14            14           0
b200-dsv4       8               8             0            0
b300            17              14            0            0
b300-cw         5               0             0            0
b300-p1         5               5             0            0
gb200           3               3             0            0
gb300           3               3             0            0
h100            6               0             0            0
h100-cw         2               0             0            0
h100-dgxc       4               0             0            0
h100-multinode  4               0             0            0
h200            17              14            0            0
h200-cw         2               0             0            0
h200-multinode  3               3             0            0
h200-nb         1               0             0            0
mi300x          9               0             0            0
mi300x-amds     9               0             0            0
mi300x-disagg   3               0             0            0
mi300x-tw       2               0             0            0
mi325x          9               0             0            0
mi325x-amds     10              0             0            0
mi325x-disagg   7               0             0            0
mi325x-tw       3               0             0            0
mi355x          9               8             0            0

Step 3 — active jobs (runtime so far):

b200-dgxc      56 min   agentic / (vllm/vllm-openai:nightly-dev-x86_64-cu13.0.1-90  29639082864
b200-dgxc      56 min   agentic / (vllm/vllm-openai:nightly-dev-x86_64-cu13.0.1-90  29639082864
b200-dgxc      56 min   agentic / (vllm/vllm-openai:nightly-dev-x86_64-cu13.0.1-90  29639082864
b200-dgxc      56 min   agentic / (vllm/vllm-openai:nightly-dev-x86_64-cu13.0.1-90  29639082864
b200-dgxc      56 min   agentic / (vllm/vllm-openai:nightly-dev-x86_64-cu13.0.1-90  29639082864
b200-dgxc      55 min   sweep (deepep-v2, deepep-v2, b200-dgxc-deepep-v2-deepseek-  29632497477
b200-dgxc      55 min   sweep (deepep-v2, deepep-v2, b200-dgxc-deepep-v2-deepseek-  29632497477
b200-dgxc      55 min   sweep (deepep-v2, deepep-v2, b200-dgxc-deepep-v2-deepseek-  29632497477
b300-nv        12 min   agentic eval / (lmsysorg/sglang:v0.5.15.post1-cu130, nvidi  29651235293
b300-nv        12 min   agentic / (lmsysorg/sglang:v0.5.15.post1-cu130, nvidia/GLM  29651235293
b300-nv        12 min   agentic / (lmsysorg/sglang:v0.5.15.post1-cu130, nvidia/GLM  29651235293
b300-nv        12 min   agentic / (lmsysorg/sglang:v0.5.15.post1-cu130, nvidia/GLM  29651235293
b300-nv        12 min   agentic / (lmsysorg/sglang:v0.5.15.post1-cu130, nvidia/GLM  29651235293
b300-nv        12 min   agentic / (lmsysorg/sglang:v0.5.15.post1-cu130, nvidia/GLM  29651235293
b300-nv        12 min   agentic / (lmsysorg/sglang:v0.5.15.post1-cu130, nvidia/GLM  29651235293
b300-nv        12 min   agentic / (lmsysorg/sglang:v0.5.15.post1-cu130, nvidia/GLM  29651235293
b300-nv        12 min   agentic / (lmsysorg/sglang:v0.5.15.post1-cu130, nvidia/GLM  29651235293
b300-nv        12 min   agentic / (lmsysorg/sglang:v0.5.15.post1-cu130, nvidia/GLM  29651235293
b300-nv        12 min   agentic / (lmsysorg/sglang:v0.5.15.post1-cu130, nvidia/GLM  29651235293
b300-nv        12 min   agentic / (lmsysorg/sglang:v0.5.15.post1-cu130, nvidia/GLM  29651235293
b300-nv        12 min   agentic / (lmsysorg/sglang:v0.5.15.post1-cu130, nvidia/GLM  29651235293
b300-nv        12 min   agentic / (lmsysorg/sglang:v0.5.15.post1-cu130, nvidia/GLM  29651235293
gb200-nv       257 min  multi-node agentic / (vllm/vllm-openai:nightly-dev-arm64-c  29632307243
gb200-nv       246 min  multi-node agentic / (vllm/vllm-openai:nightly-dev-arm64-c  29632307243
gb200-nv       245 min  multi-node agentic / (vllm/vllm-openai:nightly-dev-arm64-c  29632307243
gb300-nv       381 min  multi-node agentic / (vllm/vllm-openai:nightly-dev-arm64-c  29639451578
gb300-nv       31 min   multi-node agentic / (vllm/vllm-openai:nightly-dev-arm64-c  29639451578
gb300-nv       19 min   multi-node agentic / (vllm/vllm-openai:nightly-dev-arm64-c  29639451578
h200-dgxc      22 min   agentic / (lmsysorg/sglang:v0.5.15.post1-cu130, zai-org/GL  29650948411
h200-dgxc      22 min   agentic / (lmsysorg/sglang:v0.5.15.post1-cu130, zai-org/GL  29650948411
h200-dgxc      22 min   agentic / (lmsysorg/sglang:v0.5.15.post1-cu130, zai-org/GL  29650948411
h200-dgxc      21 min   agentic / (lmsysorg/sglang:v0.5.15.post1-cu130, zai-org/GL  29650948411
h200-dgxc      21 min   agentic / (lmsysorg/sglang:v0.5.15.post1-cu130, zai-org/GL  29650948411
h200-dgxc      21 min   agentic / (lmsysorg/sglang:v0.5.15.post1-cu130, zai-org/GL  29650948411
h200-dgxc      21 min   agentic / (lmsysorg/sglang:v0.5.15.post1-cu130, zai-org/GL  29650948411
h200-dgxc      21 min   agentic / (lmsysorg/sglang:v0.5.15.post1-cu130, zai-org/GL  29650948411
h200-dgxc      20 min   agentic / (lmsysorg/sglang:v0.5.15.post1-cu130, zai-org/GL  29650948411
h200-dgxc      20 min   agentic / (lmsysorg/sglang:v0.5.15.post1-cu130, zai-org/GL  29650948411
h200-dgxc      20 min   agentic / (lmsysorg/sglang:v0.5.15.post1-cu130, zai-org/GL  29650948411
h200-dgxc      20 min   agentic / (lmsysorg/sglang:v0.5.15.post1-cu130, zai-org/GL  29650948411
h200-dgxc      20 min   agentic / (lmsysorg/sglang:v0.5.15.post1-cu130, zai-org/GL  29650948411
h200-dgxc      0 min    agentic / (lmsysorg/sglang:v0.5.15.post1-cu130, zai-org/GL  29650948411
mi355x-amds    2 min    agentic / (lmsysorg/sglang-rocm:v0.5.15.post1-rocm720-mi35  29651589976
mi355x-amds    1 min    agentic / (lmsysorg/sglang-rocm:v0.5.13.post1-rocm720-mi35  29651566222
mi355x-amds    1 min    agentic / (lmsysorg/sglang-rocm:v0.5.13.post1-rocm720-mi35  29651566222
mi355x-amds    1 min    agentic / (lmsysorg/sglang-rocm:v0.5.13.post1-rocm720-mi35  29651566222
mi355x-amds    1 min    agentic / (lmsysorg/sglang-rocm:v0.5.13.post1-rocm720-mi35  29651566222
mi355x-amds    1 min    agentic / (lmsysorg/sglang-rocm:v0.5.13.post1-rocm720-mi35  29651566222
mi355x-disagg  20 min   multi-node 8k1k / (vllm/vllm-openai-rocm:nightly-2afa3f7e9  29650962601
mi355x-disagg  20 min   multi-node 8k1k / (vllm/vllm-openai-rocm:nightly-2afa3f7e9  29650962601

Step 4 — queued jobs (wait so far):

b200            34 min   canary / (vllm/vllm-openai:v0.25.0, moonshotai/Kimi-K2.5,   29650514816
b200-dgxc       412 min  agentic / (vllm/vllm-openai:nightly-dev-x86_64-cu13.0.1-90  29639082864
b200-dgxc       412 min  agentic / (vllm/vllm-openai:nightly-dev-x86_64-cu13.0.1-90  29639082864
b200-multinode  28 min   multi-node 8k1k / (vllm/vllm-openai:cu129-nightly-8e981630  29650707821
b200-multinode  28 min   multi-node 8k1k / (vllm/vllm-openai:cu129-nightly-8e981630  29650707821
b200-multinode  28 min   multi-node 8k1k / (vllm/vllm-openai:cu129-nightly-8e981630  29650707821
b200-multinode  28 min   multi-node 8k1k / (vllm/vllm-openai:cu129-nightly-8e981630  29650707821
b200-multinode  28 min   multi-node eval / (vllm/vllm-openai:cu129-nightly-8e981630  29650707821
b200-multinode  28 min   multi-node eval / (vllm/vllm-openai:cu129-nightly-8e981630  29650707821
b200-multinode  28 min   multi-node 8k1k / (vllm/vllm-openai:cu129-nightly-8e981630  29650707821
b200-multinode  28 min   multi-node eval / (vllm/vllm-openai:cu129-nightly-8e981630  29650707821
b200-multinode  28 min   multi-node eval / (vllm/vllm-openai:cu129-nightly-8e981630  29650707821
b200-multinode  28 min   multi-node 8k1k / (vllm/vllm-openai:cu129-nightly-8e981630  29650707821
b200-multinode  28 min   multi-node eval / (vllm/vllm-openai:cu129-nightly-8e981630  29650707821
b200-multinode  28 min   multi-node eval / (vllm/vllm-openai:cu129-nightly-8e981630  29650707821
gb200-nv        649 min  multi-node agentic / (vllm/vllm-openai:nightly-dev-arm64-c  29632307243
gb200-nv        649 min  multi-node agentic / (vllm/vllm-openai:nightly-dev-arm64-c  29632307243
gb200-nv        649 min  multi-node agentic / (vllm/vllm-openai:nightly-dev-arm64-c  29632307243
gb200-nv        649 min  multi-node agentic / (vllm/vllm-openai:nightly-dev-arm64-c  29632307243
gb200-nv        649 min  multi-node agentic / (vllm/vllm-openai:nightly-dev-arm64-c  29632307243
gb200-nv        649 min  multi-node agentic / (vllm/vllm-openai:nightly-dev-arm64-c  29632307243
gb200-nv        649 min  multi-node agentic / (vllm/vllm-openai:nightly-dev-arm64-c  29632307243
gb200-nv        649 min  multi-node agentic / (vllm/vllm-openai:nightly-dev-arm64-c  29632307243
gb200-nv        649 min  multi-node agentic / (vllm/vllm-openai:nightly-dev-arm64-c  29632307243
gb300-nv        400 min  multi-node agentic / (vllm/vllm-openai:nightly-dev-arm64-c  29639451578
gb300-nv        400 min  multi-node agentic / (vllm/vllm-openai:nightly-dev-arm64-c  29639451578
gb300-nv        400 min  multi-node agentic / (vllm/vllm-openai:nightly-dev-arm64-c  29639451578
h200-dgxc       22 min   agentic / (lmsysorg/sglang:v0.5.15.post1-cu130, zai-org/GL  29650948411
h200-dgxc       22 min   agentic / (lmsysorg/sglang:v0.5.15.post1-cu130, zai-org/GL  29650948411
h200-dgxc       22 min   agentic / (lmsysorg/sglang:v0.5.15.post1-cu130, zai-org/GL  29650948411
h200-dgxc       22 min   agentic / (lmsysorg/sglang:v0.5.15.post1-cu130, zai-org/GL  29650948411
mi355x-amds     1 min    agentic / (lmsysorg/sglang-rocm:v0.5.13.post1-rocm720-mi35  29651566222
mi355x-amds     1 min    agentic / (lmsysorg/sglang-rocm:v0.5.13.post1-rocm720-mi35  29651566222
mi355x-amds     1 min    agentic / (lmsysorg/sglang-rocm:v0.5.13.post1-rocm720-mi35  29651566222
mi355x-amds     1 min    agentic eval / (lmsysorg/sglang-rocm:v0.5.13.post1-rocm720  29651566222
mi355x-disagg   20 min   multi-node eval / (vllm/vllm-openai-rocm:nightly-2afa3f7e9  29650962601
mi355x-disagg   20 min   multi-node eval / (vllm/vllm-openai-rocm:nightly-2afa3f7e9  29650962601

中文:以上为 /ci-queue-times 命令(a355cddf 版本)于 2026-07-18 16:18 UTC 的完整实际输出。第二步汇总表按池展示了 runner 在线数/忙碌数与任务活跃数/排队数;第三步为正在运行的任务及已运行时长;第四步为排队中的任务及已等待时长。从本次快照可见:b200-multinode 无在线 runner 却积压了 12 个排队任务(池宕机);gb200-nv 排队最久(约 649 分钟);h200-dgxc 已饱和(14/14 忙碌,另有 4 个排队);mi355xmi355x-disagg 的忙碌数大于活跃数,说明其 runner 正在服务其他池的任务。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

1 participant