# 分布式网格计算部署指南(master 单向 SSH) > 把 CNO 网格计算分发到多台 Linux 服务器并行。适配"大部分机器异地、 > 只有 master 能 SSH 进 worker"的网络。 ## 1. 架构(master 单向 SSH 推/拉) ``` master(WSL2) 异地 worker tasks.json (本地 flock 安全) (无常驻进程) ├ 派任务: ssh worker "nohup run_one.py ─▶ 被动执行单点 │ --teff X ... &" 跑完写本地 conv.json + .7 ├ 取状态: ssh worker "python3 dist_check ◀─ 被动提供结果 │ .py --results results" ├ 取种子: scp worker:.7 master(收敛点) ◀─ └ 七牛云(种子库): master 代传 .7 ─▶ 七牛 ``` **核心原则**: - **只需 master → worker 单向 SSH**(worker 在 NAT 后也行,不回连 master) - **任务队列只在 master 本地**(`fcntl.flock` 强一致,零并发风险) - **worker 无常驻进程**:master 直接 SSH 执行 `run_one.py`/`seed_step.py` 跑单点 - **冷启动零依赖**(seed=None,LTE grey 自建大气)→ 绝大多数点完美分布式 - **种子库放七牛云**(仅 `.7` 大气 393KB/点)→ 供 seed_step 回退 - **大产物留 worker 本地**(`.spec` 等 13MB)→ 不跨网传 ## 2. 并发安全(重点) 任务队列 `tasks.json` **只在 master 本地文件**,用 `fcntl.flock` 排他锁保护。 master 多线程管理多台 worker,但所有 claim/report 都走本地 flock,**无跨机并发问题**。 worker 完全不碰 tasks.json。 ## 3. 一次性环境准备 ### 3.1 master(本机 WSL2) ```bash # pyyaml 可选(有则用,无则用内置极简解析器,零 pip 也能跑) pip3 install pyyaml 2>/dev/null || echo "用内置解析器,无需 pip" ``` ### 3.2 每台 worker(异地机器) 只需: - **python3**(系统自带) - **openssh-server**(让 master 能 SSH 进来) - **tlusty 树**(二进制 + 原子数据) ```bash sudo apt install python3 openssh-server ``` > **worker 不需要 curl、不需要 pip、不需要七牛配置、不需要 SSH 回 master。** ### 3.3 分发 TLUSTY 树到每台 worker(首次,约 2GB) 在 master 上对每台 worker: ```bash sudo apt install rsync # master 端装一次 TARGET=user@worker1 REMOTE_ROOT=~/tlusty/tl208-s54 # 记到 dist_config.yaml 的 tlusty_root rsync -avz --exclude='cno_grid/results' --exclude='*.log' \ /home/dckj/program/tlusty/tl208-s54/ $TARGET:$REMOTE_ROOT/ ``` ### 3.4 分发 cno_grid 代码到每台 worker(每次代码更新) ```bash rsync -avz --exclude='results' --exclude='*.log' --exclude='__pycache__' \ /home/dckj/program/tlusty/tl208-s54/cno_grid/ \ $TARGET:$REMOTE_ROOT/cno_grid/ ``` ### 3.5 配置 SSH 免密(master → worker,单向即可) ```bash ssh-copy-id user@worker1 ssh-copy-id user@worker2 # ... ``` 验证:`ssh user@worker1 echo ok` 应直接输出 `ok`,不问密码。 **worker 不需要 SSH 回 master。** ### 3.6 七牛云(可选;不配也能跑,只是没跨机种子共享) 1. 七牛云创建 bucket,拿 AK/SK,绑域名 2. master 设环境变量: ```bash export QINIU_ACCESS_KEY="你的AK" export QINIU_SECRET_KEY="你的SK" ``` > 不配七牛时,seed_step 只能用同台 worker 上已收敛的本地种子。 ## 4. 配置 dist_config.yaml ```yaml master: workdir: /home/dckj/program/tlusty/tl208-s54/cno_grid grid_config: /home/dckj/program/tlusty/tl208-s54/cno_grid/config.yaml results: results qiniu: bucket: your-bucket domain: http://xxx # 留空 = 纯本地模式 upload_by: master # master 代传种子(worker 不碰七牛) workers: - host: localhost # 本机也算 worker(可选) tlusty_root: /home/dckj/program/tlusty/tl208-s54 nproc: 8 - host: user@worker1 # 异地机器 tlusty_root: ~/tlusty/tl208-s54 nproc: 24 # ... 每台机器一项 ``` ## 5. 运行 ### 5.1 预览(dry-run) ```bash cd /home/dckj/program/tlusty/tl208-s54/cno_grid export QINIU_ACCESS_KEY=... QINIU_SECRET_KEY=... python3 src/dist_master.py dist_config.yaml --dry-run # 输出:待计算 N 点,总并发 X 核,预计 ~Y 小时 + 部署检查清单 ``` ### 5.2 全量跑 ```bash export QINIU_ACCESS_KEY=... QINIU_SECRET_KEY=... nohup python3 src/dist_master.py dist_config.yaml > results/dist_run.log 2>&1 & ``` ### 5.3 监控 ```bash tail -f results/dist_run.log # master 视角(每 20s 打印状态计数) cat results/grid_status.json # 汇总 # 看某台 worker 的某个任务日志: ssh user@worker1 "tail ~/tlusty/tl208-s54/cno_grid/worker_jobs/<模型名>.log" ``` ### 5.4 断点续算 中断后重跑同一命令,已 `done` 的点自动跳过(tasks.json 持久化在 master)。 ## 6. 工作流程(master 内部) ``` 1. init tasks.json(432 点 pending;本地已 converged 标 done) 2. 每台 worker 一个管理线程,并发跑: 循环: a. SSH 查 worker 正在跑的进程数 → 空闲槽 = nproc - running b. 每个空闲槽:本地 flock 领一个 pending→running,SSH 派 run_one.py(nohup) c. SSH 调 dist_check.py 查 worker 已完成的点: - 收敛 → scp .7 回 master → (代传七牛) → 标 done - 未收敛 → 找种子(本地缓存>七牛)→ scp 种子到 worker → SSH 派 seed_step.py 重试 - seed_step 仍失败 → 标 failed(物理极限) 3. 全部终态 → 写 grid_status.json ``` ## 7. 文件清单 | 文件 | 角色 | 运行在哪 | |------|------|---------| | `src/dist_master.py` | master 调度器(推/拉/seed_step/汇总) | master | | `src/dist_check.py` | worker 状态查询(被 SSH 调用) | 每台 worker | | `src/qiniu_store.py` | 七牛云种子库(零 SDK) | master | | `src/claim_task.py` / `report_task.py` | 任务原子操作(master 本地调) | master | | `src/run_one.py` | 单点冷启动执行器(被 SSH 调用) | 每台 worker | | `src/seed_step.py` | 单点种子步进执行器(被 SSH 调用) | 每台 worker | | `dist_config.yaml` | 分布式配置 | master | | `tasks.json` | 任务队列(运行时生成) | master | > `dist_worker.py` 已废弃(旧双向模型残留),当前架构不用。 ## 8. 带宽与时间估算 | 项 | 大小 | 说明 | |----|------|------| | 单点计算 | 1200-2500s | 主耗时 | | SSH 派任务 | ~1KB/点 | 命令字符串,可忽略 | | 取 conv.json | 1.6KB/点 | 经 SSH,可忽略 | | 取种子 .7(收敛点) | 393KB/点 | scp 回 master,2Mbps≈1.6s | | seed_step 种子推送 | 393KB/点 | 仅失败点,少数 | | **跨网传输占比** | **<5%** | 相比计算可忽略 | 432 点 / 5台×24核 ≈ **3-4 小时**(vs 单机 15-21 小时)。 ## 9. 故障排查 | 现象 | 排查 | |------|------| | master 派不出去 | `ssh user@workerN echo ok` 是否通;worker 上 `run_one.py` 路径对不对 | | worker 算了但 master 没回收 | 看 `worker_jobs/.log`;`dist_check.py` 是否能列出 | | 任务一直 running | 可能 worker 进程崩了;master 每 2 小时自动重派(stale_sec) | | 种子找不到(seed_step 失败) | 同 family 无收敛点 → 物理极限,正常;或配七牛扩种子来源 | | 单机模式仍可用 | `python3 src/run_grid.py config.yaml`(完全不受影响) | ## 10. 安全提示 - **AK/SK 只放 master 环境变量**,不写进 dist_config.yaml(会被提交仓库) - worker 默认不碰七牛(`upload_by: master`);如需 worker 直传再配域名 - SSH 用密钥免密,不用密码