Split the unattended run into a GPU-free phase and a GPU phase
The target machine's card is busy with someone else's job, so a single end-to-end script stalls on work that does not actually need a GPU. Compiling the CUDA extensions needs nvcc, not a device, and downloading 18 GB of data needs neither. Those are the slow parts (~50 min + ~30 min), so phase A now runs entirely without the card: run_setup.sh bootstrap, conda, extensions, patches, data no GPU run_train.sh voxel_max measurement, training, evaluation GPU run_setup reports the GPU but never fails on it, and verify_env.py gained SKIP_CUDA_CHECK so import coverage still runs when no device is visible. TORCH_CUDA_ARCH_LIST is stated rather than probed, since the card may be unavailable at build time. run_train waits for the GPU instead of failing when it is busy: it polls until enough VRAM frees up (12h default), so it can be queued ahead of time. Past the deadline it proceeds anyway and lets the measured voxel_max adapt to whatever is actually free. keepalive.sh now takes the phase to supervise. Replaces run_all.sh and RUN.md with SETUP.md and TRAIN.md. Adds selfcheck.sh, which syntax-checks every script and flags CRLF endings - a shell script with either fails at its first line, which for an unattended weekend run means losing the weekend. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,224 +1,180 @@
|
||||
# 새 머신에서 시작하기
|
||||
# 1단계 — 환경 구축 (GPU 불필요)
|
||||
|
||||
RTX 3090(24GB) 머신에서 SUM Parts + PointVector 학습을 재현하는 절차.
|
||||
**GPU가 다른 작업에 물려 있어도 지금 돌릴 수 있다.**
|
||||
오래 걸리는 작업(확장 빌드 50분 + 데이터 30분)이 전부 여기 들어 있다.
|
||||
|
||||
3060(12GB)에서는 VRAM이 모자라 `voxel_max`를 24000으로 낮춰야 했다.
|
||||
**24GB에서는 논문 설정 64000을 그대로 쓴다** — 이게 이 머신으로 옮기는 유일한 이유다.
|
||||
끝나면 [TRAIN.md](TRAIN.md)로 간다.
|
||||
|
||||
---
|
||||
|
||||
## 0. 전제
|
||||
## 왜 나눴나
|
||||
|
||||
CUDA 확장 빌드는 **`nvcc` 컴파일이지 GPU 실행이 아니다.** 데이터 다운로드도 마찬가지다.
|
||||
즉 카드가 남의 작업으로 바빠도 이 단계는 전부 끝낼 수 있다.
|
||||
|
||||
| 작업 | GPU 필요 | 시간 |
|
||||
|---|---|---|
|
||||
| miniconda 설치 · 업스트림 clone | ✗ | 5분 |
|
||||
| conda 환경 · CUDA 11.8 · torch 2.0.1 | ✗ | 20분 |
|
||||
| **CUDA 확장 5종 빌드** | ✗ (nvcc만) | 25분 |
|
||||
| 소스 패치 3건 | ✗ | 10초 |
|
||||
| import 검증 | ✗ | 30초 |
|
||||
| 데이터 다운로드·전개 (5.3 → 18 GB) | ✗ | 30분 |
|
||||
| split 정리 · 링크 | ✗ | 10초 |
|
||||
|
||||
**합계 약 80분.** 이걸 미리 해두면 GPU가 비는 순간 바로 학습에 들어간다.
|
||||
|
||||
---
|
||||
|
||||
## 전제
|
||||
|
||||
| 항목 | 필요 |
|
||||
|---|---|
|
||||
| OS | Windows + WSL2 (Ubuntu 22.04) 또는 네이티브 Linux |
|
||||
| GPU | RTX 3090 24GB, 드라이버가 WSL에서 인식될 것 |
|
||||
| 디스크 | **35GB 이상 여유** |
|
||||
| 계정 | HuggingFace 계정 (데이터 게이트 수락에 필요) |
|
||||
| 도구 | `git`, `curl` (sudo는 불필요) |
|
||||
| 디스크 | `$HOME`에 **35 GB 이상** |
|
||||
| 도구 | `git` `curl` `python3` `tar` (sudo 불필요) |
|
||||
| 계정 | HuggingFace 토큰 |
|
||||
|
||||
디스크 내역 — 전부 이 절차가 만들어낸다:
|
||||
GPU는 **없어도 된다.** 있으면 정보로만 표시한다.
|
||||
|
||||
### 디스크 내역
|
||||
|
||||
| 항목 | 크기 |
|
||||
|---|---|
|
||||
| miniconda + 환경 | 12 GB |
|
||||
| 업스트림 소스 | 1.7 GB |
|
||||
| 데이터셋 (아카이브 포함) | 18 GB |
|
||||
| 체크포인트·로그 | 1.5 GB |
|
||||
|
||||
WSL이면 `nvidia-smi`가 WSL 안에서 GPU를 보여야 한다. 안 보이면 여기서 멈추고 드라이버부터.
|
||||
|
||||
```bash
|
||||
nvidia-smi # RTX 3090 24576MiB 가 보여야 함
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 1. 클론
|
||||
## 1. HF 토큰 — 유일한 수동 작업
|
||||
|
||||
데이터셋에 게이트가 걸려 있다. 수락은 브라우저에서만 되고 **자동화 불가**다.
|
||||
다만 **수락은 계정 단위**라, 이미 수락한 계정의 토큰만 옮기면 된다.
|
||||
|
||||
기존 머신에서 값 확인:
|
||||
|
||||
```powershell
|
||||
type $env:USERPROFILE\.cache\huggingface\token
|
||||
```
|
||||
|
||||
이 머신 WSL에서:
|
||||
|
||||
```bash
|
||||
git clone <gitea-url>/sum-parts-test.git
|
||||
mkdir -p ~/.cache/huggingface
|
||||
echo hf_xxxxx > ~/.cache/huggingface/token
|
||||
```
|
||||
|
||||
아직 어느 계정으로도 수락한 적이 없다면 브라우저에서 1회:
|
||||
https://huggingface.co/datasets/gwxgrxhyz/SUM-Parts → 로그인 → CC BY-NC 4.0 수락
|
||||
|
||||
---
|
||||
|
||||
## 2. 클론 + 사전점검
|
||||
|
||||
```bash
|
||||
git clone https://gitea.hmac.kr/kimminsung/sum-parts-test.git
|
||||
cd sum-parts-test
|
||||
|
||||
bash scripts/selfcheck.sh # 스크립트 무결성
|
||||
RUN_DRYRUN=1 bash scripts/run_setup.sh # 전제조건만 검사
|
||||
```
|
||||
|
||||
스크립트는 경로를 `/mnt/d/MYCLAUDE_PROJECT/sum-parts-test/scripts`로 하드코딩한 곳이 있다.
|
||||
다른 경로에 두면 아래 한 줄로 일괄 치환한다.
|
||||
**`preflight OK` 가 나와야 한다.** 검사 항목:
|
||||
|
||||
```bash
|
||||
NEW=$(pwd)/scripts
|
||||
grep -rl '/mnt/d/MYCLAUDE_PROJECT/sum-parts-test/scripts' scripts/ \
|
||||
| xargs sed -i "s|/mnt/d/MYCLAUDE_PROJECT/sum-parts-test/scripts|$NEW|g"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. 환경 구축 (약 50분)
|
||||
|
||||
먼저 부트스트랩. **새 머신에는 miniconda도 업스트림 소스도 없다** —
|
||||
이 레포에는 우리 스크립트만 들어 있고, 벤치마크 본체는 별도 clone이 필요하다.
|
||||
|
||||
```bash
|
||||
bash scripts/bootstrap.sh # miniconda 설치 + 업스트림 clone + GPU 확인
|
||||
```
|
||||
|
||||
이게 만드는 것:
|
||||
|
||||
| 경로 | 내용 | 크기 |
|
||||
|---|---|---|
|
||||
| `~/miniconda3` | conda (sudo 불필요, $HOME에 설치) | 0.5 GB |
|
||||
| `~/sum-parts` | [SUM-Parts-Benchmarks](https://github.com/tudelft3d/SUM-Parts-Benchmarks) clone | 1.7 GB |
|
||||
|
||||
부트스트랩 끝에 GPU 용량을 찍어준다. **24GB면 `voxel_max=64000` 가능**하다고 알려준다.
|
||||
|
||||
이어서 환경:
|
||||
|
||||
```bash
|
||||
bash scripts/setup_env.sh # conda env + CUDA 11.8 + torch 2.0.1
|
||||
bash scripts/setup_pointnext.sh # 의존성 + CUDA 확장 5종 빌드
|
||||
```
|
||||
|
||||
`setup_env.sh` 안의 `TORCH_CUDA_ARCH_LIST`를 3090에 맞춰야 한다.
|
||||
|
||||
```bash
|
||||
# RTX 3060 = 8.6, RTX 3090 = 8.6 (둘 다 Ampere라 동일, 수정 불필요)
|
||||
# RTX 4090이면 8.9로 변경
|
||||
```
|
||||
|
||||
이어서 업스트림 소스 패치 4건. **전부 멱등이라 여러 번 실행해도 안전하다.**
|
||||
|
||||
```bash
|
||||
bash scripts/patch_numpy_aliases.sh # np.long 등 제거된 별칭 + collections ABC
|
||||
bash scripts/patch_unlabeled_test.sh # 블라인드 test셋의 label=-1 처리
|
||||
bash scripts/patch_val_mode.sh # mode=val 의 UnboundLocalError
|
||||
```
|
||||
|
||||
**게이트 — 통과 못 하면 다음으로 가지 말 것:**
|
||||
|
||||
```bash
|
||||
python scripts/verify_env.py
|
||||
# 기대: ALL OK (확장 6종 import + openpoints 체인 전부)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 데이터 (약 30분)
|
||||
|
||||
HuggingFace 게이트를 **브라우저에서 1회 수동 수락**해야 한다. 자동화 불가.
|
||||
|
||||
1. https://huggingface.co/datasets/gwxgrxhyz/SUM-Parts
|
||||
2. 로그인 → CC BY-NC 4.0 수락
|
||||
3. 토큰을 `~/.cache/huggingface/token`에 두거나 `huggingface-cli login`
|
||||
|
||||
```bash
|
||||
bash scripts/download_data.sh all # 5.3GB 받아 13GB로 전개
|
||||
bash scripts/prepare_full_split.sh # validate/ -> val/ 심볼릭 링크
|
||||
bash scripts/link_data.sh # PointNeXt_bundle/data 연결
|
||||
```
|
||||
|
||||
**게이트:** 세 split이 `24 / 8 / 8`로 집계될 것.
|
||||
|
||||
---
|
||||
|
||||
## 4. VRAM 확인 (5분) — 24GB에서 반드시 먼저
|
||||
|
||||
논문 설정이 실제로 들어가는지 확인한다. 3060에서는 여기서 실패했다.
|
||||
|
||||
```bash
|
||||
CFG=pointvector-xl ITERS=5 bash scripts/sweep_voxel_max.sh 40000 48000 64000
|
||||
```
|
||||
|
||||
기대 결과 (3090 24GB):
|
||||
|
||||
| voxel_max | peak VRAM | 판정 |
|
||||
|---|---|---|
|
||||
| 64000 | 약 16.5G | ✅ 들어감 |
|
||||
|
||||
**`fits? = yes`가 나와야 한다.** `NO (spilling)`이면 그 값은 쓰면 안 된다.
|
||||
|
||||
> ⚠️ **WSL2에서 VRAM 초과는 OOM을 내지 않는다.** 드라이버가 호스트 RAM으로 흘려서
|
||||
> 학습이 **조용히 완주한다 — 25~100배 느리게.** 반드시 peak VRAM 수치로 판정할 것.
|
||||
> 판별 보조 지표는 **전력**: 사용률 100%인데 전력이 낮으면 연산이 아니라 PCIe 전송 대기다.
|
||||
|
||||
---
|
||||
|
||||
## 5. 학습 (논문 설정, 약 3~5시간)
|
||||
|
||||
```bash
|
||||
CFG_VOXEL_MAX=64000 VAL_VOXEL_MAX=64000 \
|
||||
bash scripts/launch_overnight.sh pointvector-xl
|
||||
```
|
||||
|
||||
`setsid nohup`으로 분리 실행되므로 터미널·세션을 닫아도 살아남는다.
|
||||
크래시하면 최신 체크포인트에서 자동 재개한다(최대 8회).
|
||||
|
||||
진행 확인:
|
||||
|
||||
```bash
|
||||
bash scripts/check_training.sh # epoch, GPU, best miou
|
||||
bash scripts/verify_speed.sh # HEALTHY / DEGRADED 판정
|
||||
bash scripts/epoch_timing.sh # epoch별 소요시간, 감속 지점 특정
|
||||
```
|
||||
|
||||
중단:
|
||||
|
||||
```bash
|
||||
bash scripts/stop_training.sh # 워치독 먼저 죽여서 자동 재시작 방지
|
||||
```
|
||||
|
||||
**게이트:** `verify_speed.sh`가 `HEALTHY`, peak VRAM이 카드 용량의 95% 미만.
|
||||
|
||||
---
|
||||
|
||||
## 6. 평가
|
||||
|
||||
```bash
|
||||
bash scripts/final_eval.sh # val(라벨 있음) + test(블라인드, 예측만)
|
||||
bash scripts/eval_coarse.sh # 4클래스 통합 성적 ← 우리 과제 기준
|
||||
```
|
||||
|
||||
`eval_coarse.sh`가 실제로 중요한 수치를 낸다. SUM 13클래스를
|
||||
건물 / 수목 / 차량 / 지면으로 합쳐서 채점한다.
|
||||
|
||||
**게이트:** 통합 mIoU가 **"전부 건물" 무지성 분류기(IoU 약 67%)를 이길 것.**
|
||||
절대값이 아니라 baseline 대비로 판정한다.
|
||||
|
||||
---
|
||||
|
||||
## 참고 — 3060 실측값 (비교 기준)
|
||||
|
||||
| 모델 | voxel_max | peak VRAM | s/iter | 100 epoch |
|
||||
|---|---|---|---|---|
|
||||
| pointnet | 64000 | 6.01G | 0.291 | 2.9h |
|
||||
| pointnet++msg | 64000 | 4.16G | 0.675 | 6.8h |
|
||||
| pointvector-xl | 24000 | 6.46G | 0.402 | 2.9h |
|
||||
| pointvector-xl | 64000 | **16.49G** | 13.113 | ❌ 12GB 불가 |
|
||||
| pointnext-xl | 32000 | 8.03G | 0.635 | 6.4h |
|
||||
| pointnext-xl | 64000 | **15.47G** | 46.980 | ❌ 12GB 불가 |
|
||||
|
||||
논문 보고치 (face 트랙, 12클래스):
|
||||
|
||||
| 모델 | mIoU |
|
||||
| 항목 | 실패하면 |
|
||||
|---|---|
|
||||
| PointNet | 15.1% |
|
||||
| PointNet++ | 33.1% |
|
||||
| PointNeXt | 65.3% |
|
||||
| **PointVector** | **70.0%** |
|
||||
| `git` `curl` `python3` `tar` | 설치 |
|
||||
| `$HOME` 여유 35 GB | 공간 확보 |
|
||||
| HF 토큰 + 게이트 통과 | 위 1번 |
|
||||
|
||||
3060에서 pointnet 100 epoch 실측 = **17.19%** (논문 15.1%와 근사, 재현 확인됨).
|
||||
GPU는 검사하지 않는다 — 이 단계엔 필요 없다.
|
||||
|
||||
---
|
||||
|
||||
## 알려진 제약
|
||||
## 3. 실행
|
||||
|
||||
- **test 세트는 블라인드다.** 라벨이 전부 `-1`이라 로컬 채점이 불가능하다.
|
||||
논문 수치와 직접 대조하려면 예측을 저자(gaoweixiaocuhk@gmail.com)에게 보내야 한다.
|
||||
- **`voxel_max`는 중립적 손잡이가 아니다.** 모델의 동작점 일부다.
|
||||
같은 체크포인트가 검증 프로토콜에 따라 mIoU 17.19 / 4.20으로 갈렸다.
|
||||
- **라이선스**: 데이터 CC BY-NC 4.0, 코드 GPL-3.0. 상업 이용은 저자 허락 필요.
|
||||
```bash
|
||||
setsid nohup bash scripts/keepalive.sh setup > ~/keepalive-setup.out 2>&1 &
|
||||
```
|
||||
|
||||
터미널을 닫아도 계속 돈다. 약 80분.
|
||||
|
||||
### 아키텍처가 8.6이 아니라면
|
||||
|
||||
확장은 특정 아키텍처로 컴파일된다. GPU를 조회할 수 없을 수도 있으니 **명시**한다.
|
||||
|
||||
| GPU | 값 |
|
||||
|---|---|
|
||||
| RTX 3060 / 3070 / 3080 / **3090** | `8.6` (기본값) |
|
||||
| RTX 4090 | `8.9` |
|
||||
| A100 | `8.0` |
|
||||
|
||||
3090이면 기본값 그대로 두면 된다. 다르면:
|
||||
|
||||
```bash
|
||||
TORCH_CUDA_ARCH_LIST=8.9 setsid nohup bash scripts/keepalive.sh setup \
|
||||
> ~/keepalive-setup.out 2>&1 &
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 상세 기록
|
||||
## 4. 확인
|
||||
|
||||
- [docs/SUM-Parts-검토노트.md](docs/SUM-Parts-검토노트.md) — 트러블슈팅 16건, 실측 데이터 스키마, 라이선스 검토
|
||||
- [docs/pipeline.html](docs/pipeline.html) — 전체 공정 정의 (브라우저로 열 것)
|
||||
```bash
|
||||
cat ~/sum-parts/runs/setup/STATUS
|
||||
```
|
||||
|
||||
```
|
||||
state : DONE
|
||||
phase : done
|
||||
arch : 8.6
|
||||
```
|
||||
|
||||
| state | 뜻 |
|
||||
|---|---|
|
||||
| `DONE` | 완료 → [TRAIN.md](TRAIN.md)로 |
|
||||
| `running` / `retrying` | 진행 중 |
|
||||
| `FAILED` | `note` 줄에 원인 |
|
||||
|
||||
로그:
|
||||
|
||||
```bash
|
||||
tail -60 ~/sum-parts/runs/setup/setup.log
|
||||
cat ~/sum-parts/runs/setup/keepalive.log
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 멈춰도 계속 도는 구조
|
||||
|
||||
| 층 | 담당 |
|
||||
|---|---|
|
||||
| `keepalive.sh setup` | 프로세스 전체 사망 시 재기동 (최대 40회) |
|
||||
| `run_setup.sh` | 단계 실패 시 지수 백오프 재시도 (4회, 60→120→240초) |
|
||||
|
||||
**전 단계 멱등이다.** conda 환경·clone·패치·다운로드 아카이브를 각각 감지해서 건너뛴다.
|
||||
처음부터 다시 돌려도 안전하다.
|
||||
|
||||
### preflight만 재시도하지 않는다 — 의도적이다
|
||||
|
||||
HF 토큰 없음은 재시도해도 안 고쳐진다. 무의미하게 반복하느니
|
||||
1분 만에 실패하고 `FAILED`를 남기는 게 낫다.
|
||||
|
||||
---
|
||||
|
||||
## 중단
|
||||
|
||||
```bash
|
||||
pkill -f keepalive.sh
|
||||
pkill -f run_setup.sh
|
||||
```
|
||||
|
||||
다시 켜면 중단 지점부터 이어간다.
|
||||
|
||||
---
|
||||
|
||||
## 다음
|
||||
|
||||
[TRAIN.md](TRAIN.md) — GPU가 필요한 학습 단계.
|
||||
`SETUP_DONE` 마커가 없으면 실행을 거부한다.
|
||||
|
||||
Reference in New Issue
Block a user