dsh-scnet 0.2.1 → 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 CHANGED
@@ -1,6 +1,6 @@
1
1
  <h1 align="center">dsh-scnet</h1>
2
2
 
3
- <p align="center">在 DeepSeek Harness 里操作超算互联网(scnet.cn)及同类国产超算集群:配 SSH、生成 Slurm 作业、探测/刷新集群、运行计算节点探针、排查失败,附海光 DCU/DTK 知识。</p>
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 生成合规 Slurm 作业脚本 |
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
- │ │ └── wuzhshell.conf
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 # 默认 ../skills/scnet-hpc
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
- - 集群主机名/端口是平台公开信息,由 canonical 仓库维护。
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: SKILL_DIR, timeout: timeoutMs, maxBuffer: 16 * 1024 * 1024 },
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
- '按目标集群的约束生成合规的 Slurm 作业脚本(自动算 --mem、--gres、module load、离线环境变量,并在末尾写 exit $rc)。会写一个 <name>.slurm 到当前目录并返回上传/提交命令。',
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
- if (accelerators) argv.push(accelerators.value)
162
- if (cpus) argv.push(cpus.value)
163
- if (args.time && String(args.time).trim()) argv.push(String(args.time).trim())
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.2.1",
4
- "description": "DeepSeek Harness bundle plugin for SCNet (scnet.cn) and similar domestic HPC clusters: SSH setup, Slurm job generation, cluster probing/refresh, compute-node capability probes, and Hygon DCU/DTK guidance.",
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: 在超算互联网(scnet.cn)及同类国产超算集群上工作 —— 从个人电脑(macOS/Linux)配置 SSH 连接、提交和监控 Slurm 作业、交互式调试、排查作业失败、安装 Python 依赖,以及查找海光 DCU/DTK 的官方开发文档、数学库、通信库、分析调试和 CUDA 迁移工具。当任务涉及超算集群、Slurm 作业、海光 DCU / DTK / gfx9xx、DTK 工具库选型、或需要写 sbatch 脚本、判断该在登录节点还是计算节点执行某件事时使用。集群参数存在 clusters/*.conf,支持多集群。
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
- 面向超算互联网(scnet.cn)系列集群。**集群参数不写在文档里,存在
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
- 登录节点能做:`pip install`、`git`、读写文件、`sacct`/`squeue`、下载模型。
131
+ 登录节点通常用于 `git`、文件管理、`sacct`/`squeue` 和准备依赖;能否访问软件源、
132
+ 下载模型或执行 `pip install` 必须查看 profile 的网络字段并现场确认。
127
133
 
128
134
  ### 4. 计算节点通常无外网 —— 依赖必须预装
129
135
 
@@ -139,9 +145,15 @@ export HF_HUB_OFFLINE=1
139
145
  export TRANSFORMERS_OFFLINE=1
140
146
  ```
141
147
 
142
- ### 5. `/tmp` 通常不跨节点共享 —— 文件放家目录
148
+ ### 5. 测试任务的临时目录必须建在家目录
149
+
150
+ 针对任何集群提交测试或探针任务时,**不要使用 `/tmp`,也不要从根目录下创建临时
151
+ 目录**。统一在共享家目录中创建,例如 `$HOME/.scnet-hpc/tmp/$SLURM_JOB_ID`,并在
152
+ 作业中导出 `TMPDIR`、`TMP`、`TEMP` 指向该目录。这样登录节点、计算节点和后续作业
153
+ 都能访问同一份临时文件。任务结束后只清理本次作业自己的子目录。
143
154
 
144
- `TMP_SHARED=no` 时,`/tmp` 在计算节点是本地的,作业之间不可见。
155
+ `TMP_SHARED=no` 表示系统 `/tmp` 不作为跨节点共享路径使用;即使某个集群实测 `/tmp`
156
+ 可见,测试脚本仍默认遵循上述家目录规则。
145
157
 
146
158
  ### 6. 先验证二进制兼容性,再做完整安装
147
159
 
@@ -153,8 +165,12 @@ export TRANSFORMERS_OFFLINE=1
153
165
  ./scripts/new-job.sh <作业名> [加速器数] [cpu数] [时长]
154
166
  ./scripts/new-job.sh probe # 1 卡, 8 核, 20 分钟
155
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
156
169
  ```
157
170
 
171
+ 有独立 CPU 分区时使用 `--cpu-only`,脚本读取 `PARTITION_CPU` 并省略 `--gres`;
172
+ 临时指定其他分区时使用 `--partition <名称>`。
173
+
158
174
  上传后先验证配额而不真排队:
159
175
 
160
176
  ```bash
@@ -180,7 +196,7 @@ $ sacct -j <JOB_ID>
180
196
 
181
197
  ## 交互式调试(推荐)
182
198
 
183
- 比 sbatch 快得多,适合试代码、查环境、验证假设。实测约 5 秒拿到节点:
199
+ 通常比反复提交完整作业更适合试代码、查环境和验证假设;实际排队时间取决于分区负载:
184
200
 
185
201
  ```bash
186
202
  srun -p <分区> --gres=<类型>:1 --cpus-per-task=8 --mem=30gb --time=00:10:00 \
@@ -217,25 +233,11 @@ sinfo -p <分区> -o "%n %c %m %G %t" # 节点资源和状态
217
233
  先读 `references/hygon-dcu-development.md`。用它定位官方资料,再以目标集群的
218
234
  module、计算节点探针和 profile 为准;不要把网页当前版本直接覆盖到集群环境。
219
235
 
220
- **不要假设加速器支持什么。** 国产加速器(海光 DCU、寒武纪、昇腾)的软件栈往往
221
- 落后于上游,很多 CUDA/ROCm 上想当然的能力并不存在。profile 的
222
- `KNOWN_LIMITATIONS` 记录了已探明的缺口。
223
-
224
- 以 zzeshell 的海光 gfx936 为例,实测结论:
225
-
226
- | 能力 | 结果 |
227
- |---|---|
228
- | FP8 存储 + `.to(bfloat16)` 转换 | ✅ |
229
- | `torch._scaled_mm`(硬件 FP8 matmul) | ❌ 需 SM89+/SM90+ 或 ROCm MI300+ |
230
- | **Triton** | ❌ `libamdhip64.so` 缺 `hipDrvLaunchKernelEx` |
231
- | bitsandbytes 4-bit / 8-bit | ✅ 需补丁 / ❌ 无 INT8 algo |
232
-
233
- Triton 那条影响最大:**任何依赖 Triton kernel 的推理框架都跑不起来**
234
- ——SGLang FP8 路径、vLLM ROCm MoE 后端、transformers `finegrained-fp8` 都在此列。
235
- 遇到这类需求先想清楚有没有纯 PyTorch 的退路,别花时间在框架适配上。
236
-
237
- 碰到新集群时,用一个探针作业实测这些能力,把结论写回 profile 的
238
- `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`。
239
241
 
240
242
  ## 排查失败
241
243
 
@@ -260,6 +262,8 @@ Triton 那条影响最大:**任何依赖 Triton kernel 的推理框架都跑
260
262
 
261
263
  将集群实测结果写入公开报告或仓库前,保留环境、方法、版本、结果和限制,移除或替换以下信息:用户名、SSH 主机/端口、内部域名、IP、节点名、作业编号、绝对家目录和私有镜像地址。可用 `<USER_HOME>`、`<DTK_ROOT>`、`<CLUSTER_HOST>`、`已脱敏作业` 等占位符。
262
264
 
263
- 报告正文沿用已有 LAMMPS 报告的结构和风格:深色渐变卡片、青绿色主色、蓝色辅助色,以及“环境信息 → 编译过程与主要难题 → 最终方案 → 测试结果 → 已知限制 → 经验总结 → 附录”的叙述顺序。公开结论必须标明测试环境、验证范围和未验证边界。
265
+ 公开技术记录按“环境与版本 → 问题与证据 → 解决方法 → 验证结果 → 已知限制 →
266
+ 可复用经验”组织。结论必须标明测试环境、验证范围和未验证边界;视觉样式由具体发布
267
+ 项目决定,不写进本 skill。
264
268
 
265
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,66 @@
1
+ # xianshell —— 西安集群(eshell111.hpccube.com)
2
+ #
3
+ # 2026-08-17 完成登录节点、Slurm 和计算节点实测。
4
+ # 计算探针使用 xahdnormal 分区、1 张 DCU,并将所有临时文件放在共享家目录。
5
+
6
+ # ---- 连接 ----
7
+ CLUSTER_ID="xianshell"
8
+ CLUSTER_DESC="西安集群(eshell111)"
9
+ SSH_HOST="eshell111.hpccube.com"
10
+ SSH_PORT="65082"
11
+ HOME_BASE="/work/home"
12
+
13
+ # 私钥文件名形如:<用户名>_eshell111.hpccube.com_RsaKeyExpireTime_<日期>.txt
14
+ KEY_NAME_MARKER="_eshell111.hpccube.com_"
15
+ NEEDS_UPDATE_HOSTKEYS_NO="no"
16
+
17
+ # ---- 调度器 ----
18
+ SCHEDULER="slurm"
19
+ PARTITION="xahdnormal"
20
+ DEF_MEM_PER_CPU="3570"
21
+ MIN_GRES="dcu:1" # sbatch --test-only 实测:不申请即 QOSMinGRES
22
+ GRES_TYPE="dcu"
23
+ MAX_WALLTIME="333-08:00:00"
24
+
25
+ # xahcnormal 是异构 CPU 队列(5609 节点,少量节点也带 DCU)。
26
+ PARTITION_CPU="xahcnormal"
27
+ PARTITION_DCU="xahdnormal"
28
+
29
+ # ---- 硬件 ----
30
+ ACCEL_NAME="海光 Z100 DCU (Z100SM)"
31
+ ACCEL_ARCH="gfx906"
32
+ ACCEL_PER_NODE="4"
33
+ ACCEL_MEM_GB="16" # PyTorch 实测 16368 MiB
34
+ CPUS_PER_NODE="32" # Slurm xahdnormal 可调度 CPU;节点物理 64 核
35
+ CPU_MODEL="Hygon C86 7285 32-core Processor"
36
+ NODE_MEM_GB="123"
37
+ NODE_COUNT="465"
38
+ LOGIN_NODES="登录节点(实测,公开 profile 已脱敏)"
39
+ HOME_QUOTA_GB="450" # /work 文件系统容量,非个人独占配额
40
+
41
+ # ---- 软件栈 ----
42
+ TOOLCHAIN="DTK"
43
+ TOOLCHAIN_VERSION="26.04"
44
+ TOOLCHAIN_PATH="/public/software/compiler/dtk-26.04"
45
+ MODULE_LOADS="compiler/dtk/26.04"
46
+ PYTHON_MODULE="python/3.8.10" # 计算节点显式加载,避免依赖用户私有 PATH
47
+ DEFAULT_VENV=""
48
+
49
+ # 平台自带的可运行 PyTorch 环境(能力探针专用):
50
+ # module load Pytorch/1.10.0-hpcx-gcc-7.3.1
51
+ # 该模块会 purge 环境并改用 DTK 22.10.1,不能与上面的 DTK 26.04 同时加载。
52
+
53
+ # ---- 网络 ----
54
+ NET_OK="pypi.org pypi.tuna.tsinghua.edu.cn modelscope.cn github.com"
55
+ NET_BLOCKED="huggingface.co"
56
+ PIP_INDEX="https://pypi.tuna.tsinghua.edu.cn/simple"
57
+ COMPUTE_NODE_OFFLINE="yes"
58
+ TMP_SHARED="no"
59
+
60
+ # ---- 已知问题 ----
61
+ LOGIN_NODE_MISSING_LIBS=""
62
+ KNOWN_LIMITATIONS="平台 PyTorch 1.10.0a0+git2040069-dtk2210 仅探测到 BF16,无 FP8 dtype,torch._scaled_mm 跳过;\
63
+ Triton 未安装;bitsandbytes 未安装;计算节点无法访问 pypi.org;\
64
+ 平台 PyTorch module 固定加载 DTK 22.10.1,与默认 DTK 26.04 不可混用;\
65
+ 远端缺少 C.UTF-8 locale,SSH 和作业启动会产生 setlocale 警告但不影响执行;\
66
+ 测试任务临时目录必须使用 \$HOME/.scnet-hpc/tmp/\$SLURM_JOB_ID,不使用 /tmp"
@@ -82,6 +82,10 @@ srun -p <分区> --gres=gpu:1 --time=00:05:00 nvidia-smi --query-gpu=name --form
82
82
  **这一步别省。** 国产加速器的软件栈往往落后于上游,很多想当然的能力并不存在。
83
83
  花 5 分钟测清楚,能省掉后面几天的困惑。
84
84
 
85
+ 所有探针和测试任务的临时文件必须放在共享家目录中,例如
86
+ `$HOME/.scnet-hpc/tmp/$SLURM_JOB_ID`。不要使用 `/tmp` 或从根目录创建临时目录;作业
87
+ 启动后应导出 `TMPDIR`、`TMP`、`TEMP` 指向该目录。
88
+
85
89
  用一个探针作业测这些:
86
90
 
87
91
  ```python
@@ -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) CLUSTER="${2:-}"; shift 2 ;;
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
  }
@@ -104,11 +104,12 @@ try:
104
104
  except Exception:
105
105
  emit("NET_PYPI", "OFFLINE")
106
106
 
107
- # /tmp 是否跨节点共享无法只靠单节点可靠判断,这里只记录文件系统信息
107
+ # 测试任务统一使用家目录中的 TMPDIR;记录实际路径,确认规则生效。
108
108
  try:
109
- emit("TMP_FSTYPE", str(os.statvfs("/tmp").f_fsid))
109
+ tmp_dir = os.environ.get("TMPDIR", "")
110
+ emit("TMPDIR", tmp_dir)
111
+ emit("TMP_IN_HOME", "1" if tmp_dir and os.path.commonpath([os.path.expanduser("~"), tmp_dir]) == os.path.expanduser("~") else "0")
110
112
  except Exception as exc:
111
- emit("TMP_FSTYPE", "ERR:" + short_error(exc))
112
- emit("TMP_SHARED", "UNKNOWN")
113
+ emit("TMPDIR", "ERR:" + short_error(exc))
113
114
 
114
115
  print("PROBE_EXIT=0", flush=True)
@@ -1,7 +1,8 @@
1
1
  #!/usr/bin/env bash
2
2
  # 生成一个符合目标集群所有约束的作业脚本骨架。
3
3
  #
4
- # ./new-job.sh [--cluster <集群短名>] <作业名> [加速器数] [cpu数] [时长]
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="${2:-}"; shift 2 ;;
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 <远端用户名>] [--refresh|--no-auto] <作业名> [加速器数] [cpu数] [时长]
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=${PARTITION}
144
+ #SBATCH --partition=${EFFECTIVE_PARTITION}
109
145
  ${GRES_LINE}
110
146
  #SBATCH --nodes=1
111
147
  #SBATCH --ntasks-per-node=1
@@ -119,6 +155,13 @@ module purge
119
155
  ${MODULES}
120
156
  ${VENV_LINE}
121
157
 
158
+ # 集群测试/作业的临时文件统一放共享家目录,不使用节点本地 /tmp。
159
+ JOB_TMPDIR="${HOME_DIR}/.scnet-hpc/tmp/\${SLURM_JOB_ID:-manual-\$\$}"
160
+ mkdir -p "\$JOB_TMPDIR"
161
+ export TMPDIR="\$JOB_TMPDIR"
162
+ export TMP="\$JOB_TMPDIR"
163
+ export TEMP="\$JOB_TMPDIR"
164
+
122
165
  ${OFFLINE_LINES}
123
166
 
124
167
  echo "### node=\$(hostname) jobid=\$SLURM_JOB_ID"
@@ -146,7 +189,7 @@ sed -i.bak '/^$/N;/^\n$/D' "$OUT" 2>/dev/null && rm -f "$OUT.bak"
146
189
 
147
190
  echo "已生成 $OUT"
148
191
  echo " 集群=${CLUSTER_ID} ${GRES_TYPE:-加速器}=${ACCEL} CPU=${CPUS} 内存=${MEM_NOTE} 时长=${TIME}"
149
- echo " 分区=${PARTITION:-未设置} 节点数=${NODE_COUNT:-未探测}(来源:${NODE_COUNT_SOURCE:-profile/cache})"
192
+ echo " 分区=${EFFECTIVE_PARTITION} 模式=$([ "$CPU_ONLY" = yes ] && echo CPU || echo accelerator) 节点数=${NODE_COUNT:-未探测}(来源:${NODE_COUNT_SOURCE:-profile/cache})"
150
193
  echo " 日志目录=${HOME_DIR}/scripts/logs(用户名 ${REMOTE_USER},不对请加 --user)"
151
194
  echo
152
195
  echo "上传并提交:"
@@ -19,21 +19,32 @@ PYTHON_BIN=""
19
19
 
20
20
  while [ $# -gt 0 ]; do
21
21
  case "$1" in
22
- --cpus) CPUS="${2:-$CPUS}"; shift 2 ;;
22
+ --cpus) [ $# -ge 2 ] || die "--cpus 缺少参数"; CPUS="$2"; shift 2 ;;
23
23
  --cpus=*) CPUS="${1#*=}"; shift ;;
24
- --time) TIME="${2:-$TIME}"; shift 2 ;;
24
+ --time) [ $# -ge 2 ] || die "--time 缺少参数"; TIME="$2"; shift 2 ;;
25
25
  --time=*) TIME="${1#*=}"; shift ;;
26
- --accelerators) ACCEL="${2:-$ACCEL}"; shift 2 ;;
26
+ --accelerators) [ $# -ge 2 ] || die "--accelerators 缺少参数"; ACCEL="$2"; shift 2 ;;
27
27
  --accelerators=*) ACCEL="${1#*=}"; shift ;;
28
- --user) REMOTE_USER="${2:-}"; shift 2 ;;
28
+ --user) [ $# -ge 2 ] || die "--user 缺少参数"; REMOTE_USER="$2"; shift 2 ;;
29
29
  --user=*) REMOTE_USER="${1#*=}"; shift ;;
30
- --python) PYTHON_BIN="${2:-}"; shift 2 ;;
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,8 +52,10 @@ 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
- PROBE_BASE="${HOME_DIR}/scnet-hpc-probe"
57
+ PROBE_DIR="${HOME_DIR}/.scnet-hpc/probes"
58
+ PROBE_BASE="${PROBE_DIR}/compute-probe"
46
59
 
47
60
  ssh_cmd() { ssh -o BatchMode=yes -o ConnectTimeout=20 -o ServerAliveInterval=15 -o ServerAliveCountMax=3 "$@"; }
48
61
  scp_cmd() { scp -o BatchMode=yes -o ConnectTimeout=20 "$@"; }
@@ -95,6 +108,13 @@ module purge
95
108
  ${MODULE_LINE}
96
109
  ${PYTHON_MODULE_LINE}
97
110
  ${VENV_LINE}
111
+
112
+ # 探针临时文件必须位于共享家目录,不能使用计算节点本地 /tmp。
113
+ JOB_TMPDIR="${HOME_DIR}/.scnet-hpc/tmp/\${SLURM_JOB_ID:-manual-\$\$}"
114
+ mkdir -p "\$JOB_TMPDIR"
115
+ export TMPDIR="\$JOB_TMPDIR"
116
+ export TMP="\$JOB_TMPDIR"
117
+ export TEMP="\$JOB_TMPDIR"
98
118
  export HF_HUB_OFFLINE=1
99
119
  export TRANSFORMERS_OFFLINE=1
100
120
 
@@ -115,7 +135,7 @@ echo "PROBE_EXIT=\$rc"
115
135
  exit \$rc
116
136
  EOF
117
137
 
118
- ssh_cmd "$CLUSTER_ID" "mkdir -p ${HOME_DIR}/scripts/logs"
138
+ ssh_cmd "$CLUSTER_ID" "mkdir -p ${HOME_DIR}/scripts/logs ${PROBE_DIR} ${HOME_DIR}/.scnet-hpc/tmp"
119
139
  scp_cmd -q "$TMPDIR_LOCAL/compute-probe.py" "${CLUSTER_ID}:${PROBE_BASE}.py"
120
140
  scp_cmd -q "$TMPDIR_LOCAL/probe.slurm" "${CLUSTER_ID}:${PROBE_BASE}.slurm"
121
141
 
@@ -129,4 +149,4 @@ else
129
149
  printf '%s\n' "$ERR" >&2
130
150
  fi
131
151
 
132
- ssh_cmd "$CLUSTER_ID" "rm -f ${PROBE_BASE}.py ${PROBE_BASE}.slurm ${HOME_DIR}/scripts/logs/scnet-hpc-probe_${JOBID}.out ${HOME_DIR}/scripts/logs/scnet-hpc-probe_${JOBID}.err"
152
+ ssh_cmd "$CLUSTER_ID" "rm -f ${PROBE_BASE}.py ${PROBE_BASE}.slurm ${HOME_DIR}/scripts/logs/scnet-hpc-probe_${JOBID}.out ${HOME_DIR}/scripts/logs/scnet-hpc-probe_${JOBID}.err; rm -rf ${HOME_DIR}/.scnet-hpc/tmp/${JOBID}"