dsh-scnet 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -5
- package/index.mjs +15 -7
- package/package.json +4 -3
- package/skills/scnet-hpc/SKILL.md +22 -24
- package/skills/scnet-hpc/clusters/_template.conf +1 -0
- package/skills/scnet-hpc/references/quickstart-en.md +123 -0
- package/skills/scnet-hpc/references/software-compatibility.md +29 -0
- package/skills/scnet-hpc/scripts/_common.sh +9 -1
- package/skills/scnet-hpc/scripts/new-job.sh +42 -6
- package/skills/scnet-hpc/scripts/run-compute-probe.sh +17 -5
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<h1 align="center">dsh-scnet</h1>
|
|
2
2
|
|
|
3
|
-
<p align="center">在 DeepSeek Harness 里操作超算互联网(
|
|
3
|
+
<p align="center">在 DeepSeek Harness 里操作超算互联网(SCNet)集群:配 SSH、生成 CPU/DCU Slurm 作业、探测/刷新集群、运行计算节点探针、排查失败,附海光 DCU/DTK 知识和英文快速指南。</p>
|
|
4
4
|
|
|
5
5
|
## 这是什么
|
|
6
6
|
|
|
@@ -31,6 +31,7 @@ git 源、本地目录安装以及验证步骤见 [INSTALL.md](./INSTALL.md)。
|
|
|
31
31
|
| zzeshell | 超算互联网 · 郑州 | 海光 BW1000 DCU (gfx936) ×8, 64GB/卡 |
|
|
32
32
|
| kseshell | 超算互联网 · 昆山 | 海光 Z100 DCU (gfx906) ×4, 16GB/卡 |
|
|
33
33
|
| wuzhshell | 超算互联网 · 乌镇 | 海光 Z100 DCU (gfx906) ×4, 16GB/卡 |
|
|
34
|
+
| xianshell | 超算互联网 · 西安 | 海光 Z100 DCU (gfx906) ×4, 16GB/卡 |
|
|
34
35
|
|
|
35
36
|
### Tools
|
|
36
37
|
|
|
@@ -38,7 +39,7 @@ git 源、本地目录安装以及验证步骤见 [INSTALL.md](./INSTALL.md)。
|
|
|
38
39
|
|---|---|
|
|
39
40
|
| scnet_list_clusters | 列出已配置的集群 profile |
|
|
40
41
|
| scnet_show_cluster | 读取指定集群的完整参数 |
|
|
41
|
-
| scnet_generate_job | 按 profile
|
|
42
|
+
| scnet_generate_job | 按 profile 生成加速器或 CPU-only Slurm 作业,支持显式分区覆盖 |
|
|
42
43
|
| scnet_setup_ssh | 配置本地到集群的 SSH 连接 |
|
|
43
44
|
| scnet_probe_cluster | 探测新集群并生成 profile |
|
|
44
45
|
| scnet_refresh_cluster | 动态刷新已有集群的规则缓存 |
|
|
@@ -60,7 +61,8 @@ git 源、本地目录安装以及验证步骤见 [INSTALL.md](./INSTALL.md)。
|
|
|
60
61
|
│ ├── clusters/
|
|
61
62
|
│ │ ├── zzeshell.conf
|
|
62
63
|
│ │ ├── kseshell.conf
|
|
63
|
-
│ │
|
|
64
|
+
│ │ ├── wuzhshell.conf
|
|
65
|
+
│ │ └── xianshell.conf
|
|
64
66
|
│ ├── scripts/
|
|
65
67
|
│ └── references/
|
|
66
68
|
├── sync.sh # 从 canonical 仓库同步
|
|
@@ -76,7 +78,7 @@ git 源、本地目录安装以及验证步骤见 [INSTALL.md](./INSTALL.md)。
|
|
|
76
78
|
本仓库是发布面,知识内容(`skills/scnet-hpc/` 下的 SKILL.md、clusters、references、scripts)从 canonical 仓库 `lql341/scnet-hpc` 同步:
|
|
77
79
|
|
|
78
80
|
```sh
|
|
79
|
-
./sync.sh #
|
|
81
|
+
./sync.sh # 当前本机布局默认 ../../skills/scnet-hpc
|
|
80
82
|
./sync.sh --src /path/to/scnet-hpc
|
|
81
83
|
```
|
|
82
84
|
|
|
@@ -88,7 +90,7 @@ git 源、本地目录安装以及验证步骤见 [INSTALL.md](./INSTALL.md)。
|
|
|
88
90
|
- 仓库不含私钥、token、用户名、密钥指纹。
|
|
89
91
|
- `scnet_setup_ssh` 会写入 `~/.ssh/`,调用前确认私钥路径和集群。
|
|
90
92
|
- `scnet_generate_job` 生成的 `.slurm` 可能含本机用户名,`.gitignore` 已排除。
|
|
91
|
-
-
|
|
93
|
+
- SSH 接入端点仅使用平台面向用户公开提供的信息,由 canonical 仓库维护。
|
|
92
94
|
- `scnet_refresh_cluster` / `scnet_run_compute_probe` 会 SSH 到远端并可能提交作业;运行前确认集群和副作用。
|
|
93
95
|
- `clusters/.cache/` 是本机动态探测缓存,`.gitignore` 已排除,不应提交。
|
|
94
96
|
|
package/index.mjs
CHANGED
|
@@ -12,12 +12,12 @@ const SKILL_DIR = join(__dirname, 'skills', 'scnet-hpc')
|
|
|
12
12
|
const SCRIPTS_DIR = join(SKILL_DIR, 'scripts')
|
|
13
13
|
const CLUSTERS_DIR = join(SKILL_DIR, 'clusters')
|
|
14
14
|
|
|
15
|
-
function runBash(script, args, timeoutMs = 120000) {
|
|
15
|
+
function runBash(script, args, timeoutMs = 120000, cwd = SKILL_DIR) {
|
|
16
16
|
return new Promise((resolve) => {
|
|
17
17
|
execFile(
|
|
18
18
|
'bash',
|
|
19
19
|
[script, ...args],
|
|
20
|
-
{ cwd
|
|
20
|
+
{ cwd, timeout: timeoutMs, maxBuffer: 16 * 1024 * 1024 },
|
|
21
21
|
(error, stdout, stderr) => {
|
|
22
22
|
const code = error ? (typeof error.code === 'number' ? error.code : 1) : 0
|
|
23
23
|
resolve({
|
|
@@ -126,7 +126,7 @@ export function apply(ctx) {
|
|
|
126
126
|
defineTool({
|
|
127
127
|
name: 'scnet_generate_job',
|
|
128
128
|
description:
|
|
129
|
-
'
|
|
129
|
+
'按目标集群约束生成 Slurm 作业脚本。支持加速器作业、cpu_only CPU 分区和显式 partition 覆盖;自动计算内存、按需申请 GRES、加载 module、设置离线环境并传播退出码。',
|
|
130
130
|
parameters: {
|
|
131
131
|
name: { type: 'string', required: true, description: '作业名(slurm --job-name 和输出文件名)' },
|
|
132
132
|
accelerators: { type: 'string', description: '加速器数量,默认 1' },
|
|
@@ -134,6 +134,8 @@ export function apply(ctx) {
|
|
|
134
134
|
time: { type: 'string', description: '时长,默认 00:20:00,格式 HH:MM:SS 或 D-HH:MM:SS' },
|
|
135
135
|
cluster: { type: 'string', description: '集群短名;省略时若只有一个 profile 则自动选择' },
|
|
136
136
|
remote_user: { type: 'string', description: '远端用户名;与本地不同时填写(日志路径需要真实用户名)' },
|
|
137
|
+
cpu_only: { type: 'boolean', description: '使用 profile 的 PARTITION_CPU 且不申请 GRES(默认否)' },
|
|
138
|
+
partition: { type: 'string', description: '显式覆盖目标 Slurm 分区;需自行确认该分区的 GRES 规则' },
|
|
137
139
|
refresh: { type: 'boolean', description: '是否在生成前运行 refresh-cluster.sh 刷新动态规则(默认否)' },
|
|
138
140
|
no_auto: { type: 'boolean', description: '是否忽略 clusters/.cache/*.auto.conf 动态缓存(默认否)' },
|
|
139
141
|
},
|
|
@@ -155,15 +157,21 @@ export function apply(ctx) {
|
|
|
155
157
|
if (cluster) argv.push('--cluster', cluster)
|
|
156
158
|
const remoteUser = String(args.remote_user || '').trim()
|
|
157
159
|
if (remoteUser) argv.push('--user', remoteUser)
|
|
160
|
+
if (args.cpu_only === true) argv.push('--cpu-only')
|
|
161
|
+
const partition = String(args.partition || '').trim()
|
|
162
|
+
if (partition) argv.push('--partition', partition)
|
|
158
163
|
if (args.refresh === true) argv.push('--refresh')
|
|
159
164
|
if (args.no_auto === true) argv.push('--no-auto')
|
|
160
165
|
argv.push(nameVal)
|
|
161
|
-
|
|
162
|
-
if (cpus)
|
|
163
|
-
|
|
166
|
+
const time = String(args.time || '').trim()
|
|
167
|
+
if (accelerators || cpus || time) {
|
|
168
|
+
argv.push(accelerators?.value || (args.cpu_only === true ? '0' : '1'))
|
|
169
|
+
}
|
|
170
|
+
if (cpus || time) argv.push(cpus?.value || '8')
|
|
171
|
+
if (time) argv.push(time)
|
|
164
172
|
|
|
165
173
|
const timeoutMs = args.refresh === true ? 240000 : 30000
|
|
166
|
-
const res = await runBash(join(SCRIPTS_DIR, 'new-job.sh'), argv, timeoutMs)
|
|
174
|
+
const res = await runBash(join(SCRIPTS_DIR, 'new-job.sh'), argv, timeoutMs, process.cwd())
|
|
167
175
|
if (res.ok) return res.stdout.trim() || res.stderr.trim()
|
|
168
176
|
return `生成失败(exit ${res.code}):\n${res.stderr.trim() || res.stdout.trim()}`
|
|
169
177
|
},
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-scnet",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "DeepSeek Harness
|
|
3
|
+
"version": "0.4.0",
|
|
4
|
+
"description": "DeepSeek Harness plugin for SCNet HPC: SSH setup, CPU/DCU Slurm jobs, cluster probing, compute-node diagnostics, and Hygon DCU/DTK guidance.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./index.mjs",
|
|
7
7
|
"exports": {
|
|
@@ -40,7 +40,8 @@
|
|
|
40
40
|
"slurm",
|
|
41
41
|
"hpc",
|
|
42
42
|
"hygon",
|
|
43
|
-
"dcu"
|
|
43
|
+
"dcu",
|
|
44
|
+
"scnet"
|
|
44
45
|
],
|
|
45
46
|
"license": "MIT"
|
|
46
47
|
}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: scnet-hpc
|
|
3
|
-
description: 在超算互联网(
|
|
3
|
+
description: 在超算互联网(SCNet)集群上配置 SSH、使用 Slurm、申请 CPU/DCU 资源、提交和排查作业、安装依赖及验证国产加速器兼容性;当前深度验证以海光 DCU/DTK/gfx9xx 为主。Use for SCNet HPC tasks involving SSH setup, Slurm jobs, login versus compute nodes, CPU/DCU resource requests, Hygon DCU, DTK, gfx9xx, sbatch/srun, offline compute nodes, cluster profiles, or accelerator compatibility. Other SCNet accelerators must be verified on their target cluster.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# 国产超算集群使用规范
|
|
7
7
|
|
|
8
|
-
面向超算互联网(
|
|
8
|
+
面向超算互联网(SCNet)系列集群,当前收录节点以海光 DCU 为主。其他芯片平台
|
|
9
|
+
只复用连接、调度和验证方法,不套用海光工具链结论。**集群参数不写在文档里,存在
|
|
9
10
|
`clusters/<集群短名>.conf`**,脚本从 profile 读取,所以同一套流程能用于多个集群。
|
|
10
11
|
|
|
11
12
|
## 先确认在跟哪个集群打交道
|
|
@@ -33,6 +34,10 @@ cat clusters/<集群短名>.conf # 看具体参数
|
|
|
33
34
|
| `references/adding-cluster.md` | 新增集群的完整步骤 |
|
|
34
35
|
| `references/hygon-dcu-development.md` | 海光 DCU 开发流程、DTK 工具库与官方资源索引 |
|
|
35
36
|
| `references/software-compatibility.md` | 国产超算上的软件兼容性排查、验证分层与公开报告脱敏 |
|
|
37
|
+
| `references/quickstart-en.md` | English quick start for SSH, Slurm, CPU/DCU jobs, and troubleshooting |
|
|
38
|
+
|
|
39
|
+
用户使用英文提问或需要英文操作说明时,读取 `references/quickstart-en.md`;集群具体
|
|
40
|
+
参数仍以 `clusters/*.conf` 为准,不从英文示例猜测。
|
|
36
41
|
|
|
37
42
|
## 换机器
|
|
38
43
|
|
|
@@ -123,7 +128,8 @@ ImportError: libmsgpackc.so.2: cannot open shared object file
|
|
|
123
128
|
**不要在登录节点试 torch 代码然后困惑为什么报错。** 哪怕只想看一眼 tensor 的
|
|
124
129
|
dtype,也要走 `srun` 或 `sbatch`。
|
|
125
130
|
|
|
126
|
-
|
|
131
|
+
登录节点通常用于 `git`、文件管理、`sacct`/`squeue` 和准备依赖;能否访问软件源、
|
|
132
|
+
下载模型或执行 `pip install` 必须查看 profile 的网络字段并现场确认。
|
|
127
133
|
|
|
128
134
|
### 4. 计算节点通常无外网 —— 依赖必须预装
|
|
129
135
|
|
|
@@ -159,8 +165,12 @@ export TRANSFORMERS_OFFLINE=1
|
|
|
159
165
|
./scripts/new-job.sh <作业名> [加速器数] [cpu数] [时长]
|
|
160
166
|
./scripts/new-job.sh probe # 1 卡, 8 核, 20 分钟
|
|
161
167
|
./scripts/new-job.sh infer 8 32 01:30:00 # 8 卡, 32 核, 1.5 小时
|
|
168
|
+
./scripts/new-job.sh --cpu-only build 0 32 01:00:00
|
|
162
169
|
```
|
|
163
170
|
|
|
171
|
+
有独立 CPU 分区时使用 `--cpu-only`,脚本读取 `PARTITION_CPU` 并省略 `--gres`;
|
|
172
|
+
临时指定其他分区时使用 `--partition <名称>`。
|
|
173
|
+
|
|
164
174
|
上传后先验证配额而不真排队:
|
|
165
175
|
|
|
166
176
|
```bash
|
|
@@ -186,7 +196,7 @@ $ sacct -j <JOB_ID>
|
|
|
186
196
|
|
|
187
197
|
## 交互式调试(推荐)
|
|
188
198
|
|
|
189
|
-
|
|
199
|
+
通常比反复提交完整作业更适合试代码、查环境和验证假设;实际排队时间取决于分区负载:
|
|
190
200
|
|
|
191
201
|
```bash
|
|
192
202
|
srun -p <分区> --gres=<类型>:1 --cpus-per-task=8 --mem=30gb --time=00:10:00 \
|
|
@@ -223,25 +233,11 @@ sinfo -p <分区> -o "%n %c %m %G %t" # 节点资源和状态
|
|
|
223
233
|
先读 `references/hygon-dcu-development.md`。用它定位官方资料,再以目标集群的
|
|
224
234
|
module、计算节点探针和 profile 为准;不要把网页当前版本直接覆盖到集群环境。
|
|
225
235
|
|
|
226
|
-
**不要假设加速器支持什么。**
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
| 能力 | 结果 |
|
|
233
|
-
|---|---|
|
|
234
|
-
| FP8 存储 + `.to(bfloat16)` 转换 | ✅ |
|
|
235
|
-
| `torch._scaled_mm`(硬件 FP8 matmul) | ❌ 需 SM89+/SM90+ 或 ROCm MI300+ |
|
|
236
|
-
| **Triton** | ❌ `libamdhip64.so` 缺 `hipDrvLaunchKernelEx` |
|
|
237
|
-
| bitsandbytes 4-bit / 8-bit | ✅ 需补丁 / ❌ 无 INT8 algo |
|
|
238
|
-
|
|
239
|
-
Triton 那条影响最大:**任何依赖 Triton kernel 的推理框架都跑不起来**
|
|
240
|
-
——SGLang FP8 路径、vLLM ROCm MoE 后端、transformers `finegrained-fp8` 都在此列。
|
|
241
|
-
遇到这类需求先想清楚有没有纯 PyTorch 的退路,别花时间在框架适配上。
|
|
242
|
-
|
|
243
|
-
碰到新集群时,用一个探针作业实测这些能力,把结论写回 profile 的
|
|
244
|
-
`KNOWN_LIMITATIONS`,别让下一个人重踩。
|
|
236
|
+
**不要假设加速器支持什么。** 即使同属 SCNet,不同芯片、DTK/驱动和框架版本的
|
|
237
|
+
能力也可能不同。先读取目标 profile 的 `KNOWN_LIMITATIONS`,再用计算节点探针验证
|
|
238
|
+
设备枚举、dtype、kernel、通信和真实功能。海光 DCU/DTK 的开发资料入口见
|
|
239
|
+
`references/hygon-dcu-development.md`;软件兼容性验证顺序见
|
|
240
|
+
`references/software-compatibility.md`。
|
|
245
241
|
|
|
246
242
|
## 排查失败
|
|
247
243
|
|
|
@@ -266,6 +262,8 @@ Triton 那条影响最大:**任何依赖 Triton kernel 的推理框架都跑
|
|
|
266
262
|
|
|
267
263
|
将集群实测结果写入公开报告或仓库前,保留环境、方法、版本、结果和限制,移除或替换以下信息:用户名、SSH 主机/端口、内部域名、IP、节点名、作业编号、绝对家目录和私有镜像地址。可用 `<USER_HOME>`、`<DTK_ROOT>`、`<CLUSTER_HOST>`、`已脱敏作业` 等占位符。
|
|
268
264
|
|
|
269
|
-
|
|
265
|
+
公开技术记录按“环境与版本 → 问题与证据 → 解决方法 → 验证结果 → 已知限制 →
|
|
266
|
+
可复用经验”组织。结论必须标明测试环境、验证范围和未验证边界;视觉样式由具体发布
|
|
267
|
+
项目决定,不写进本 skill。
|
|
270
268
|
|
|
271
269
|
详细的兼容性排查和报告模板见 `references/software-compatibility.md`。
|
|
@@ -24,6 +24,7 @@ SCHEDULER="slurm"
|
|
|
24
24
|
PARTITION=""
|
|
25
25
|
|
|
26
26
|
DEF_MEM_PER_CPU="" # MB。scontrol show partition <名> 里的 DefMemPerCPU
|
|
27
|
+
DEF_MEM_PER_CPU_CPU="" # 可选:CPU 分区不同于默认分区时填写
|
|
27
28
|
MIN_GRES="" # QOS 强制的最小 GRES,如 "dcu:1";无则留空
|
|
28
29
|
GRES_TYPE="" # "dcu" / "gpu" / "npu" 等
|
|
29
30
|
MAX_WALLTIME=""
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# SCNet HPC English Quick Start
|
|
2
|
+
|
|
3
|
+
This guide covers the common workflow for SCNet clusters. Current repository profiles focus
|
|
4
|
+
mainly on Hygon DCU/DTK systems. Always read the target profile before using a partition,
|
|
5
|
+
memory value, accelerator type, module, or home-directory path.
|
|
6
|
+
|
|
7
|
+
## 1. Inspect the available profiles
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
ls clusters/*.conf
|
|
11
|
+
sed -n '1,220p' clusters/<cluster>.conf
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Check at least `PARTITION`, `PARTITION_CPU`, `GRES_TYPE`, `MIN_GRES`,
|
|
15
|
+
`DEF_MEM_PER_CPU`, `MODULE_LOADS`, `COMPUTE_NODE_OFFLINE`, and
|
|
16
|
+
`KNOWN_LIMITATIONS`.
|
|
17
|
+
|
|
18
|
+
## 2. Install the skill
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
git clone https://github.com/lql341/scnet-hpc.git
|
|
22
|
+
cd scnet-hpc
|
|
23
|
+
./scripts/install.sh
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
The repository is designed to be shared by Codex, Claude Code, and OpenCode. Installation
|
|
27
|
+
paths depend on the local agent layout; `install.sh --link` is useful when developing the
|
|
28
|
+
skill from a shared source directory.
|
|
29
|
+
|
|
30
|
+
## 3. Configure SSH
|
|
31
|
+
|
|
32
|
+
Download the private key from the SCNet console, then run:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
./scripts/setup-ssh.sh --cluster <cluster> <private-key-file> <username>
|
|
36
|
+
ssh <cluster>
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
The script installs the key under `~/.ssh`, adds an SSH config entry, and tests the
|
|
40
|
+
connection. Do not commit private keys, usernames, internal node names, or personal paths.
|
|
41
|
+
|
|
42
|
+
## 4. Generate a Slurm job
|
|
43
|
+
|
|
44
|
+
Accelerator job:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
./scripts/new-job.sh --cluster <cluster> myjob 1 8 00:20:00
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
CPU-only job, when the profile defines `PARTITION_CPU`:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
./scripts/new-job.sh --cluster <cluster> --cpu-only build 0 32 01:00:00
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Explicit partition override:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
./scripts/new-job.sh --cluster <cluster> --partition <partition> probe 1 8 00:10:00
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
The generator calculates a safe memory request from the profile, adds GRES only when
|
|
63
|
+
needed, configures a shared temporary directory, enables offline mode when appropriate,
|
|
64
|
+
and propagates the program exit code.
|
|
65
|
+
|
|
66
|
+
Create the remote log directory before submission:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
ssh <cluster> 'mkdir -p ~/scripts/logs'
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Upload the generated script and validate the request before queueing it:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
scp myjob.slurm <cluster>:~/scripts/
|
|
76
|
+
ssh <cluster> 'sbatch --test-only ~/scripts/myjob.slurm'
|
|
77
|
+
ssh <cluster> 'sbatch ~/scripts/myjob.slurm'
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## 5. Monitor and debug
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
squeue -u "$USER"
|
|
84
|
+
squeue -j <job-id> --start
|
|
85
|
+
sacct -j <job-id> --format=JobID,State%14,ExitCode,Elapsed,MaxRSS -P
|
|
86
|
+
scancel <job-id>
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Do not trust `COMPLETED` alone. Read both stdout and stderr, and make sure the job script
|
|
90
|
+
ends with the real program exit code.
|
|
91
|
+
|
|
92
|
+
For short experiments, request an interactive allocation with `srun`. Use the partition,
|
|
93
|
+
GRES type, CPU count, and memory limit from the target profile.
|
|
94
|
+
|
|
95
|
+
## 6. SCNet environment rules
|
|
96
|
+
|
|
97
|
+
- Login nodes are for source management, dependency preparation, file operations, and
|
|
98
|
+
scheduler commands. Whether package indexes and model sites are reachable is cluster-specific.
|
|
99
|
+
- Compute nodes are often offline. Download dependencies, models, and kernels before the job.
|
|
100
|
+
- A DCU partition may require at least one accelerator even for a CPU-oriented command.
|
|
101
|
+
- Memory limits may be tied to `cpus-per-task × DefMemPerCPU`.
|
|
102
|
+
- Do not use system `/tmp` for files that must be shared across login and compute nodes.
|
|
103
|
+
- Loading a module on a login node does not prove that the runtime works on a compute node.
|
|
104
|
+
- Hygon DCU software capabilities depend on the exact DTK, driver, framework, and `gfx` target.
|
|
105
|
+
|
|
106
|
+
## 7. Refresh and probe a cluster
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
./scripts/refresh-cluster.sh --cluster <cluster> --dry-run
|
|
110
|
+
./scripts/refresh-cluster.sh --cluster <cluster>
|
|
111
|
+
./scripts/refresh-cluster.sh --cluster <cluster> --compute
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
The default refresh performs read-only login-node checks. `--compute` submits a small Slurm
|
|
115
|
+
job to test the accelerator runtime and therefore consumes cluster resources.
|
|
116
|
+
|
|
117
|
+
For detailed diagnostics, see the Chinese references:
|
|
118
|
+
|
|
119
|
+
- `references/setup.md`
|
|
120
|
+
- `references/environment.md`
|
|
121
|
+
- `references/troubleshooting.md`
|
|
122
|
+
- `references/software-compatibility.md`
|
|
123
|
+
- `references/hygon-dcu-development.md`
|
|
@@ -8,6 +8,35 @@
|
|
|
8
8
|
4. **依赖路径**:区分 pip/conda 解析失败、运行时动态库失败、框架 kernel 不支持和模型/数据下载失败。
|
|
9
9
|
5. **端到端结果**:记录成功条件、性能、显存/内存、失败日志和未验证范围。
|
|
10
10
|
|
|
11
|
+
### 编译型软件的分层验证
|
|
12
|
+
|
|
13
|
+
- **把编译放到计算节点**:C++/HIP 大型构建的峰值内存可能远高于登录节点限额。
|
|
14
|
+
编译器进程被 OOM kill 时,先换到有明确内存配额的计算作业,不要立即归因于源码。
|
|
15
|
+
- **只生成目标架构**:显式设置目标 `gfx` 架构。默认同时生成多个架构会成倍增加
|
|
16
|
+
编译时间、产物体积和峰值内存。
|
|
17
|
+
- **升级工具链后重跑最小构建**:DTK/编译器升级可能改变 wrapper 头、host/device
|
|
18
|
+
编译模式或默认链接路径。保存 verbose compile command,与上一版本逐项比较。
|
|
19
|
+
- **区分节点环境**:登录/CPU 节点可能加载得到 module,却缺少只在加速器节点完整
|
|
20
|
+
可见的 HSA/HIP 库或符号链接。以目标计算节点解析到的真实库文件为准,必要时通过
|
|
21
|
+
CMake cache 变量显式传入,不创建全局假链接。
|
|
22
|
+
- **先串行能力、后并行能力**:先完成无 MPI 的单卡最小构建和功能验证,再开启 MPI,
|
|
23
|
+
最后测试 GPU-aware 通信与多卡扩展,避免把编译器、运行库和通信栈问题混在一起。
|
|
24
|
+
|
|
25
|
+
### GPU-aware MPI 的验证边界
|
|
26
|
+
|
|
27
|
+
系统 MPI 能启动多进程,不代表它带加速器感知能力。先记录 MPI 构建参数,并做
|
|
28
|
+
GPU-aware on/off 对照。单节点验证可先固定共享内存与 self 传输,减少 UCX/IB
|
|
29
|
+
站点配置带来的变量;这只能证明单节点路径,不能外推到跨节点通信。
|
|
30
|
+
|
|
31
|
+
多卡扩展通常同时依赖足够大的问题规模、较高的计算/通信比以及可用的 GPU-aware
|
|
32
|
+
路径。小问题或低计算密度任务扩展不佳,不足以单独证明硬件或 MPI 配置错误。
|
|
33
|
+
|
|
34
|
+
### 数值与性能验收
|
|
35
|
+
|
|
36
|
+
加速器移植至少应同时报告:CPU/参考实现的关键数值偏差、守恒量或长期稳定性、
|
|
37
|
+
单卡问题规模扫描、固定规模的 1/2/单节点全卡强扩展、GPU-aware on/off 对照、
|
|
38
|
+
峰值内存/显存,以及每项测试的退出码和完整日志。性能通过不能替代正确性验证。
|
|
39
|
+
|
|
11
40
|
### 已验证的典型边界
|
|
12
41
|
|
|
13
42
|
- **gfx936 / BW1000**:Triton、硬件 FP8 `torch._scaled_mm`、部分 bitsandbytes INT8 路径可能不可用;纯 PyTorch 软件反量化可作为推理兜底,但需要单独做性能和精度验证。
|
|
@@ -98,9 +98,17 @@ parse_cluster_arg() {
|
|
|
98
98
|
REST=()
|
|
99
99
|
while [ $# -gt 0 ]; do
|
|
100
100
|
case "$1" in
|
|
101
|
-
--cluster)
|
|
101
|
+
--cluster)
|
|
102
|
+
[ $# -ge 2 ] || die "--cluster 缺少参数"
|
|
103
|
+
CLUSTER="$2"
|
|
104
|
+
shift 2
|
|
105
|
+
;;
|
|
102
106
|
--cluster=*) CLUSTER="${1#*=}"; shift ;;
|
|
103
107
|
*) REST+=("$1"); shift ;;
|
|
104
108
|
esac
|
|
105
109
|
done
|
|
110
|
+
if [ -n "$CLUSTER" ]; then
|
|
111
|
+
[[ "$CLUSTER" =~ ^[A-Za-z0-9][A-Za-z0-9._-]*$ ]] \
|
|
112
|
+
|| die "集群短名包含不安全字符"
|
|
113
|
+
fi
|
|
106
114
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
# 生成一个符合目标集群所有约束的作业脚本骨架。
|
|
3
3
|
#
|
|
4
|
-
# ./new-job.sh [--cluster <集群短名>]
|
|
4
|
+
# ./new-job.sh [--cluster <集群短名>] [--cpu-only] [--partition <分区>] \
|
|
5
|
+
# <作业名> [加速器数] [cpu数] [时长]
|
|
5
6
|
#
|
|
6
7
|
# 内存按 cpus × DEF_MEM_PER_CPU 自动取安全值,避免手算出错。
|
|
7
8
|
|
|
@@ -16,11 +17,16 @@ set -- "${REST[@]+${REST[@]}}"
|
|
|
16
17
|
REMOTE_USER=""
|
|
17
18
|
REFRESH=no
|
|
18
19
|
USE_AUTO=yes
|
|
20
|
+
CPU_ONLY=no
|
|
21
|
+
PARTITION_OVERRIDE=""
|
|
19
22
|
ARGS=()
|
|
20
23
|
while [ $# -gt 0 ]; do
|
|
21
24
|
case "$1" in
|
|
22
|
-
--user) REMOTE_USER="$
|
|
25
|
+
--user) [ $# -ge 2 ] || die "--user 缺少参数"; REMOTE_USER="$2"; shift 2 ;;
|
|
23
26
|
--user=*) REMOTE_USER="${1#*=}"; shift ;;
|
|
27
|
+
--partition) [ $# -ge 2 ] || die "--partition 缺少参数"; PARTITION_OVERRIDE="$2"; shift 2 ;;
|
|
28
|
+
--partition=*) PARTITION_OVERRIDE="${1#*=}"; shift ;;
|
|
29
|
+
--cpu-only) CPU_ONLY=yes; shift ;;
|
|
24
30
|
--refresh) REFRESH=yes; shift ;;
|
|
25
31
|
--no-auto) USE_AUTO=no; shift ;;
|
|
26
32
|
*) ARGS+=("$1"); shift ;;
|
|
@@ -35,17 +41,32 @@ TIME="${4:-00:20:00}"
|
|
|
35
41
|
|
|
36
42
|
if [ -z "$NAME" ]; then
|
|
37
43
|
cat >&2 <<EOF
|
|
38
|
-
用法: $0 [--cluster <集群短名>] [--user <远端用户名>] [--
|
|
44
|
+
用法: $0 [--cluster <集群短名>] [--user <远端用户名>] [--cpu-only]
|
|
45
|
+
[--partition <分区>] [--refresh|--no-auto] <作业名> [加速器数] [cpu数] [时长]
|
|
39
46
|
|
|
40
47
|
例子:
|
|
41
48
|
$0 probe # 1 卡, 8 核, 20 分钟(探针)
|
|
42
49
|
$0 infer 8 32 01:30:00 # 8 卡, 32 核, 1.5 小时(大模型)
|
|
50
|
+
$0 --cpu-only build 0 32 01:00:00 # 使用 profile 的 CPU 分区,不申请加速器
|
|
43
51
|
|
|
44
52
|
可用集群: $(list_clusters | tr '\n' ' ')
|
|
45
53
|
EOF
|
|
46
54
|
exit 1
|
|
47
55
|
fi
|
|
48
56
|
|
|
57
|
+
[[ "$NAME" =~ ^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$ ]] \
|
|
58
|
+
|| die "作业名只允许 1-64 个字母、数字、点、下划线或连字符,且必须以字母或数字开头"
|
|
59
|
+
[[ "$ACCEL" =~ ^[0-9]+$ ]] || die "加速器数必须是非负整数"
|
|
60
|
+
[[ "$CPUS" =~ ^[1-9][0-9]*$ ]] || die "CPU 数必须是正整数"
|
|
61
|
+
[[ "$TIME" =~ ^([0-9]+-)?[0-9]{1,2}:[0-9]{2}:[0-9]{2}$ ]] \
|
|
62
|
+
|| die "时长格式应为 HH:MM:SS 或 D-HH:MM:SS"
|
|
63
|
+
if [ -n "$REMOTE_USER" ]; then
|
|
64
|
+
[[ "$REMOTE_USER" =~ ^[A-Za-z0-9._-]+$ ]] || die "远端用户名包含不安全字符"
|
|
65
|
+
fi
|
|
66
|
+
if [ -n "$PARTITION_OVERRIDE" ]; then
|
|
67
|
+
[[ "$PARTITION_OVERRIDE" =~ ^[A-Za-z0-9._-]+$ ]] || die "分区名包含不安全字符"
|
|
68
|
+
fi
|
|
69
|
+
|
|
49
70
|
if [ "$REFRESH" = yes ]; then
|
|
50
71
|
"$REPO_ROOT/scripts/refresh-cluster.sh" --cluster "${CLUSTER:-}"
|
|
51
72
|
fi
|
|
@@ -56,6 +77,17 @@ load_cluster "$CLUSTER"
|
|
|
56
77
|
[ "${SCHEDULER:-slurm}" = "slurm" ] \
|
|
57
78
|
|| die "暂只支持 slurm,${CLUSTER_ID} 用的是 ${SCHEDULER}"
|
|
58
79
|
|
|
80
|
+
if [ "$CPU_ONLY" = yes ]; then
|
|
81
|
+
[ -n "${PARTITION_CPU:-}" ] \
|
|
82
|
+
|| die "${CLUSTER_ID} profile 未定义 PARTITION_CPU,不能使用 --cpu-only"
|
|
83
|
+
EFFECTIVE_PARTITION="${PARTITION_OVERRIDE:-$PARTITION_CPU}"
|
|
84
|
+
ACCEL=0
|
|
85
|
+
[ -n "${DEF_MEM_PER_CPU_CPU:-}" ] && DEF_MEM_PER_CPU="$DEF_MEM_PER_CPU_CPU"
|
|
86
|
+
else
|
|
87
|
+
EFFECTIVE_PARTITION="${PARTITION_OVERRIDE:-${PARTITION:-}}"
|
|
88
|
+
fi
|
|
89
|
+
[ -n "$EFFECTIVE_PARTITION" ] || die "目标分区为空,请补 profile 或使用 --partition"
|
|
90
|
+
|
|
59
91
|
# 内存上限 = cpus × DEF_MEM_PER_CPU,留 1GB 余量避免边界抖动
|
|
60
92
|
if [ -n "${DEF_MEM_PER_CPU:-}" ]; then
|
|
61
93
|
MEM_MB=$(( CPUS * DEF_MEM_PER_CPU ))
|
|
@@ -70,15 +102,19 @@ fi
|
|
|
70
102
|
|
|
71
103
|
# QOS 强制申请加速器时必须写 --gres
|
|
72
104
|
GRES_LINE=""
|
|
73
|
-
if [ -n "${GRES_TYPE:-}" ]; then
|
|
105
|
+
if [ "$CPU_ONLY" != yes ] && [ -n "${GRES_TYPE:-}" ] && [ "$ACCEL" -gt 0 ]; then
|
|
74
106
|
GRES_LINE="#SBATCH --gres=${GRES_TYPE}:${ACCEL}"
|
|
75
107
|
[ -n "${MIN_GRES:-}" ] && GRES_LINE="$GRES_LINE # 必须:QOS 要求最少 ${MIN_GRES}"
|
|
76
108
|
fi
|
|
109
|
+
if [ "$CPU_ONLY" != yes ] && [ -n "${MIN_GRES:-}" ] && [ "$ACCEL" -eq 0 ]; then
|
|
110
|
+
die "默认/指定分区要求至少 ${MIN_GRES};请申请加速器或使用 --cpu-only"
|
|
111
|
+
fi
|
|
77
112
|
|
|
78
113
|
# 远端用户名。#SBATCH 是注释行,Slurm 不做变量展开 —— 日志路径里写 $USER
|
|
79
114
|
# 会被当成字面量目录名,作业以 exit 53 失败且不产生日志。所以这里必须展开成
|
|
80
115
|
# 真实用户名。默认取本地用户名,不同时用 --user 覆盖。
|
|
81
116
|
REMOTE_USER="${REMOTE_USER:-${REMOTE_USER_DETECTED:-$(whoami)}}"
|
|
117
|
+
[[ "$REMOTE_USER" =~ ^[A-Za-z0-9._-]+$ ]] || die "探测到的远端用户名包含不安全字符,请用 --user 显式指定"
|
|
82
118
|
HOME_DIR="${HOME_BASE}/${REMOTE_USER}"
|
|
83
119
|
|
|
84
120
|
# 脚本体(非 #SBATCH 行)里可以正常用 $USER
|
|
@@ -105,7 +141,7 @@ cat > "$OUT" <<EOF
|
|
|
105
141
|
# shell 里定义,用普通 "#!/bin/bash" 会让 module load 静默失败 —— 作业照样
|
|
106
142
|
# 返回 0,但 ROCM_PATH 不设置、rocminfo/rocm-smi 无输出。实测于昆山集群。
|
|
107
143
|
#SBATCH --job-name=${NAME}
|
|
108
|
-
#SBATCH --partition=${
|
|
144
|
+
#SBATCH --partition=${EFFECTIVE_PARTITION}
|
|
109
145
|
${GRES_LINE}
|
|
110
146
|
#SBATCH --nodes=1
|
|
111
147
|
#SBATCH --ntasks-per-node=1
|
|
@@ -153,7 +189,7 @@ sed -i.bak '/^$/N;/^\n$/D' "$OUT" 2>/dev/null && rm -f "$OUT.bak"
|
|
|
153
189
|
|
|
154
190
|
echo "已生成 $OUT"
|
|
155
191
|
echo " 集群=${CLUSTER_ID} ${GRES_TYPE:-加速器}=${ACCEL} CPU=${CPUS} 内存=${MEM_NOTE} 时长=${TIME}"
|
|
156
|
-
echo " 分区=${
|
|
192
|
+
echo " 分区=${EFFECTIVE_PARTITION} 模式=$([ "$CPU_ONLY" = yes ] && echo CPU || echo accelerator) 节点数=${NODE_COUNT:-未探测}(来源:${NODE_COUNT_SOURCE:-profile/cache})"
|
|
157
193
|
echo " 日志目录=${HOME_DIR}/scripts/logs(用户名 ${REMOTE_USER},不对请加 --user)"
|
|
158
194
|
echo
|
|
159
195
|
echo "上传并提交:"
|
|
@@ -19,21 +19,32 @@ PYTHON_BIN=""
|
|
|
19
19
|
|
|
20
20
|
while [ $# -gt 0 ]; do
|
|
21
21
|
case "$1" in
|
|
22
|
-
--cpus) CPUS="$
|
|
22
|
+
--cpus) [ $# -ge 2 ] || die "--cpus 缺少参数"; CPUS="$2"; shift 2 ;;
|
|
23
23
|
--cpus=*) CPUS="${1#*=}"; shift ;;
|
|
24
|
-
--time) TIME="$
|
|
24
|
+
--time) [ $# -ge 2 ] || die "--time 缺少参数"; TIME="$2"; shift 2 ;;
|
|
25
25
|
--time=*) TIME="${1#*=}"; shift ;;
|
|
26
|
-
--accelerators) ACCEL="$
|
|
26
|
+
--accelerators) [ $# -ge 2 ] || die "--accelerators 缺少参数"; ACCEL="$2"; shift 2 ;;
|
|
27
27
|
--accelerators=*) ACCEL="${1#*=}"; shift ;;
|
|
28
|
-
--user) REMOTE_USER="$
|
|
28
|
+
--user) [ $# -ge 2 ] || die "--user 缺少参数"; REMOTE_USER="$2"; shift 2 ;;
|
|
29
29
|
--user=*) REMOTE_USER="${1#*=}"; shift ;;
|
|
30
|
-
--python) PYTHON_BIN="$
|
|
30
|
+
--python) [ $# -ge 2 ] || die "--python 缺少参数"; PYTHON_BIN="$2"; shift 2 ;;
|
|
31
31
|
--python=*) PYTHON_BIN="${1#*=}"; shift ;;
|
|
32
32
|
-h|--help) sed -n '2,10p' "$0" | sed 's/^# \?//'; exit 0 ;;
|
|
33
33
|
*) die "未知参数: $1" ;;
|
|
34
34
|
esac
|
|
35
35
|
done
|
|
36
36
|
|
|
37
|
+
[[ "$CPUS" =~ ^[1-9][0-9]*$ ]] || die "CPU 数必须是正整数"
|
|
38
|
+
[[ "$ACCEL" =~ ^[1-9][0-9]*$ ]] || die "加速器数必须是正整数"
|
|
39
|
+
[[ "$TIME" =~ ^([0-9]+-)?[0-9]{1,2}:[0-9]{2}:[0-9]{2}$ ]] \
|
|
40
|
+
|| die "时长格式应为 HH:MM:SS 或 D-HH:MM:SS"
|
|
41
|
+
if [ -n "$REMOTE_USER" ]; then
|
|
42
|
+
[[ "$REMOTE_USER" =~ ^[A-Za-z0-9._-]+$ ]] || die "远端用户名包含不安全字符"
|
|
43
|
+
fi
|
|
44
|
+
if [ -n "$PYTHON_BIN" ]; then
|
|
45
|
+
[[ "$PYTHON_BIN" =~ ^[A-Za-z0-9_./-]+$ ]] || die "Python 命令包含不安全字符"
|
|
46
|
+
fi
|
|
47
|
+
|
|
37
48
|
[ -n "${CLUSTER:-}" ] || die "请用 --cluster <集群短名> 指定集群。"
|
|
38
49
|
load_cluster "$CLUSTER"
|
|
39
50
|
|
|
@@ -41,6 +52,7 @@ load_cluster "$CLUSTER"
|
|
|
41
52
|
[ -n "${PARTITION:-}" ] || die "${CLUSTER_ID} 的 PARTITION 为空,无法提交计算节点探针。"
|
|
42
53
|
|
|
43
54
|
REMOTE_USER="${REMOTE_USER:-${REMOTE_USER_DETECTED:-$(whoami)}}"
|
|
55
|
+
[[ "$REMOTE_USER" =~ ^[A-Za-z0-9._-]+$ ]] || die "探测到的远端用户名包含不安全字符,请用 --user 显式指定"
|
|
44
56
|
HOME_DIR="${HOME_BASE}/${REMOTE_USER}"
|
|
45
57
|
PROBE_DIR="${HOME_DIR}/.scnet-hpc/probes"
|
|
46
58
|
PROBE_BASE="${PROBE_DIR}/compute-probe"
|