8 核只用了 1 个?CNB 云构建 CPU 并发调优从串行到并行

2026-07-05

问题:配置不对劲

最近在 CNB(腾讯云)上调 GPU 并发时配过一次 CI_VIDEO_CONCURRENT=3CI_BATCH_SIZE=32。但 CPU 环境的配置一直是很久以前从一个小内存机器上搬过来的——没改过。

直到有天心血来潮看了一眼 CPU workspace 的 .cnb.yml

env:
  CI_DEVICE: cpu
  CI_BATCH_SIZE: "4"
  CI_VIDEO_CONCURRENT: "1"

一个 CPU 8 核的机器,concurrent=1,正在串行处理视频。

再一查文档——CNB 默认 CPU Dev Workspace 是 8 核 16GB。等于手里拿了 8 条车道但只开了 1 条。

对比:GPU 配置是好的坐标系

同样工程,GPU 环境的配置完全不一样:

参数 GPU CPU(改前) CPU(改后目标)
CI_VIDEO_CONCURRENT 3 1 2
CI_BATCH_SIZE 32 4 8
cpus (runner) 8 未指定 8

GPU 并发数是 CPU 的 3 倍,batch 是 8 倍。说明 CPU 配置不是”本来就该这么小”,而是从旧环境迁移时没调。

为什么 CPU 也能并行

这个 CI 脚本的核心逻辑是:每个视频独立下载→处理→上传。各个视频之间没有共享状态,天然适合并行。

max_concurrent = int(os.environ.get("CI_VIDEO_CONCURRENT", "1"))
batch_size = os.environ.get("CI_BATCH_SIZE", "4" if device == "cpu" else "8")

with ThreadPoolExecutor(max_workers=max_concurrent, ...) as executor:
    for video in pending_videos:
        executor.submit(process_single_video, video, batch_size)

关键判断:

  • 并发(concurrent:开几个线程并行处理视频。每个线程独立跑一个 YOLO 推理 subprocess,各占约 4 核。2 个并发正好用满 8 核
  • 批次(batch:单视频内攒多少帧再做一次批量推理。batch 越大,单位帧的推理成本越低
  • CPU 核数(cpus:不显式声明的话,CNB 调度器可能给更少的核

所以最终只改了三个参数:

# 改前
CI_BATCH_SIZE: "4"
CI_VIDEO_CONCURRENT: "1"
# runner: 无 cpus

# 改后
CI_BATCH_SIZE: "8"
CI_VIDEO_CONCURRENT: "2"
runner:
  tags: cnb:arch:amd64
  cpus: 8

提交时写了这么一行:

git commit -m "opt(cpu): concurrent 1→2, batch 4→8 (8 core utilization)"

踩坑记录

1. 双 Remote 推错仓库

本地仓库配了 2 个 remote:

  • origin → cnb-workspace-test(目标仓库)
  • new-origin → cnb-video-pipeline(历史遗留)

git push origin dev-cpu 推对了仓库,但本地分支没关联上游,git branch -vv 不显示追踪关系。差点推错。

解决方法:git ls-remote 验证 SHA 一致性,然后 git remote remove new-origin 清理多余 remote。

git ls-remote origin dev-cpu          # → 939e69e(新 commit ✓)
git ls-remote new-origin dev-cpu      # → d024579(旧 commit,没推到这里 ✓)

2. 本地 master 落后远程几个月

另一个工程 cnb-video-pipeline 的远程 master 已经统一架构了(用 api_trigger_cpu/cpu-processor 标签区分环境而非分支),但本地 master 还是初始提交。查文件时 git show master:.cnb.yml 直接报错。

解决方法:先 git fetch origin master,再用 git ls-tree --name-only origin/master 确认远程文件,然后 git checkout master && git pull origin master 同步。

先在 git fetch 之后再下结论——这是一个反复被纠正的经验,但确实容易忘。

3. 两处 CPU 配置需要同步

cnb-video-pipeline 工程的 .cnb.yml 中有两处涉及 CPU 配置:

  1. api_trigger_cpu(CI 构建触发入口)
  2. cpu-processor(Workspace 开发环境)

两处都是 CPU 环境,改了第一个忘了第二个就麻烦了。改完后 grep 确认全覆盖。

4. 推送被远程拒绝

git push origin dev-cpu! [rejected] dev-cpu → dev-cpu (fetch first)。远程有本地没有的提交——之前在别处直接改了远程。

解决:git pull origin dev-cpu --rebase 变基后重新推送。

最终结果

两个工程的并行配置都从 1 串行调到了 2 并行:

工程 改前 concurrent 改后 改前 batch 改后 cpus
cnb-test 1 2 4 8 未设→8
cnb-video-pipeline 1 2 4 8 2→8

同时把 cnb-video-pipeline 从 3 分支(dev-cpu, dev-gpu, master)整理为单 master 分支——远程 master 已统一架构,不再需要独立分支。

可复用的经验

  1. CI 平台的 CPU 资源往往比预期的多。 文档上写着 8 核,但默认配置保守,不等于真正拿到了 8 核。
  2. cpus 一定要显式声明。 CNB 不设 cpus 可能会走调度器的默认值,而不是真正的 8 核。
  3. batch 和 concurrent 是两回事。 一个控制单视频内部的帧批量,一个控制多视频之间的并行度,需要独立调优。
  4. GPU 配置是好的参考坐标系。 如果你有 GPU 环境的参数,可以反推 CPU 的合理范围——GPU 对并行度的要求更高,CPU 按比例降低就能得到一个安全的初始值。
  5. 远程验证用 git ls-remote git push 的输出可能让人误以为推成功了,git ls-remote 返回 SHA 签名——确认才是硬道理。

总结

这次调优本质上只干了三件事:把 concurrent 从 1 改成 2,batch 从 4 改成 8,加上 cpus: 8。没有改代码逻辑,没有引入新框架,纯配置改动。

有时候优化就是”发现已经有的资源,让代码真正用上它”。