HPC¶
一、 概览¶
1. HPC的定义¶
高性能计算(High Performance Computing, HPC) 是通过聚合多个计算节点(如超级计算机或集群系统)的并行处理能力,解决大规模、高复杂度的科学、工程和商业问题的技术。其核心在于利用并行计算模型(如MPI、OpenMP)和高速网络通信,实现海量数据的高效处理与多维任务的快速执行
2. 技术框架¶
2.1 硬件层¶
- 计算节点:由多核CPU、GPU或专用加速器(如TPU)组成的并行处理单元;
- 高速网络:InfiniBand、Omni-Path等低延迟、高带宽互联技术,支撑节点间数据交换;
- 存储系统:分布式文件系统(如Lustre、GPFS)或对象存储,满足海量数据的快速读写需求。
2.2 软件栈
- 并行编程模型:MPI(消息传递接口)、OpenMP(共享内存并行)等实现任务分配与协同;
- 调度系统:Slurm、PBS等作业调度工具,管理集群资源分配;
- 优化工具:性能分析器(如Intel VTune)、编译器优化(如GCC、LLVM)提升计算效率
2.2 HPC网络类型及典型场景¶
| 网络类型 | 技术特性 | 适用场景 | 解决的核心问题 |
|---|---|---|---|
| InfiniBand | - 原生RDMA支持,延迟<1μs- 带宽400Gb/s(HDR标准)- 支持多级QoS策略 | - 气象模拟、分子动力学等科学计算- 金融高频交易实时分析 | 计算密集型任务的通信瓶颈 |
| RoCEv2以太网 | - 基于以太网的RDMA实现- 兼容传统TCP/IP网络架构- 成本低于InfiniBand | - AI训练(如千卡GPU集群)- 基因组学大数据处理 | 传统以太网无法满足HPC性能需求 |
| 二层交换网络 | - 基于MAC地址转发,延迟低至纳秒级- 无IP路由开销1 | - HPC集群内部节点间通信- 超算中心机柜内互联1 | 广播域过大导致的网络拥塞 |
| 三层路由网络 | - 跨子网通信支持- 基于IP地址的路由策略15 | - 跨数据中心的混合HPC任务(如云边协同)- 多租户资源隔离15 | 大规模集群的跨域通信需求15 |
| 共享内存网络 | - 通过NUMA架构实现内存共享- 延迟低于100ns | - 单节点多核CPU密集任务(如流体力学仿真)- 实时信号处理 | 分布式内存架构的通信开销问题 |
2.3 Lustre¶
Lustre 是专为 HPC / 超算 / EDA 场景设计的开源并行分布式文件系统,核心是元数据与数据分离、数据条带化(Stripe)、内核态、高并发、线性扩展,是芯片研发集群的标配存储方案
2.3.1 核心架构¶
Lustre 采用三层架构,所有组件通过 LNet 网络协议通信:
-
管理服务器 MGS(Management Server)
-
全局配置中心,存储所有 Lustre 文件系统的配置信息
- 客户端、MDS、OSS 启动时先连 MGS 获取配置
-
通常与 MDS 部署在同一节点,可做 HA
-
元数据服务层(MDS + MDT)
-
MDS(Metadata Server):处理文件创建 / 删除 / 权限 / 路径查找,不参与数据读写
- MDT(Metadata Target):存储元数据(文件名、目录、权限、文件布局)
- 特点:元数据与数据完全分离,避免 MDS 成为 I/O 瓶颈
-
高可用:Active-Standby 双机热备
-
数据服务层(OSS + OST)
-
OSS(Object Storage Server):负责实际数据 I/O、网络请求处理
- OST(Object Storage Target):后端存储(本地盘 / RAID / 块设备),文件数据分片存在多个 OST
-
扩展:加 OSS/OST 即可线性提升容量与带宽
-
客户端 Client
-
内核态模块,挂载后像本地目录一样使用
- 直接与 MDS(元数据)、多个 OSS(数据)并行通信
- 支持万级客户端并发访问
2.3.2 关键特性¶
-
极致性能
-
聚合带宽:数百 GB/s ~ TB/s
- 支持:数万客户端、PB~EB 级容量
-
适合:大文件、高并发、顺序读写(EDA 仿真 / 验证)
-
线性扩展
-
容量 / 带宽随 OSS/OST 数量线性增长
-
支持在线扩容,不中断业务
-
高可用 HA
-
MDS/OSS 均支持 Active-Standby 双机
- 单节点故障自动切换,业务无感知
-
自身不做数据多副本,依赖底层 RAID / 块存储保障数据安全
-
网络支持
-
支持:以太网、InfiniBand、Omni-Path
-
推荐:EDA 场景用 InfiniBand 或 100G 以太网
-
POSIX 兼容
-
完全兼容 Linux 文件系统 API,应用无需修改即可迁移
2.3.3 常用命令¶
# 查看 Lustre 文件系统整体状态
lfs check
# 查看挂载信息
lfs df -h
# 查看所有 OST 状态、使用率
lfs osts
# 查看 MDT 信息
lfs mdts
# 查看当前 stripe 策略
lfs getstripe /lustre/path
# 查看客户端连接信息
lfs client_list
# 创建目录并设置 stripe count=4, stripe_size=1M
lfs setstripe -c 4 -S 1M /lustre/project
# 对已有目录递归设置 stripe(慎用)
lfs setstripe -c 8 -S 4M /lustre/eda
# 默认 stripe 设置(新文件自动继承)
lfs setstripe -c 4 /lustre
# -c N:stripe 个数(跨 N 个 OST),-S size:块大小 1M/4M/8M/16M
# 查看文件分布在哪些 OST
lfs find /lustre/file --ost
# 查看读写带宽
lfs stats /lustre
# 清理 OST 残留对象(运维命令)
lfs ost scrub
# 挂载 MDT
mount -t lustre /dev/md0 /mnt/mdt
# 挂载 OST
mount -t lustre /dev/osd0 /mnt/ost
# 重启 lustre 服务
systemctl restart lustre
二、Slurm 调度器¶
1. 概览¶
SLURM(Simple Linux Utility for Resource Management)是专为HPC集群设计的开源作业调度系统,负责分配计算资源、管理作业队列,并监控任务执行状态
2. 核心功能¶
2.1 资源分配¶
- 动态分配:按需分配CPU、GPU、内存、节点等资源,支持独占或共享模式。
- 多租户支持:通过QoS(服务质量)和账户(Account)限制用户/组的资源使用
2.2 作业调度¶
- 优先级调度:基于公平分享(Fair-share)、作业时长、用户优先级等策略排序任务。
- 回填调度(Backfill):利用空闲资源提前运行后续作业,提升集群利用率。
2.3 作业管理¶
- 任务启停:通过
srun直接运行任务,或通过sbatch提交脚本。 - 状态监控:实时查看作业状态(Pending/Running/Failed)、资源占用及执行日志
2.4 优势总结¶
灵活的调度策略,细粒度资源控制,以及高扩展性
3. 架构与组件¶
| 组件 | 功能描述 |
|---|---|
| slurmctld | 中央控制守护进程,管理作业调度、资源分配及节点状态。 |
| slurmd | 运行在计算节点上的守护进程,执行来自slurmctld的命令(如启动任务)。 |
| slurmdbd | 数据库守护进程,存储作业历史、资源使用记录及账户信息(需配合MySQL/PostgreSQL)。 |
| sacct/sstat | 命令行工具,用于查询数据库中的作业历史及实时状态。 |
4. 场景举例¶
资源需求:128节点(每节点32核CPU + 4块GPU),运行时长48小时
#!/bin/bash
#SBATCH --job-name=climate_sim # 作业名称
#SBATCH --partition=climate # 指定队列(Partition)
#SBATCH --nodes=128 # 节点数
#SBATCH --ntasks-per-node=4 # 每节点MPI进程数
#SBATCH --cpus-per-task=8 # 每个MPI进程的CPU核数(供OpenMP使用)
#SBATCH --gres=gpu:4 # 每节点GPU数量
#SBATCH --time=48:00:00 # 最大运行时间
#SBATCH --output=sim_%j.out # 标准输出日志
#SBATCH --error=sim_%j.err # 错误日志
#SBATCH --account=atm_research # 账户名
#SBATCH --qos=high_priority # QoS策略
# 加载MPI和CUDA环境
module load openmpi/4.1.1 cuda/11.4
# 启动混合并行任务(MPI进程数为128节点×4=512,每个进程使用8线程)
srun --mpi=pmix -n 512 --cpu-bind=cores ./climate_model -i input.nml
关键参数解析
--partition:指定作业队列(如climate队列专用于气候模拟任务)。
--gres=gpu:4:每节点请求4块GPU,总计128×4=512块GPU。
--cpu-bind=cores:将OpenMP线程绑定到物理核心,减少缓存争用。
--mpi=pmix:使用PMIx库优化MPI进程间通信。
5. sbatch命令及高级选项¶
5.1 基础资源请求选项¶
| 选项 | 作用 | 示例及说明 |
|---|---|---|
--job-name=<name> |
指定作业名称(便于监控和检索) | --job-name=EDA_sim,作业在队列中显示为EDA_sim |
--nodes=<N> | -N |
请求节点数量 | --nodes=4,分配4个计算节点 |
--ntasks=<N> | -n |
请求总任务数(进程数) | --ntasks=64,启动64个MPI进程 |
--ntasks-per-node=<N> |
每节点的任务数(与--nodes联用) |
--nodes=8 --ntasks-per-node=8,总任务数=64(8×8) |
--cpus-per-task=<N> | -c |
每个任务分配的CPU核数(用于多线程任务,如OpenMP) | --cpus-per-task=4,每个任务使用4核,配合OMP_NUM_THREADS=4 |
--mem=<size> |
每个节点请求的内存总量 | --mem=64G,每个节点分配64GB内存(注意单位:G/M) |
--mem-per-cpu=<size> |
每个CPU核分配的内存 | --mem-per-cpu=4G,若--cpus-per-task=8,则总内存=32G |
--time=<duration> |
最大运行时间(超时作业会被终止) | --time=02:30:00(2小时30分钟)或--time=1-05(1天5小时) |
--partition=<name> |
指定作业提交的队列/分区 | --partition=gpu,提交到GPU专用队列 |
--account=<name> |
指定计费账户(多用户共享集群必填) | --account=eda_project |
--gres=<resource>:<N> |
请求通用资源(如GPU、FPGA) | --gres=gpu:tesla_v100:2,每节点请求2块Tesla V100 GPU |
| --dry-run | 不真正提交任务 | sbatch --dry-run -N2 --ntasks-per-node=4 -c1 job.sh |
5.2 高级资源控制选项¶
| 选项 | 作用 | 示例及说明 |
|---|---|---|
--exclusive |
独占节点资源(禁止其他任务共享节点) | 常用于需要最大化带宽或避免干扰的任务(如大规模MPI作业) |
--dependency=<type:ID> |
设置作业依赖关系 | --dependency=afterok:12345,仅在作业ID 12345成功后才启动 |
--array=<indexes> |
任务阵列提交多个相似任务 | --array=1-100%10,提交100个任务,每次最多并行10个(通过$SLURM_ARRAY_TASK_ID传递索引) |
--licenses=<name> |
请求软件许可证(需集群配置许可证管理) | --licenses=eda_sim:1,请求1个EDA仿真工具许可证 |
--constraint=<feature> |
指定节点硬件/软件特性约束 | --constraint="intel|amd",选择Intel或AMD节点;--constraint=ssd选择带SSD的节点 |
5.3 输出与日志管理¶
| 选项 | 作用 | 示例及说明 |
|---|---|---|
--output=<file> |
标准输出(stdout)重定向路径 | --output=sim_%j.log,%j会被替换为作业ID(如sim_12345.log) |
--error=<file> |
标准错误(stderr)重定向路径 | --error=sim_%j.err,可与--output合并(--output=sim_%j.out --error=sim_%j.err) |
--open-mode=append|truncate |
控制输出文件的写入方式(追加或覆盖) | --open-mode=append,日志文件追加写入(用于重启的任务) |
--mail-type=<type> |
邮件通知类型(任务状态变化时触发) | --mail-type=BEGIN,END,FAIL,任务开始、结束或失败时发送邮件 |
--mail-user=<email> |
接收通知的邮箱地址 | --mail-user=user@example.com |
5.4 任务并行与绑定选项¶
| 选项 | 作用 | 示例及说明 |
|---|---|---|
--cpu-bind=<type> |
绑定进程到CPU核(优化NUMA性能) | --cpu-bind=cores,将进程绑定到物理核(避免超线程干扰) |
--distribution=<type> |
控制进程在节点间的分布策略 | --distribution=cyclic:block,交替分配进程块到不同节点 |
--switches=<N>@<timeout> |
允许任务在节点故障时重调度到其他节点 | --switches=2@30,允许2次节点切换,每次间隔30分钟 |
6. 多租户支持:Qos与账户(account)¶
6.1 账户层级与结构¶
- 树形层级:账户支持多级嵌套(如
root.account.subaccount),实现资源逐级分配。 - 默认账户:每个用户必须属于至少一个账户,未指定时使用系统默认账户。
6.2 账户创建与关联¶
# 创建父账户(如部门级)
sacctmgr add account finance Description="Finance Department" Organization=company
# 创建子账户(如项目级)
sacctmgr add account finance.research Parent=finance Description="Research Project"
# 关联用户到账户
sacctmgr add user alice Account=finance.research
sacctmgr add user bob Account=finance.research
6.3 账户资源限制¶
- 通过 Association(关联) 定义账户的资源配额
# 限制finance.research账户的总CPU核数(MaxTRES=cpu)和作业数(MaxJobs)
sacctmgr modify account finance.research set MaxTRES=cpu=200 MaxJobs=50
- 账户级资源限制参数说明
| 参数 | 含义 | 作用 |
|---|---|---|
MaxTRESPerAccount |
账户总资源限制(如cpu=200,mem=1T) |
限制整个账户的CPU和内存总量 |
MaxJobsPerAccount |
账户同时运行的作业数上限(如10) |
防止账户内作业过度占用集群资源 |
MaxSubmitPerAccount |
账户同时提交的作业数上限(如20) |
控制账户的作业提交并发量 |
MaxWallTimePerJob |
单个作业的最大运行时间(如24:00:00) |
避免超长作业影响其他用户 |
6.4 Qos(服务质量)策略配置¶
QoS定义作业的运行策略,包括优先级、时间限制和资源限制,可与账户绑定。
# 创建高优先级QoS(如premium)
sacctmgr add qos premium Priority=1000 MaxTRESPerUser=cpu=50 GrpTRES=cpu=500
# 创建普通QoS(如normal)
sacctmgr add qos normal Priority=500 MaxWall=48:00:00 MaxTRESPerAccount=cpu=100
6.5 Qos 核心参数¶
| 参数 | 含义 | 作用 |
|---|---|---|
Priority |
QoS优先级(整数) | 数值越高,作业调度优先级越高(如高优先级作业可抢占低优先级资源) |
GraceTime |
作业降级/抢占前的宽限时间(如5:00表示5分钟) |
防止频繁抢占,允许作业在宽限期内完成关键操作 |
Preempt |
指定可被抢占的QoS(如qos1,qos2) |
允许高优先级QoS抢占当前QoS的资源 |
MaxTRESPerUser |
用户可用的最大资源(如cpu=100,mem=500G) |
限制单个用户的总CPU核数或内存使用量 |
MaxJobsPerUser |
用户同时运行的作业数上限(如4) |
防止单个用户占用过多并发作业 |
MaxSubmitPerUser |
用户同时提交的作业数上限(如6) |
控制作业提交频率,避免队列拥堵 |
MaxWallTime |
作业最大运行时间(如1-00:00:00表示1天) |
防止长期占用资源 |
6.6 关联Qos到账户¶
# 将premium QoS绑定到finance.research账户
sacctmgr modify account finance.research set QOS=premium,normal
# 允许用户使用多个QoS(默认使用最高优先级)
sacctmgr modify user alice set QOS=premium,normal
6.7 Qos覆盖规则¶
- 层级继承:子账户继承父账户的QoS,可叠加额外限制。
- 冲突解决:更小范围的限制覆盖更大范围(如用户级限制覆盖账户级)
7. Slurm调度器调度策略及应用场景 --任务调度策略¶
7.1 核心调度策略¶
| 策略 | 机制说明 | 关键参数 |
|---|---|---|
| 先进先出(FIFO) | 默认策略,按作业提交顺序分配资源,前一个作业满足后才会调度下一个。 | SchedulerType=sched/builtin |
| 回填调度(Backfill) | 允许后续作业利用空闲资源“插队”运行,前提是不影响已预留的高优先级作业。 | SchedulerParameters=backfill, bf_interval=30(调整回填检查间隔) |
| 公平共享(FairShare) | 基于账户/用户的资源使用历史动态调整优先级,避免资源垄断。 | PriorityType=priority/multifactor PriorityDecayHalfLife=7-0(权重衰减) |
| 优先级调度(Priority) | 静态优先级,通过权重直接控制作业调度顺序。 | PriorityWeightAge=1000 PriorityWeightFairshare=1000 |
| 拓扑感知调度 | 优化任务与节点物理拓扑(如NUMA、GPU NVLink)的匹配,减少通信延迟。 | SelectType=select/cons_tres SelectTypeParameters=CR_CPU_Memory |
| 分区调度(Partition) | 将集群划分为逻辑分区(如CPU/GPU分区),作业按分区提交并独立调度。 | scontrol create Partition=GPU nodes=node[1-4] |
7.2 slurm 分区节点分配策略¶
a. 默认分配策略
在SLURM调度器中,当一个分区包含多个计算节点时,默认采用块分配(Block Allocation)策略,即优先将连续的任务分配到同一节点,直到该节点资源耗尽后再转向下一个节点。具体表现为:
- 若节点资源充足(如CPU核心、内存等),作业会先占满单个节点,再分配至下一个节点;
- 若作业请求的资源超过单个节点容量,则会跨节点分配,但依然遵循最小化节点数的原则
b. 分配策略调整方案
| 调整方式 | 配置方法 | 适用场景 |
|---|---|---|
| 节点选择算法 | 在slurm.conf中修改SelectType参数: SelectType=select/cons_res |
控制资源分配粒度(节点级或核心级) |
| 任务分布模式 | 提交作业时指定--distribution参数: --distribution=block/cyclic/plane |
强制任务按块、轮询或拓扑结构分配 |
| 资源碎片优化 | 启用Gres(通用资源)插件,配置节点异构资源标签(如GPU型号) |
需精确匹配特定硬件资源的作业 |
| 负载均衡调度 | 在分区配置中启用OverSubscribe=YES,允许节点超卖资源 |
处理大量短作业或低资源占用的任务 |
# 将作业任务按轮询模式分配到各节点(每个任务分配到不同节点)
sbatch --spread --ntasks=5 --distribution=cyclic job.sh
c. 全局轮询模拟方案
| 配置项 | 实现方式 | 作用范围 | |
|---|---|---|---|
| 节点选择算法 | 在slurm.conf中设置: SelectType=select/linear |
全局生效 | |
| 任务分布模式默认值 | 在slurm.conf中添加: TaskPlugin=task/affinity DefDist=cyclic |
所有未指定参数的作业 | |
| 分区级策略覆盖 | 创建专用分区并配置: scontrol create Partition=cyclic_partition Default=YES \ Nodes=ALL DefDist=cyclic |
指定分区内的作业 |
8 EDA 调度、QOS、抢占最佳实战¶
全局调度框架固定 + 分区 / QoS 做业务差异化 = 最终灵活支撑全流程
Slurm 策略本质就是按任务脆弱性、资源需求、优先级、可并行性做匹配:
- 有的任务不能停(停了重跑几小时 / 几天)
- 有的任务极吃内存(一抢就 OOM、收敛失败)
- 有的任务海量小作业(要高吞吐、高并发)
- 有的任务优先级极高(流片、Signoff)
- 集群资源有限(必须隔离、抢占、回填、公平共享)
| 工具 / 环节 | 推荐分区 | QoS 优先级 | CPU / 任务 | 内存 / 任务 | 独占? | 抢占? |
|---|---|---|---|---|---|---|
| Synthesis | eda_normal | 中高 | 4~8 | 32~64G | 否 | 否 |
| Innovus/ICC2 PnR | eda_large | 高 | 16 | 256~512G | 是 | 否 |
| SPICE | eda_large | 高 | 1 | 128~256G | 是 | 否 |
| FastSPICE | eda_normal | 中 | 8~16 | 64~128G | 否 | 是 |
| VCS/Xcelium RTL | eda_fast | 低 | 2 | 16G | 否 | 是 |
| DRC/LVS 批量 | eda_fast | 低 | 2~4 | 16~32G | 否 | 是 |
| Formal/LEC | eda_fast | 中低 | 1~4 | 16~128G | 按需 | 是 |
| PrimeTime PT | eda_large | 高 | 32 | 256G+ | 是 | 否 |
| Tapeout 终审 | eda_high | 最高 | 全节点 | 全节点 | 是 | 否 |
8.1 EDA 场景 × Slurm 调度策略 对应逻辑表¶
| EDA 环节 | 典型场景 / 任务 | 任务核心特征 | 采用的 Slurm 调度策略 | 选择该策略的核心原因 |
|---|---|---|---|---|
| 设计 | 逻辑综合 Synthesis | 中并行、中等内存、可重跑但耗时不低 | 共享节点、中等优先级、FairShare、合理时限 | 1. 无需独占,共享提升利用率2. 避免卡死占用资源3. 防止单项目垄断资源、其他项目饥饿 |
| 布局布线 PnR (Innovus/ICC2) | 极高内存、对扰动敏感、中断必须重跑、流片关键路径 | 节点独占、禁止抢占、高优先级、限制单用户并发 | 1. 内存竞争会导致时序恶化 / 任务崩溃2. 抢占代价极高,必须保证不中断3. 防止单个用户占满所有大内存节点 | |
| 物理验证 DRC/LVS 批量 | 海量轻量小任务、可重跑、追求总吞吐 | 任务数组、超订阅 / 共享、可抢占、低优先级、短时限 | 1. 轻任务适合高并发批量调度2. 超订阅避免资源浪费3. 可让位高优任务,利用碎片资源4. 自动清理僵尸任务 | |
| 仿真 | SPICE 晶体管级仿真 | 串行单核、极高内存、收敛慢、中断即从头开始 | 节点独占、严禁抢占、高优先级、长时限、限并发 | 1. CPU / 内存波动会导致不收敛 / 结果异常2. 抢占成本不可接受3. 防止多任务并发挤爆内存 |
| FastSPICE / AMS 混合信号仿真 | 多线程、中高内存、可适度共享 | 中等资源分配、节点共享、可被高优抢占 | 1. 工具并行效率有上限,资源过多浪费2. 平衡吞吐与稳定性3. 保障关键任务优先 | |
| RTL 仿真(VCS/Xcelium)回归 | 海量极短任务、完全可重跑、追求整体吞吐量 | 回填调度、超订阅、任务数组、最低优先级、可抢占 | 1. 利用集群碎片时间大幅提升利用率2. 高并发跑满用例3. 不影响核心流片任务 | |
| GPU 加速仿真 | GPU 稀缺、不可共享、任务成本高、不宜中断 | GPU 独占、高优先级、禁止抢占、CPU-GPU 绑定 | 1. GPU 争抢会直接导致仿真失败2. 昂贵任务不允许被打断3. 减少调度开销保证稳定 | |
| 验证 | 形式验证 Formal | 高内存、轻线程、状态搜索易崩溃、断点续跑困难 | 节点 / 内存独占、禁止抢占、长时限、高优先级 | 1. 内存不足会导致状态空间爆炸无法收敛2. 深度搜索中断即失效3. 求解时长不可预估需宽松窗口 |
| 等价性检查 LEC | 极轻量、高吞吐、随意重跑 | 最小资源分配、超大任务数组、最高可抢占性、低优先级 | 1. 资源需求极低,避免浪费2. 支持数万任务并发排队3. 随时可让位任何高优任务 | |
| UVM 大规模验证回归 | 任务量巨大、时长不均、只关心总吞吐量 | 回填调度、FairShare、可抢占、节点共享 | 1. 吃满资源碎片,不干扰主力任务2. 多用户公平使用,避免饥饿3. 可被高优任务打断 | |
| Signoff / 流片 | PrimeTime 时序分析 | 极高内存多线程、结果不可出错、不可中断 | 节点独占、禁止抢占、高优先级、长时限 | 1. 内存 / CPU 扰动会影响时序分析结果2. 任务不可失败,必须稳定跑完 |
| Tapeout 终审任务 | 业务优先级最高、时间窗口固定、不可失败 | 最高优先级、禁止任何抢占、可突破配额、全节点独占 | 1. 流片任务一提交必须立即获得资源2. 任何抢占都等于项目风险3. 配额限制为日常设计,流片需兜底保障 | |
| 通用多项目管理 | 多团队 / 多项目共用集群 | 资源争抢、优先级差异大、需稳定运维 | 分区隔离、QoS 分级、FairShare、抢占分级、回填 | 1. 防止单个项目拖垮集群2. 低代价任务让高代价任务,整体损失最小3. 长期资源使用均衡,提升集群利用率 |
9 SLURM调试器调试策略及应用场景指南¶
SLURM作为分布式集群调度系统,其调试核心在于 作业生命周期跟踪 和 资源分配逻辑分析
9.1 调试核心策略¶
| 调试目标 | 关键工具 | 核心策略 |
|---|---|---|
| 作业状态异常 | scontrol show job |
检查作业的Reason字段,明确挂起/失败原因(如资源不足、依赖未满足) |
| 节点健康状态 | sinfo -N -l | 分析节点STATE(如drain*表示维护),结合slurmd.log定位硬件/服务故障 |
| 调度延迟 | sdiag -f | 查看调度周期统计(schedule_cycle耗时),识别资源碎片化或策略瓶颈 |
| 资源争用 | sreport job sizes | 按用户/账户统计资源占用,定位超额使用或QoS配置错误 |
| 权限问题 | sacct -X -j |
检查作业提交用户的账户权限(Account和QoS绑定关系) |
| GPU/NPU异构故障 | scontrol show node |
验证Gres配置(如gpu:tesla_a100:2),对比驱动版本和CUDA兼容性 |
9.2 Slurm sdiag 关键字速查表¶
1 调度器线程 / 队列
| 英文 | 中文翻译 | 运维含义 |
|---|---|---|
| Server thread count | 调度服务线程数 | slurmctld 主线程数 |
| Agent queue size | Agent 队列长度 | 执行代理任务积压数 |
| DBD Agent queue size | 数据库代理队列 | 计费 / 入库任务积压 |
2 作业统计
| 英文 | 中文翻译 | 运维含义 |
|---|---|---|
| Jobs submitted | 提交作业数 | 这段时间提交多少任务 |
| Jobs started | 启动作业数 | 已开始运行的任务 |
| Jobs completed | 完成作业数 | 正常结束任务 |
| Jobs canceled | 取消作业数 | 被手动取消任务 |
| Jobs failed | 失败作业数 | 运行出错 / 挂掉任务 |
| Jobs pending | 排队作业数 | 正在等待资源的任务 |
| Jobs running | 运行作业数 | 正在跑的任务 |
3 主调度性能(核心)
| 英文 | 中文翻译 | 运维含义 |
|---|---|---|
| Main schedule statistics | 主调度统计 | 调度器效率核心指标 |
| Last cycle | 上次调度耗时 | 最近一次调度花费时间(微秒) |
| Max cycle | 最大调度耗时 | 历史最忙时调度耗时 |
| Mean cycle | 平均调度耗时 | 平均调度效率 |
| Cycles per minute | 每分钟调度次数 | 调度频率 |
| Last queue length | 上次队列长度 | 调度时排队任务数 |
4 回填调度
| 英文 | 中文翻译 | 运维含义 |
|---|---|---|
| Backfilling stats | 回填调度统计 | 碎片资源利用优化 |
| Total backfilled jobs | 回填作业总数 | 利用碎片跑的任务数 |
| Last cycle | 上次回填耗时 | 回填调度花费时间 |
5 RPC内部通信
| 英文 | 中文翻译 | 运维含义 |
|---|---|---|
| RPC statistics | 远程调用统计 | Slurm 内部通信耗时 |
| count | 调用次数 | 该请求发生多少次 |
| ave_time | 平均耗时 | 单次平均耗时(微秒) |
| total_time | 总耗时 | 该类请求总耗时 |
| Pending RPCs | 等待中的 RPC | 是否有通信阻塞 |
8.3 sreport 查询资源使用量
sreport cluster utilization
sreport job sizesbyaccount
sreport user top
9.3 常规性能排查¶
按CPU → 内存 → IO → 网络 → 调度器 → EDA 自身日志
- 前言:
90% 就 4 个地方:
- CPU 算力不够 / 绑定不对 / 调度不均
- 内存不够、swap、频繁换页
- 存储太慢:仿真读写巨大波形、文件 IO 卡死
-
多机并行时网络慢(MPI)
-
系统级性能排查工具
top / htop
-
看:CPU 占用、核负载、进程优先级
-
EDA 常见:
- 有的核跑满,有的 idle → 绑定不对
- 整体很低 → IO 瓶颈或工具没并行起来
mpstat -P ALL 1
看每个 CPU 核心的使用率,判断是不是负载不均。
pidstat -u 1
看进程级 CPU 使用率。
- 内存 / 交换区瓶颈
free -h
看是否用了 swap,一用 swap 仿真直接慢 10~100 倍。
vmstat 1
si/so大于 0 → 正在换页,巨慢us sy id wa→ 看是 CPU 还是 IO 瓶颈
pidstat -r 1`
看 EDA 进程物理内存、虚拟内存
- IO 瓶颈(仿真 90% 慢在这里)
iostat -x 1
%util接近 100% → 存储满负载await高 → 盘慢、NAS / 并行文件系统慢
iotop
看哪个进程在疯狂读写(一般就是 EDA)。
df -i
inode 满了也会让 EDA 卡死
- 多机并行(MPI)网络瓶颈
总结:
CPU 高,时间快 → 正常,算力瓶颈
CPU 低,时间慢 → IO 瓶颈(90%)
CPU 低 + 磁盘 util 100% → 存储太慢
CPU 低 + 磁盘不高 → 工具没并行 / 配置错
用了 swap → 内存不够,必慢
10 slurm.conf¶
# ============================================================
# 一、集群基本信息
# ============================================================
ClusterName=eda-hpc-cluster # 集群名称,自定义
SlurmctldHost=slurmctl01 # 主控制节点(调度节点)
SlurmctldHost=slurmctl02 # 备控制节点(HA 高可用,可选)
SlurmdbdHost=slurmdb01 # 计费/记账数据库节点(可选)
SlurmUser=slurm # Slurm 运行用户,禁止用 root
SlurmdSpoolDir=/var/spool/slurmd # 计算节点状态目录(必须本地)
SlurmctldPidFile=/var/run/slurmctld.pid
SlurmdPidFile=/var/run/slurmd.pid
StateSaveLocation=/var/spool/slurmctld # 调度状态保存目录
# ============================================================
# 二、日志与调试
# ============================================================
SlurmctldLogFile=/var/log/slurm/slurmctld.log
SlurmdLogFile=/var/log/slurm/slurmd.log
SlurmSchedLogFile=/var/log/slurm/slurm_sched.log
SlurmctldDebug=3
SlurmdDebug=3
# ============================================================
# 三、核心调度机制(最关键部分)
# ============================================================
# 资源选择插件
# cons_tres = 按可消费资源(CPU、内存、GPU、License)调度
# EDA/HPC 必须用这个,才能精确管控内存/GPU
SelectType=select/cons_tres
# 资源调度粒度
# CR_Core 按物理核心调度(不按超线程)
# Memory 支持内存作为独立可分配资源
# CR_Pack 尽量把任务打包到更少节点,提高利用率
SelectTypeParameters=CR_Core_Memory,CR_Pack
# 任务绑定与隔离插件
# task/affinity CPU 亲和绑定(PnR/SPICE 稳定性极强)
# task/cgroup 内核级资源隔离(CPU/内存/IO 强隔离)
TaskPlugin=task/affinity,task/cgroup
# ============================================================
# 四、抢占策略(Preempt)EDA 必开
# ============================================================
# 抢占模式:按 QoS 优先级抢占
PreemptType=preempt/qos
# 抢占行为
# SUSPEND 挂起低优先级任务(温和,推荐)
# GANG 时间片共享,适合大量小任务并发
# REQUEUE 直接重启低优任务(激进,EDA 慎用)
PreemptMode=SUSPEND,GANG
# 高优先级任务可以抢占低优先级
PreemptExemptTime=00:02:00 # 任务启动2分钟内不被抢
# ============================================================
# 五、多因子优先级策略(Priority)
# ============================================================
# 多因子综合优先级(行业标准)
PriorityType=priority/multifactor
# 各项权重(数值越大权重越高)
PriorityWeightFairshare=5000 # 公平共享(最重要,防止单用户垄断)
PriorityWeightQOS=2000 # QoS 业务优先级(流片/PnR/SPICE)
PriorityWeightAge=1000 # 排队时间(排队越久优先级越高)
PriorityWeightPartition=500 # 分区权重
PriorityWeightJobSize=200 # 任务大小权重
# 公平共享衰减系数
# 越大:历史资源使用影响越小,越“宽容”
# 越小:惩罚越重
FairShareDampeningFactor=6
# 优先级更新间隔
PriorityDecayHalfLife=14-00:00:00
# ============================================================
# 六、回填调度(Backfill)EDA 集群利用率关键
# ============================================================
SchedulerType=sched/backfill
# 回填参数
# bf_window 向后看多长时间的空闲窗口(分钟)
# bf_depth 一次扫描多少排队任务
# defer 避免小任务无限阻塞大任务
SchedulerParameters=backfill,bf_window=180,bf_depth=200,defer
# ============================================================
# 七、Cgroup 资源硬隔离(EDA 必配)
# ============================================================
CgroupAutomount=yes
CgroupMountpoint=/sys/fs/cgroup
# 开启核心隔离
ConstrainCores=yes
# 开启内存/swap 硬限制
ConstrainRamSpace=yes
ConstrainSwapSpace=yes
# 限制 device 设备访问
ConstrainDevices=yes
# 限制进程间相互干扰
PropagateResourceLimits=ALL
# ============================================================
# 八、任务规模与并发上限(EDA 海量任务必备)
# ============================================================
MaxJobCount=100000 # 集群最大同时作业数
MaxArraySize=100000 # 最大任务数组(UVM/DRC/LVS 大量用)
MaxTasksPerNode=1024
MaxThreadsPerCore=1
# 默认每核内存(防止用户不指定内存导致OOM)
DefMemPerCPU=4096
MaxMemPerCPU=32*1024=30720
# 默认任务时限
DefaultTime=08:00:00
# ============================================================
# 九、自定义资源类型(GPU / License)
# ============================================================
# gpu = GPU 卡
# lic = EDA License(把 License 当作调度资源)
GresTypes=gpu,lic
# ============================================================
# 十、节点定义(示例:2路CPU,256G 内存节点)
# ============================================================
# NodeName 节点名称支持 range 写法
# Sockets CPU 路数
# CoresPerSocket 每路物理核心数
# ThreadsPerCore 超线程关闭=1,开启=2
# RealMemory 实际可用内存(MB)
NodeName=node[001-100] Sockets=2 CoresPerSocket=16 ThreadsPerCore=1 RealMemory=256000 State=UP
# ============================================================
# 十一、分区(队列)配置 EDA 典型分区规划
# ============================================================
# 1. 大内存分区:PnR / SPICE / PT / Formal
PartitionName=highmem \
Nodes=node[001-020] \
Default=NO \
MaxTime=7-00:00:00 \
State=UP \
Hidden=NO
# 2. 通用分区:综合 / DRC / LVS / 仿真
PartitionName=normal \
Nodes=node[021-080] \
Default=YES \
MaxTime=3-00:00:00 \
State=UP
# 3. 短作业/回归分区:UVM回归、LEC、小验证
PartitionName=fast \
Nodes=node[081-100] \
Default=NO \
MaxTime=12:00:00 \
State=UP
# 4. GPU 分区:GPU 仿真、AI 辅助验证
PartitionName=gpu \
Nodes=node[g01-g04] \
Default=NO \
MaxTime=2-00:00:00 \
State=UP
# ============================================================
# 十二、其他系统行为
# ============================================================
# 不允许任务超支使用内存
EnforceForcedLimits=yes
# 任务异常时自动清理环境
KillOnBadExit=yes
# 节点健康检查(可选)
# HealthCheckProgram=/etc/slurm/scripts/healthcheck.sh
# HealthCheckInterval=300
10.1 gres.conf¶
####################################################################
# GRES = Generic Resource,通用资源
# 作用:让 Slurm 把 GPU、EDA License 当作“可调度资源”
# 格式:NodeName 节点名 资源类型 数量
####################################################################
# --------------------------
# 1. GPU 节点配置
# --------------------------
NodeName=g[01-04] Name=gpu File=/dev/nvidia0
NodeName=g[01-04] Name=gpu File=/dev/nvidia1 # 双GPU卡
# --------------------------
# 2. License 资源(虚拟GRES)
# 注意:这里只定义资源类型,不写真实License数量
# 真实数量在 sacctmgr 中用 QoS/TRES 限制
# --------------------------
# 所有节点都可以申请EDA License
NodeName=node[001-100],g[01-04] Name=lic Type=count Count=1000
# 按厂商拆分License(更精细)
NodeName=node[001-100] Name=lic_synopsys Type=count Count=1000
NodeName=node[001-100] Name=lic_cadence Type=count Count=1000
NodeName=node[001-100] Name=lic_mentor Type=count Count=1000
10.2 qos.conf (EDA 标准 QoS 分级模板)¶
####################################################################
# QoS 优先级从高到低:
# tapeout > pnr > signoff > synth > sim > fast > debug
# 高优先级可抢占低优先级
####################################################################
# --------------------------
# 1. 流片终审(最高)
# --------------------------
QoS:
Name=tapeout
Priority=10000
PreemptMode=OFF
GrpTRES=cpu=1024,mem=2TB
MaxJobsPerUser=10
MaxWall=14-00:00:00
# --------------------------
# 2. 布局布线 PnR
# --------------------------
QoS:
Name=pnr
Priority=8000
PreemptMode=OFF
GrpTRES=cpu=512,mem=1TB
MaxJobsPerUser=5
MaxWall=7-00:00:00
# --------------------------
# 3. Signoff 签核(PT/SPICE/Formal)
# --------------------------
QoS:
Name=signoff
Priority=7000
PreemptMode=OFF
GrpTRES=cpu=256,mem=512GB
MaxJobsPerUser=8
MaxWall=7-00:00:00
# --------------------------
# 4. 综合 Synthesis
# --------------------------
QoS:
Name=synth
Priority=5000
PreemptMode=SUSPEND
GrpTRES=cpu=256,mem=512GB
MaxJobsPerUser=20
MaxWall=3-00:00:00
# --------------------------
# 5. 仿真仿真(VCS/Xcelium)
# --------------------------
QoS:
Name=sim
Priority=3000
PreemptMode=SUSPEND
GrpTRES=cpu=512,mem=1TB
MaxJobsPerUser=100
MaxWall=2-00:00:00
# --------------------------
# 6. 快速小任务(DRC/LVS/LEC/UVM回归)
# --------------------------
QoS:
Name=fast
Priority=1000
PreemptMode=SUSPEND
GrpTRES=cpu=1024,mem=2TB
MaxJobsPerUser=500
MaxWall=12:00:00
# --------------------------
# 7. 调试(最低)
# --------------------------
QoS:
Name=debug
Priority=500
PreemptMode=SUSPEND
MaxJobsPerUser=5
MaxWall=01:00:00
11 运维相关¶
11.1 submit 节点需求¶
| 检查项 | 当前状态 | 目标状态 | 是否满足 |
|---|---|---|---|
| MUNGE 服务 | active (running) | 运行中 | ✅ 满足 |
| MUNGE 密钥一致性 | 318fd0af...(与主节点一致) | 与主节点相同 | ✅ 满足 |
| SLURM 客户端命令 | 已安装于 /usr/local/slurm/bin/ | sbatch/squeue/sinfo 等可用 | ✅ 满足 |
| slurm.conf 配置文件 | /var/spool/slurmd/conf-cache/slurm.conf | configless 模式 | ⚠️ 需关注 |
| 网络到 slurmctld:6817 | 连通 | 可达 | ✅ 满足 |
| 时间同步 (chronyd) | active (running),NTP enabled | 运行中 | ✅ 满足 |
三、 LSF¶
1. 概览¶
LSF(Load Sharing Facility)是IBM开发的一款分布式集群管理软件,专为高性能计算(HPC)环境设计,用于统一管理计算资源并调度批处理作业。其核心目标是通过智能调度策略最大化硬件利用率,同时为用户提供透明的资源访问接口
2. LSF 核心组件¶
- MBD(Master Batch Daemon):主控守护进程,负责作业队列管理、资源分配及调度策略执行(类似
slurmctld),支持高可用部署。 - LIM(Load Information Manager):负载信息管理器,实时收集节点资源状态(CPU/内存/磁盘),为调度决策提供数据支撑。
- SBD(Slave Batch Daemon):节点代理,执行作业启动、监控及资源回收,类似slurmd
3. 作业调度策略¶
3.1 基础调度策略¶
- 先来先服务(FCFS)
- 默认策略:LSF 默认按作业提交顺序调度,最早提交的作业优先获得资源。
- 局限性:无法处理紧急任务插队需求,需依赖优先级调整机制。
- 优先级调度
- 用户自定义优先级:通过
bsub -sp指定作业优先级,高优先级作业优先调度。 - 动态优先级调整:管理员可通过
bbot、btop动态修改作业优先级,支持业务紧急任务插队
3.2 高级调度策略¶
- 抢占式调度(Preemptive Scheduling)
- 资源抢占:高优先级作业可抢占低优先级作业资源,被抢占作业暂停(PSUSP/SSUSP)直至资源释放。
- 适用场景:适用于混合云环境,保障关键任务快速完成。
- 公平分享调度(Fairshare Scheduling)
- 资源公平分配:根据用户/队列预设权重分配资源,避免单一用户或队列垄断集群资源24。
- 全局公平共享:在多集群场景下,跨地理位置统一资源分配策略,确保全局资源公平性47。
- 队列分层管理
- 队列优先级:通过
bqueues设置队列优先级(数值越高优先级越高),调度时按队列优先级顺序检查作业。 - 资源限制:队列可绑定特定主机(
HOSTS)或用户白名单(USERS),实现资源隔离
四、其它¶
1. Slurm/SGE/LSF命令行任务下发方式对比¶
1.1 基础任务下发¶
| 功能 | Slurm | SGE | LSF | |
|---|---|---|---|---|
| 批处理作业 | sbatch job_script.sh |
qsub job_script.sh |
bsub < job_script.sh |
|
| 交互式任务 | srun --pty -n 1 -p partition bash |
qrsh -l h_rt=1:00:00 |
bsub -Is -q queue bash |
|
| 资源分配 | salloc -N 2 --gres=gpu:2 |
qsub -l h=node1,node2 |
bsub -R "rusage[ngpus=2]" |
|
1.2 高级任务控制¶
| 功能 | Slurm | SGE | LSF | |
|---|---|---|---|---|
| 作业依赖 | sbatch --dependency=afterok:JOBID |
qsub -hold_jid JOBID |
bsub -w "done(JOBID)" |
|
| 任务阵列 | sbatch --array=1-10 |
qsub -t 1-10 |
bsub -J "arrayjob[1-10]" |
|
| 资源限制 | #SBATCH --mem=4G |
#$ -l mem_free=4G |
#BSUB -M 4096 |
1.3 作业监控与管理¶
| 功能 | Slurm | SGE | LSF | |
|---|---|---|---|---|
| 查看作业状态 | squeue -u $USER |
qstat -u $USER |
bjobs -u $USER |
|
| 取消作业 | scancel JOBID |
qdel JOBID |
bkill JOBID |
|
| 查看资源使用 | sinfo -p partition |
qhost -q |
bhosts 或 lshosts |
|
1.4 核心参数对标¶
| 参数类型 | Slurm | SGE | LSF |
|---|---|---|---|
| 指定队列/分区 | -p partition |
-q queue |
-q queue |
| 节点数量 | -N 2 |
-l nodes=2 |
-n 2 |
| 任务并行度 | -n 8 |
-pe smp 8 |
-n 8 |
| 时间限制 | --time=01:00:00 |
-l h_rt=1:00:00 |
-W 60(分钟) |
1.5 slurm与lsf命令平替¶
| Slurm命令 | LSF等效命令 | 功能说明 |
|---|---|---|
squeue |
bjobs |
查看作业队列状态 |
squeue -u $USER |
bjobs -u $USER |
查看指定用户的作业 |
scancel JOBID |
bkill JOBID |
终止指定作业 |
sacct |
bhist -l 或 bacct |
查看历史作业统计信息 |
scontrol show job JOBID |
bjobs -l JOBID |
查看作业详细信息(资源分配、节点列表等 |
| Slurm命令/参数 | LSF等效实现 | 功能说明 |
|---|---|---|
sbatch job_script.sh |
bsub < job_script.sh |
提交批处理作业脚本 |
--nodes=2 |
-n 2(总节点数)或 -R "span[ptile=1]" |
指定节点数量 |
--ntasks-per-node=8 |
-R "span[ptile=8]" |
每节点任务数(MPI进程数) |
--cpus-per-task=4 |
-R "rusage[cpuf=4]" |
每个任务独占CPU核心数 |
--gres=gpu:2 |
-R "rusage[ngpus_excl_p=2]" |
每个任务分配GPU卡数 |
--mem=16G |
-R "rusage[mem=16384]" |
每个任务内存限制(单位MB) |
--time=24:00:00 |
-W 1440(单位分钟) |
作业最大运行时间限制 |
| Slurm命令 | LSF等效命令 | 功能说明 |
|---|---|---|
sinfo |
bqueues 或 lshosts |
查看分区/队列及节点状态 |
scontrol show partition |
bqueues -l QUEUE_NAME |
查看指定分区的详细配置 |
scontrol show nodes |
bhosts -l HOSTNAME |
查看节点资源详情(CPU/内存/GPU等) |
scontrol update ... |
bmod |
动态修改作业参数(如时间限制) |
| Slurm命令 | LSF等效实现 | 功能说明 |
|---|---|---|
srun --pty bash |
bsub -Is bash |
启动交互式会话(分配资源后进入Shell) |
salloc --nodes=1 |
bsub -I -n 1 -R "span[hosts=1]" sleep 3600 |
预分配资源并保持会话(需配合后续命令) |
srun -n 8 ./a.out |
mpirun -n 8 ./a.out(需结合bsub提交) |
并行执行MPI程序67 |
| Slurm场景 | LSF实现方案 | 说明 |
|---|---|---|
| GPU亲和性控制 | -R "select[gpu_model0] rusage[ngpus_excl_p=1]" |
指定特定GPU型号并独占使用 |
| 多队列优先级 | -q high_priority |
通过不同队列名称实现优先级调度 |
| 作业依赖(DAG) | -w "done(jobid)" |
基于作业完成状态的依赖链 |
| 弹性资源预留 | bsub -J "reservation_name" -R "rusage[...]" |
创建资源预留(需LSF管理员配置策略) |
eg:
sbatch --nodes=4 --ntasks-per-node=8 --cpus-per-task=2 --mem=8G mpi_job.sh
bsub -n 32 -R "span[ptile=8] rusage[mem=8192,cpuf=2]" mpi_job.sh
两者等效
五 Environment Modules/Lmod¶
1 概览¶
1.1 说明¶
Environment Modules(环境模块)能将不同软件的环境配置封装成「模块」,你可以通过简单的命令快速加载 / 卸载模块,实现环境的一键切换,无需手动修改环境变量
Lmod(新一代的模块管理工具)是 Environment Modules 的升级版(基于 Lua 开发),兼容传统模块语法,还增加了依赖管理、层级模块、模块缓存等高级特性
1.2 核心工作原理¶
模块文件(Modulefile):
核心是「模块文件」(后缀通常为.lua或.mod),本质是一段脚本,定义了加载 / 卸载该模块时要修改的环境变量。
- 加载模块:执行模块文件中的
prepend-path/setenv等指令,修改环境变量 - 卸载模块:执行反向操作,恢复环境变量到加载前的状态
模块路径:
系统会预设模块文件的存放路径(比如/opt/modulefiles),module命令会扫描这些路径下的模块文件,供你调用
2 核心命令¶
| 命令 | 作用 | 示例 |
|---|---|---|
module avail |
列出所有可用模块 | module avail python(过滤 python 相关) |
module load <模块名> |
加载模块 | module load python/3.10 |
module unload <模块名> |
卸载模块 | module unload python/3.10 |
module list |
查看已加载的模块 | - |
module purge |
卸载所有已加载模块 | - |
module swap <旧模块> <新模块> |
切换模块版本 | module swap python/3.8 python/3.10 |
module show <模块名> |
查看模块的具体配置 | module show gcc/11.2 |
3 Lmod 进阶特性(对比传统 Module 的优势)¶
3.1 层级模块¶
Lmod 会自动处理模块依赖,比如加载python/3.10时,会自动加载其依赖的gcc/11.2,无需手动加载
# 加载python/3.10,Lmod自动加载依赖的gcc
module load python/3.10
module list
# 输出:
# 1) gcc/11.2 2) python/3.10
3.2 模块缓存¶
Lmod 会缓存模块文件的解析结果,大幅提升module avail/module list等命令的执行速度(尤其适合模块数量多的超算环境)
3.3 模块别名¶
可以为常用模块设置别名,简化操作
-- 在模块文件中设置别名
alias("py310", "python/3.10")
3.4 条件加载
通过 Lua 语法实现更灵活的模块逻辑,比如根据系统架构(x86/arm)加载不同版本:
-- 示例:Lmod的lua模块文件(python/3.10.lua)
local arch = os.getenv("ARCH") or "x86_64"
if arch == "x86_64" then
prepend_path("PATH", "/opt/python/3.10/x86_64/bin")
elseif arch == "aarch64" then
prepend_path("PATH", "/opt/python/3.10/aarch64/bin")
end
setenv("PYTHON_VERSION", "3.10")
4 配置¶
4.1 初始化lmod 环境¶
Lmod 的核心是通过 shell 脚本初始化环境,不同 shell(bash/zsh/csh)需要加载对应的初始化脚本
# 方法1:临时生效(仅当前会话)
# bash/zsh 用户
source /usr/share/lmod/lmod/init/bash
# csh/tcsh 用户
source /usr/share/lmod/lmod/init/csh
# 方法2:永久生效(所有用户)
# 将初始化脚本加入系统全局配置
echo 'source /usr/share/lmod/lmod/init/bash' >> /etc/profile.d/lmod.sh
chmod +x /etc/profile.d/lmod.sh
# 重启会话或执行以下命令立即生效
source /etc/profile.d/lmod.sh
4.2 配置默认模块路径¶
Lmod 默认会扫描 /etc/modulefiles 和 /usr/share/modulefiles,但通常需要自定义模块路径(比如集群常用的 /opt/modulefiles),修改 Lmod 的核心配置文件 /etc/lmodrc.lua(若不存在则新建)
-- /etc/lmodrc.lua 核心配置示例
-- 1. 设置模块文件的默认搜索路径(优先级从左到右)
module_path = {
"/opt/modulefiles", -- 自定义模块路径(推荐)
"/usr/local/modulefiles",
"/usr/share/modulefiles",
"/etc/modulefiles"
}
-- 2. 启用模块缓存(提升大数量模块的查询速度)
cacheDir = "/var/cache/lmod"
enable_cache = true
-- 3. 设置默认模块显示风格(精简/详细)
show_hidden = false -- 不显示隐藏模块(以.开头的模块文件)
style = "system" -- 显示风格:system(系统)/compact(紧凑)/full(完整)
-- 4. 启用层级模块(Lmod核心特性)
enable_hierarchy = true
-- 5. 设置模块冲突检测级别
strict_load = true -- 加载冲突模块时直接报错(而非自动卸载)
-- 6. 自定义模块别名(全局生效)
alias_map = {
["python3"] = "python/3.10",
["gcc"] = "gcc/11.2"
}
或通过设置环境变量指定自定义加载目录
export MODULEPATH=/mnt/nfs/slurm/modules
4.3 启用缓存¶
启用后需要创建缓存目录并设置权限并验证:
mkdir -p /var/cache/lmod
chmod 755 /var/cache/lmod
chown root:root /var/cache/lmod
# 查看Lmod配置信息
module --config
# 查看默认模块路径
echo $MODULEPATH
# 查看可用模块(验证路径是否生效)
module avail
5 Lmod 模块文件核心语法(Lua 语法为主)¶
5.1 基础指令¶
| 指令 | 作用 | 示例 |
|---|---|---|
help([[内容]]) |
模块帮助信息(module help <模块名> 显示) |
help([[Python 3.10 模块,包含pip和虚拟环境]]) |
whatis("描述") |
模块简短描述(module whatis <模块名> 显示) |
whatis("Version: 3.10") |
setenv("变量名", "值") |
设置环境变量 | setenv("PYTHON_HOME", "/opt/python/3.10") |
prepend_path("路径变量", "路径") |
路径添加到变量头部(优先级最高) | prepend_path("PATH", "/opt/python/3.10/bin") |
append_path("路径变量", "路径") |
路径添加到变量尾部 | append_path("PYTHONPATH", "/opt/python/3.10/lib") |
remove_path("路径变量", "路径") |
移除指定路径 | remove_path("PATH", "/usr/bin/python2.7") |
depends_on("模块名") |
声明模块依赖(加载时自动加载依赖) | depends_on("gcc/11.2") |
conflict("模块名") |
声明冲突模块(无法同时加载) | conflict("python/2.7") |
family("分类名") |
归类模块(同一分类仅能加载一个) | family("python") |
set_alias("别名", "命令")| 设置命令别名 |alias("python3", "/opt/python/3.10/bin/python")` |
||
load("模块名") |
主动加载其他模块(等同于 depends_on) |
load("openmpi/4.1.4") |
5.2 流程控制¶
-- 1. 条件判断(if-else)
local arch = os.getenv("ARCH") or "x86_64" -- 获取系统架构
if arch == "x86_64" then
prepend_path("PATH", "/opt/python/3.10/x86_64/bin")
elseif arch == "aarch64" then
prepend_path("PATH", "/opt/python/3.10/aarch64/bin")
else
LmodError("不支持的架构:" .. arch) -- 抛出错误
end
-- 2. 循环(for)
local libs = { "lib", "lib64", "lib/python3.10/site-packages" }
for _, lib in ipairs(libs) do
prepend_path("LD_LIBRARY_PATH", "/opt/python/3.10/" .. lib)
end
-- 3. 获取系统变量/路径
local home = os.getenv("HOME") -- 用户家目录
local prefix = "/opt/python/3.10" -- 软件安装根目录
local shell = os.getenv("SHELL") -- 当前shell类型
5.3 特殊变量与函数
| 变量 / 函数 | 作用 | 示例 |
|---|---|---|
home |
等价于 $HOME,用户家目录 |
prepend_path("PYTHONPATH", home .. "/.local/lib/python3.10") |
mode() |
返回当前操作模式(load/unload/show) | if mode() == "load" then print("加载模块") end |
LmodError("信息") |
抛出错误并终止模块加载 | LmodError("必须先加载gcc模块!") |
LmodWarning("信息") |
抛出警告但继续加载 | LmodWarning("该模块即将废弃,请使用python/3.11") |
os.getenv("变量") |
获取环境变量 | local mpi = os.getenv("MPI_VERSION") or "openmpi" |
5.3 万能通用模板¶
-- ==============================================
-- Lmod 模块文件万能模板(Python 3.10 示例)
-- 适用场景:编译器/应用软件/库文件等所有模块编写
-- ==============================================
-- 1. 模块基础信息(必选)
-- 帮助信息(module help <模块名> 显示)
help([[
模块名称:Python 3.10
安装路径:/opt/python/3.10
功能说明:
- 内置pip、venv虚拟环境工具
- 支持x86_64/aarch64双架构
- 依赖gcc/11.2编译器
使用方法:
module load python/3.10
module unload python/3.10
注意事项:
- 与Python 2.7冲突,加载时会自动卸载
- 建议配合虚拟环境使用,避免全局包污染
]])
-- 简短描述(module whatis <模块名> 显示)
whatis("Name: Python")
whatis("Version: 3.10.12")
whatis("Category: Programming Language")
whatis("URL: https://www.python.org/")
whatis("Description: High-level programming language")
-- 2. 核心配置(必选)
-- 软件安装根目录(统一管理,便于修改)
local prefix = "/opt/python/3.10"
-- 系统架构(自动识别)
local arch = os.getenv("ARCH") or (io.popen("uname -m"):read("*a"):gsub("\n", ""))
-- 3. 多架构适配(可选,通用场景)
local bin_path, lib_path
if arch == "x86_64" then
bin_path = pathJoin(prefix, "x86_64", "bin")
lib_path = pathJoin(prefix, "x86_64", "lib64")
elseif arch == "aarch64" then
bin_path = pathJoin(prefix, "aarch64", "bin")
lib_path = pathJoin(prefix, "aarch64", "lib64")
else
LmodError("不支持的架构:" .. arch .. ",仅支持x86_64/aarch64")
end
-- 4. 依赖管理(可选,通用场景)
-- 强制依赖(必须先加载,否则报错)
depends_on("gcc/11.2")
-- 可选依赖(存在则加载,不存在则忽略)
if isloaded("openmpi/4.1.4") then
load("mpi4py/3.1.4") -- 加载MPI相关扩展
end
-- 5. 冲突管理(可选,通用场景)
-- 禁止同时加载Python 2.7
conflict("python/2.7")
-- 同一分类仅能加载一个版本(family指令)
family("python")
-- 6. 环境变量配置(核心)
-- 核心路径(优先级最高)
prepend_path("PATH", bin_path)
prepend_path("LD_LIBRARY_PATH", lib_path)
prepend_path("MANPATH", pathJoin(prefix, "share", "man"))
-- Python专属路径
prepend_path("PYTHONPATH", pathJoin(lib_path, "python3.10", "site-packages"))
prepend_path("PYTHONHOME", prefix)
-- 自定义环境变量
setenv("PYTHON_VERSION", "3.10.12")
setenv("PYTHON_BIN", bin_path .. "/python3.10")
-- 7. 命令别名(可选)
alias("python", bin_path .. "/python3.10")
alias("pip", bin_path .. "/pip3.10")
alias("python3", bin_path .. "/python3.10")
-- 8. 用户自定义扩展(可选,适配个性化需求)
-- 允许用户通过环境变量自定义额外路径
local user_python_path = os.getenv("USER_PYTHON_PATH")
if user_python_path then
prepend_path("PYTHONPATH", user_python_path)
LmodWarning("已添加用户自定义Python路径:" .. user_python_path)
end
-- 9. 卸载/清理逻辑(可选,Lmod自动反向操作,可自定义)
if mode() == "unload" then
-- 卸载时提示
LmodMessage("已卸载Python 3.10,恢复系统默认Python环境")
-- 可选:清理用户临时设置的变量
unsetenv("USER_PYTHON_PATH")
end
-- 10. 兼容性处理(可选,适配旧系统)
-- 检查系统版本(示例:CentOS 7+)
local os_release = io.popen("cat /etc/centos-release | grep -o '[0-9]\\+' | head -1"):read("*a"):gsub("\n", "")
if tonumber(os_release) < 7 then
LmodWarning("CentOS " .. os_release .. " 可能存在兼容性问题,建议升级到CentOS 7+")
end