PrimeTime 跑后端时计算节点 /tmp 被撑满
在多核或分布式后端时序分析场景中,PrimeTime(PT)会在 /tmp 下产生大量临时文件,
轻则拖慢节点,重则导致整个作业因”No space left on device”报错崩溃。
版本参考:Synopsys PrimeTime 2022.x / 2023.x
平台:CentOS 7 / RHEL 8,作业调度:IBM LSF / SGE
官方建议:节点/tmp容量 ≥ 物理内存 2 倍(如 RAM 512 GB,则 /tmp 需 ≥ 1 TB)
一、PT 临时文件的来源
PT 运行期间会在本地 /tmp 下写入多类临时文件,来源如下:
| 来源 | 说明 |
|---|---|
| 寄生参数读取(SPEF/DSPF) | PT 为加速解析会将寄生数据缓存到临时文件 |
| 多核分析内部通信 | multicore 模式下 Master 与 Worker 线程间的共享数据 |
| DMSA Slave 进程 | 分布式多场景分析(DMSA)中,Slave 在各自节点的 /tmp 写入工作数据 |
| Tcl 脚本临时变量序列化 | 部分版本会将大型内存对象序列化到磁盘以降低峰值内存 |
二、与临时目录相关的变量
PT 提供了多个变量来控制临时文件路径,但它们的作用范围和生效条件各不相同:
2.1 pt_tmp_dir(PT 应用变量 / app_var)
1
2
# 在 .synopsys_pt.setup 或 run.tcl 中设置(推荐使用 set_app_var)
set_app_var pt_tmp_dir "/tmpdata/pt_tmp/$env(USER)"
- 作用:控制 PT 在 high capacity mode 下读取寄生参数时产生的临时文件的存储位置,默认为
/tmp。 - 生效范围:仅在设置该变量的 PT 进程会话(即 Master)中生效。
- 局限:这是一个 PT 应用变量(app_var),不是 Shell 环境变量,无法通过
export传递给 Slave 进程。
验证当前值
1
2
3
printvar pt_tmp_dir
# 或
echo $pt_tmp_dir
2.2 multi_core_working_directory(PT 应用变量 / app_var)
1
set_app_var multi_core_working_directory "/tmpdata/pt_mc_work/$env(USER)"
- 作用:多核分析(
set_host_options -num_cores N)时的工作目录,存放 Worker 的日志和交换数据。 - 默认值:不设置时,默认为启动 PT 时所在的目录(即
pt_shell被调用时的当前目录)。 - 要求:必须是所有参与节点均可读写的共享路径(NFS/GPFS/Lustre 等)。
2.3 multi_scenario_working_directory(PT 应用变量 / app_var)
1
set_app_var multi_scenario_working_directory "/tmpdata/pt_dmsa_work/$env(USER)"
- 作用:DMSA 模式下 Master 与 Slave 之间的共享工作目录,存放各 scenario 的日志和中间数据。
- 默认值:不设置时,默认为启动 PT 时所在的目录(即
pt_shell被调用时的当前目录)。 - 要求:必须是网络可访问的共享路径,且 Master 和所有 Slave 都需有写权限。
2.4 TMPDIR(Shell 环境变量)
1
export TMPDIR=/tmpdata/pt_tmp/$USER
- 作用:Unix 标准临时目录变量,许多底层库(如 glibc、OpenSSL)会优先读取此变量。
- 局限:PT 自身对
TMPDIR的响应行为因版本而异,不能替代pt_tmp_dir,但同时设置可覆盖底层库的临时文件行为。
三、为什么设置了环境变量还不生效
这是最常见的困惑。以下是已知的失效原因:
3.1 变量类型混淆:PT app_var ≠ Shell 环境变量
pt_tmp_dir 是 PT 的应用变量(app_var),不是 Shell 环境变量。
1
2
3
4
5
6
7
# ❌ 错误:这样设置对 PT 无效
export pt_tmp_dir=/tmpdata/pt_tmp
setenv pt_tmp_dir /tmpdata/pt_tmp
# ✅ 正确:必须在 PT 启动时读取的脚本中用 set_app_var 设置
# .synopsys_pt.setup 或 run.tcl 中:
set_app_var pt_tmp_dir "/tmpdata/pt_tmp"
3.2 Slave 进程继承失效
在 DMSA 分布式模式下,LSF/SGE 将 Slave 作业派发到各计算节点时:
- Slave 进程独立启动,拥有独立的 PT 会话。
- Master 中
set_app_var pt_tmp_dir的设置不会自动传递到 Slave。 - 每个 Slave 都需要在其启动时的
.synopsys_pt.setup中读到该设置。
解决方案:将 pt_tmp_dir 写入所有节点都能访问的 .synopsys_pt.setup(通常放在项目共享目录或 $HOME)。
1
2
# 推荐写法(.synopsys_pt.setup)
set_app_var pt_tmp_dir "/tmpdata/pt_scratch/$env(USER)/[exec hostname]"
提示:按主机名划分子目录,避免多节点 Slave 并发写入同一目录产生冲突。
3.3 临时文件来源不止一处
即使正确设置了 pt_tmp_dir,节点 /tmp 仍然可能被写满,原因是:
- 底层库(如某些第三方 C++ solver)绕过
pt_tmp_dir,直接使用TMPDIR或硬编码/tmp。 - 操作系统层面的 tmpfs:许多 HPC 节点的
/tmp是 tmpfs(内存盘),容量默认为 RAM 的 50%,当 PT 进程内存压力大时,底层可能发生 swap 行为写入/tmp。
3.4 目录权限或路径不存在
PT 若无法写入指定的 pt_tmp_dir,通常会静默回退到 /tmp,没有任何报错提示。
1
2
3
# 确保目录存在且可写
mkdir -p /tmpdata/pt_scratch/$USER
chmod 700 /tmpdata/pt_scratch/$USER
四、推荐配置方案
4.1 单机多核场景
在 .synopsys_pt.setup(放置于项目目录或 $HOME)中:
1
2
3
4
5
# 临时文件重定向
set_app_var pt_tmp_dir "/tmpdata/pt_scratch/[exec id -un]"
# 多核工作目录(若使用 multicore)
set_app_var multi_core_working_directory "/tmpdata/pt_mc/[exec id -un]"
在 LSF 提交脚本中同步设置 Shell 层面的 TMPDIR:
1
2
3
4
5
6
7
#BSUB -J pt_run
#BSUB -n 8
export TMPDIR=/tmpdata/pt_scratch/$USER
mkdir -p $TMPDIR
pt_shell -f run.tcl
4.2 DMSA 分布式多场景
1
2
3
4
5
# master run.tcl
set_app_var multi_scenario_working_directory "/nfs_shared/pt_dmsa/$env(USER)"
# 各 slave 的 .synopsys_pt.setup(放在 $HOME 或项目共享 HOME_PT_SETUP 路径)
set_app_var pt_tmp_dir "/tmpdata/pt_scratch/$env(USER)/[exec hostname]"
LSF 提交脚本同步设置:
1
2
3
4
5
6
7
#BSUB -J pt_dmsa
#BSUB -n 1 # master
export TMPDIR=/tmpdata/pt_scratch/$USER
mkdir -p $TMPDIR
# 确保 HOME 中的 .synopsys_pt.setup 可被 slave host 读取
pt_shell -f dmsa_run.tcl
4.3 节点级批量初始化(系统管理员)
若无法修改用户脚本,系统管理员可在节点的 compute 节点部署 prologue 脚本(LSF PRE_EXEC):
1
2
3
4
#!/bin/bash
# /etc/lsf/prologue.sh
mkdir -p /tmpdata/pt_scratch/$LSB_JOBUSER
chown $LSB_JOBUSER /tmpdata/pt_scratch/$LSB_JOBUSER
并通过 module 文件为用户自动设置:
1
2
# module file for primetime
setenv TMPDIR /tmpdata/pt_scratch/$env(USER)
五、诊断方法
当不确定 PT 实际在哪里写临时文件时,可以使用如下方法排查:
1
2
3
4
5
6
7
8
9
10
11
# 方法1:实时监控 /tmp 中 PT 进程写入的文件(按 PID 过滤)
PID=$(pgrep -f pt_shell | head -1)
lsof -p $PID | grep /tmp
# 方法2:strace 追踪文件创建(适合开发环境,不建议生产环境)
strace -f -e trace=openat,creat -o /tmp/pt_strace.log pt_shell -f run.tcl 2>&1 &
# 方法3:在 PT 内部检查变量值
# 在 pt_shell 交互模式中:
printvar pt_tmp_dir
printvar multi_core_working_directory
六、变量速查表
| 变量 | 类型 | 默认值 | 是否传播到 Slave | 作用范围 |
|---|---|---|---|---|
pt_tmp_dir |
PT app_var | /tmp |
❌ 需手动配置到每个 Slave 的 .synopsys_pt.setup |
high capacity 模式下寄生参数临时文件 |
multi_core_working_directory |
PT app_var | PT 启动时的工作目录 | ❌ 需配置为所有节点可访问的共享路径 | 多核分析 Worker 工作目录 |
multi_scenario_working_directory |
PT app_var | PT 启动时的工作目录 | ❌ 需配置为所有节点可访问的共享路径 | DMSA 全场景共享工作目录 |
TMPDIR |
Shell 环境变量 | /tmp |
取决于 LSF/SGE 的 -env 配置 |
底层 C 库及第三方库临时文件 |
七、总结
PT 计算节点 /tmp 被撑满的核心原因在于:
pt_tmp_dir是 PT app_var,不是 Shell 环境变量,无法通过export/setenv生效,必须用set_app_var写入 PT 启动时读取的.synopsys_pt.setup。- Slave 进程独立启动,不继承 Master 的 app_var 设置,每个 Slave 都需要自己的完整配置。
- 临时文件有多个来源,仅设置
pt_tmp_dir无法覆盖底层库的行为,需同时设置 Shell 层的TMPDIR。 - 目标路径需提前创建且用户具备写权限,否则 PT 静默回退到
/tmp。
推荐的完整方案是:在项目共享目录的 .synopsys_pt.setup 中配置所有 Tcl 路径变量,同时在 LSF/SGE 提交脚本中 export TMPDIR 并提前 mkdir -p,从两个维度同时覆盖临时文件的写入路径。