原理与机制¶
读者:会用工具、但想知道"为什么这样设计"的人。 前置:跑通过一次前仿(见 tutorial-first-sim.md)。 读完能做什么:理解白名单、层次网名、srun 崩溃、存储分层这四件事背后的道理。 环境锚点:Virtuoso IC617 + Spectre 15.10 + Slurm;核实日期 2026-10-13。
三十秒版¶
这篇回答四个"为什么":为什么要配白名单、为什么子层次节点选不了、 为什么加了 srun 就崩、为什么结果要分三层存。每个都按"解决什么问题 → 怎么运作 → 为什么 → 何时失效"讲。
一、为什么要配保存白名单¶
它解决什么问题¶
不配的话,仿真器默认把电路里每个节点的波形都存下来,盘会满。 本项目未裁剪时 200 个点 × 60 µs 估计约 780 GB——整个集群都装不下。
怎么运作¶
你在 Outputs Setup 表勾 Save ──► 网表写出 save VCTL REF VCOCK FB ──► Spectre 只写这四路
(名单) (规矩:save=selected) (其余不写盘)
体积的算式:
体积 = 保存信号数 × 采样点数(时长 ÷ strobeperiod) × 每点字节
三个因子就是三个旋钮:少存信号、少存时间点、换更省的格式。
为什么这么设计¶
波形是"时间 × 节点 × 精度"的三维数据。其中节点数最容易失控,
所以工具给了"只存点名的"这一层闸门(selected),而不是让你事后删。
实测(本项目,2026-10-12)¶
| 配置 | 单点 psf | 6 点目录 |
|---|---|---|
| 无白名单,1 µs | 8.5 MB | 55 MB |
| 4 路白名单,1 µs | 0.27 MB | 5.5 MB |
| 4 路白名单,10 µs | 4.4 MB | 32 MB |
白名单把单点压约 31×;目录总量只降约 10×,因为 netlist、日志等固定开销不随白名单变。
什么情况下失效¶
- 名单为空时
selected退化成"全存所有节点"——这是最坑的一点,配了等于没配。 strobeperiod抽稀(采样间隔调大)只能用于慢节点/包络,不能用于 VCO 高频波形,会严重欠采样。compression=yes在本环境实测反而变大(×1.73),别开。
二、为什么子层次里的节点选不了¶
它解决什么问题¶
你想存"div8 的输出",但在信号列表里,div8 内部节点是灰的,选不了。
怎么运作¶
仿真器按顶层网表保存,顶层网表里只有顶层 net 有名字:
XDIV (VCOCK GND FB VDD) div8
└──── 括号里是 div8 的四个顶层连接,第 3 个 FB 就是 div8 的输出
所以"某模块的输出"要认顶层连接的网名,这里就是 FB。
为什么这么设计¶
子层次内部节点的名字在顶层不唯一(两个模块里都可以有一个 out),
没法直接指名保存,所以工具只让你选顶层 net。
什么情况下失效¶
- 子 cell 的端口名大小写与子 schematic 必须逐字一致,否则层次连接为空,
FB这种顶层名也就不存在了。 - 顶层 net 名带前导
/(如/VCTL);不带/的多半不是顶层 net。
三、为什么加了 srun,Spectre 就崩¶
它解决什么问题¶
ADE-XL 把每个仿真点丢给 Slurm 集群跑,但作业一启动就报错、跑不起来。
怎么运作¶
ADE-XL ──► Job Policy = Command ──► srun -N1 -n1 -c1 -p long --mpi=none ./runICRP
│
srun 默认会往进程里塞 MPI 环境变量(PMI_*)
│
Spectre 看到 PMI_* 以为要跑 MPI,初始化失败 → 崩
报错长这样:[cli_0]: Unable to write to PMI_fd 或 Fatal error in MPI_Init。
加 --mpi=none 告诉 srun"别塞这些变量",就好了。
为什么这么设计 / 为什么会踩¶
本集群的 Slurm 配置里 MpiDefault = pmi2(上游出厂默认是 none),
所以这道坎是本集群特有的——换一套默认 none 的集群就不会遇到。
什么情况下失效¶
- 必须用
srun(前台阻塞),不能用sbatch:ADE-XL 靠本地代理进程推断作业状态、发SIGTERM。 - 失败会留
SE/JobHeldUser残骸,累积到一定量后 ADE-XL 会停止派发(清掉即恢复)。 - 派发粒度是一点一核(
-N1 -n1 -c1);单点用多核(+mt=4)对小电路几乎没有收益。
四、为什么结果和日志要分开存¶
它解决什么问题¶
波形大、寿命短;日志小、寿命长;设计源要永久留。放一起会互相拖累盘。
怎么运作¶
| 层 | 路径 | 性质 | 放什么 |
|---|---|---|---|
| Tier1 | /projects/... |
NFS,持久、可备份 | 设计源、netlist、日志、配置、裁剪后的结果 |
| Tier0 | /mnt/lustre/scratch/users/<你>/... |
Lustre,共享临时,30 天老化 | 仿真波形、大中间产物、作业 workdir |
| 本地 | $TMPDIR(节点本地盘,不共享) |
不共享 | 作业级临时(脚本别放这里) |
为什么这么设计¶
三类东西的容量与生命周期完全不同:波形会撑爆盘但几天后就没用, 日志很小但要长期查,设计源必须永久留。用一块盘扛三种需求,必然有一头被牺牲。
什么情况下失效¶
- Lustre 30 天老化:要长期保留的结果必须 stage-out 回
/projects。 - EDA 编译产物默认落在当前目录,作业脚本要显式
cd "$TMPDIR"或指定路径。 - 判"能不能写"别用
test -w(曾误报),要真实写一个文件验证。
五、为什么作业数上不去(三道闸门)¶
它解决什么问题¶
明明机器闲着,作业却排着队;改了参数并发数变了,却不知道为什么。
怎么运作¶
能同时跑几个作业,由三道闸门里最紧的那道决定:
第一道 配额(逻辑) QOS 的 MaxJobsPerUser ← 管理员设
第二道 内存(申请) 节点内存 ÷ 每个作业 --mem
第三道 核数(物理) 节点核数 × 节点数
并发 = 三者取最小
在本机实测(2026-10-13,198 点批跑)¶
| 配置 | 第一道 | 第二道 | 第三道 | 实际并发 |
|---|---|---|---|---|
-p long、--mem=2G |
10 | 21 | 24 | 10 |
-p regression、--mem=2G |
200 | 21 | 24 | 21 |
-p regression、--mem=1G |
200 | 42 | 24 | 24 |
读法:先换分区解开配额,再降 --mem 解开内存,最后才碰到物理核数这堵真墙。
怎么知道现在撞的是哪道¶
squeue 的 REASON 列直接说了:
| REASON | 撞哪道 | 对策 |
|---|---|---|
QOSMaxJobsPerUserLimit |
配额 | 换 QOS 更宽的分区(本机 regression 是 200) |
Resources |
内存或核 | 降 --mem;已到核数上限就无解 |
Priority |
排队优先级 | 等 |
为什么这么设计¶
集群多人共用:配额防一个人吃独食,内存防一个作业撑爆节点,核数就是机器的物理容量。 三件事各管一段,所以分三道闸门。
什么情况下失效¶
- 配额放大到几百,物理核数不会跟着涨——超过核数的配额是虚的。
--mem申请的是上限不是预占:--mem=1G时作业实际只用 93 MB,剩下仍被记账占位, 所以降它能提并发,但降太狠会 OOM。- 四个分区(
long/regression/compile/interactive)共用同一批节点, 换分区只换配额与时限,不换机器。
相关¶
- 怎么配:白名单见 howto-adexl.md;落层见 howto-hpc.md。
- 出事记录:见 incident.md。
- 选型:波形格式、Slurm/LSF、存储层,见 compare.md。
来源:
/home/rain/Documents/eda_tools_ins/design/docs/kb/concept.md| 最后更新:2026-10-13 01:53(由build/sync.py同步,请勿在站点侧修改)