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>
216 lines
6.0 KiB
Markdown
216 lines
6.0 KiB
Markdown
# 2단계 — 학습 (GPU 필요)
|
|
|
|
[SETUP.md](SETUP.md)가 끝난 뒤 실행한다. `SETUP_DONE` 마커가 없으면 거부한다.
|
|
|
|
**GPU가 아직 바빠도 지금 걸어둘 수 있다.** 카드가 빌 때까지 기다렸다가 알아서 시작한다.
|
|
|
|
---
|
|
|
|
## 이 단계가 하는 것
|
|
|
|
| 작업 | 시간 |
|
|
|---|---|
|
|
| GPU 대기 (VRAM 확보될 때까지) | 가변 |
|
|
| `voxel_max` 실측 선택 | 10분 |
|
|
| **학습 100 epoch** | 3~6시간 |
|
|
| 평가 (val + test + 4클래스 통합) | 10분 |
|
|
|
|
---
|
|
|
|
## 1. 사전점검
|
|
|
|
```bash
|
|
cd sum-parts-test
|
|
RUN_DRYRUN=1 bash scripts/run_train.sh
|
|
```
|
|
|
|
**`preflight OK` 가 나와야 한다.** 검사 항목:
|
|
|
|
| 항목 | 실패하면 |
|
|
|---|---|
|
|
| `SETUP_DONE` 마커 | [SETUP.md](SETUP.md) 먼저 |
|
|
| conda 환경 `sumparts` | 동상 |
|
|
| 데이터 `24 / 8 / 8` | 동상 |
|
|
| `nvidia-smi` + GPU 인식 | 드라이버 문제 — 여기서 해결 |
|
|
|
|
GPU가 **바쁜 것은 실패가 아니다.** 인식만 되면 통과한다.
|
|
|
|
---
|
|
|
|
## 2. 실행
|
|
|
|
```bash
|
|
setsid nohup bash scripts/keepalive.sh train > ~/keepalive-train.out 2>&1 &
|
|
```
|
|
|
|
터미널을 닫아도 계속 돈다.
|
|
|
|
### GPU 대기 동작
|
|
|
|
남의 작업이 카드를 쓰고 있으면 **실패하지 않고 기다린다.**
|
|
|
|
```
|
|
[11:40:02] card has 24576 MiB; waiting until 16000 MiB is free
|
|
[11:40:02] 3200 MiB free, need 16000 -- checking again in 5 min
|
|
```
|
|
|
|
5분마다 확인하고, 확보되면 자동으로 시작한다. 기본 대기 상한 12시간.
|
|
|
|
조정:
|
|
|
|
```bash
|
|
GPU_FREE_MB=20000 GPU_WAIT_MINUTES=1440 \
|
|
setsid nohup bash scripts/keepalive.sh train > ~/keepalive-train.out 2>&1 &
|
|
```
|
|
|
|
상한을 넘기면 **실패시키지 않고 그냥 진행한다.** 그 시점의 가용 VRAM에 맞춰
|
|
`voxel_max`가 측정되므로, 작게라도 학습은 된다.
|
|
|
|
---
|
|
|
|
## 3. 확인
|
|
|
|
```bash
|
|
cat ~/sum-parts/runs/train/STATUS
|
|
```
|
|
|
|
```
|
|
state : running
|
|
phase : train
|
|
cfg : pointvector-xl
|
|
voxel_max: 64000
|
|
```
|
|
|
|
| state | 뜻 |
|
|
|---|---|
|
|
| `DONE` | 완료 |
|
|
| `waiting` | GPU 비기를 기다리는 중 |
|
|
| `running` / `retrying` | 진행 중 |
|
|
| `FAILED` | `note` 줄에 원인 |
|
|
|
|
상세:
|
|
|
|
```bash
|
|
tail -60 ~/sum-parts/runs/train/train_phase.log
|
|
bash scripts/check_training.sh # epoch, GPU, best miou
|
|
bash scripts/verify_speed.sh # HEALTHY / DEGRADED 판정
|
|
bash scripts/epoch_timing.sh # epoch별 소요, 감속 지점
|
|
```
|
|
|
|
결과:
|
|
|
|
```bash
|
|
cat ~/sum-parts/runs/coarse_eval/coarse.txt # 4클래스 통합 성적 ← 핵심
|
|
```
|
|
|
|
---
|
|
|
|
## voxel_max 자동 결정
|
|
|
|
논문 설정은 `voxel_max: 64000`, 약 **16.5 GB** 필요하다.
|
|
3060(12 GB)에서는 못 들어가 24000으로 낮춰야 했고, **그게 3090으로 옮기는 이유다.**
|
|
|
|
높은 값부터 내려가며 **실측**해서 실제로 들어가는 첫 값을 쓴다.
|
|
|
|
```
|
|
64000 → 48000 → 40000 → 32000 → 24000
|
|
```
|
|
|
|
3060 실측 (비교 기준):
|
|
|
|
| voxel_max | peak VRAM | s/iter | 12 GB |
|
|
|---|---|---|---|
|
|
| 64000 | **16.49 G** | 13.113 | ❌ |
|
|
| 48000 | 11.75 G | 29.169 | ❌ 폴백 |
|
|
| 40000 | 9.88 G | 1.169 | ✅ |
|
|
| 32000 | 8.03 G | 0.635 | ✅ |
|
|
| 24000 | 6.46 G | 0.402 | ✅ |
|
|
|
|
> ⚠️ **WSL2에서 VRAM 초과는 OOM을 내지 않는다.**
|
|
> 드라이버가 호스트 RAM으로 흘려서 **조용히 완주한다 — 25~100배 느리게.**
|
|
> 12 GB 카드에서 `peak 15.47 GB`가 찍힌다.
|
|
> 그래서 "돌아가더라"를 믿지 않고 peak 할당량으로 판정한다.
|
|
>
|
|
> 보조 지표는 **전력**이다. 사용률 100 %인데 전력이 낮으면
|
|
> (3060 기준 60 W대) 연산이 아니라 PCIe 전송 대기다. 정상이면 140 W대.
|
|
|
|
---
|
|
|
|
## 멈춰도 계속 도는 구조 — 3중
|
|
|
|
| 층 | 담당 | 동작 |
|
|
|---|---|---|
|
|
| `keepalive.sh train` | 프로세스 전체 사망 | VM 재시작·OOM kill 후 재기동 (최대 40회) |
|
|
| `run_train.sh` | 단계 실패 | 지수 백오프 재시도 (4회, 60→120→240초) |
|
|
| `train_watchdog.sh` | 학습 크래시 | 최신 체크포인트에서 재개 (최대 8회) |
|
|
|
|
**재시작해도 epoch 1로 돌아가지 않는다.** 최신 체크포인트를 워치독에 넘겨
|
|
optimizer·scheduler·epoch을 복원한다.
|
|
|
|
`wsl --shutdown`이나 Windows 재부팅은 못 버틴다 — WSL 안에서 도는 건 다 마찬가지다.
|
|
그 경우 같은 명령을 다시 치면 중단 지점부터 이어간다.
|
|
|
|
---
|
|
|
|
## 설정
|
|
|
|
| 변수 | 기본 | 뜻 |
|
|
|---|---|---|
|
|
| `CFG` | `pointvector-xl` | 모델 (논문 mIoU 70.0 %, 번들 최고이자 최속) |
|
|
| `EPOCHS` | `100` | |
|
|
| `VAL_FREQ` | `5` | 검증 주기 |
|
|
| `VOXEL_CANDIDATES` | `64000 48000 40000 32000 24000` | 높은 값부터 시도 |
|
|
| `GPU_FREE_MB` | `16000` | 이만큼 비어야 시작 |
|
|
| `GPU_WAIT_MINUTES` | `720` | 대기 상한 |
|
|
| `STEP_RETRIES` | `4` | 단계별 재시도 |
|
|
| `MAX_RESTARTS` | `40` | keepalive 재기동 상한 |
|
|
|
|
예:
|
|
|
|
```bash
|
|
CFG=pointnext-xl EPOCHS=50 \
|
|
setsid nohup bash scripts/keepalive.sh train > ~/keepalive-train.out 2>&1 &
|
|
```
|
|
|
|
---
|
|
|
|
## 중단
|
|
|
|
```bash
|
|
pkill -f keepalive.sh # 감시자 먼저 — 안 그러면 다시 살린다
|
|
bash scripts/stop_training.sh
|
|
```
|
|
|
|
체크포인트는 남는다.
|
|
|
|
---
|
|
|
|
## 참고 — 논문 보고치
|
|
|
|
face 트랙, 12클래스:
|
|
|
|
| 모델 | mIoU |
|
|
|---|---|
|
|
| PointNet | 15.1 % |
|
|
| PointNet++ | 33.1 % |
|
|
| PointNeXt | 65.3 % |
|
|
| **PointVector** | **70.0 %** |
|
|
|
|
3060에서 PointNet 100 epoch 실측 = **17.19 %** (논문 15.1 %와 근사, 재현 확인).
|
|
|
|
### 최종 판정 기준
|
|
|
|
`coarse.txt`의 통합 mIoU가 **"전부 건물" 무지성 분류기(IoU 약 67 %)를 이겨야 한다.**
|
|
절대값이 아니라 baseline 대비로 본다 — 3060 PointNet은 building IoU 59.41 %로
|
|
그 baseline보다 낮았다.
|
|
|
|
---
|
|
|
|
## 알려진 제약
|
|
|
|
- **test 세트는 블라인드다.** 라벨이 전부 `-1`이라 로컬 채점 불가.
|
|
논문 수치와 직접 대조하려면 예측을 저자(gaoweixiaocuhk@gmail.com)에게 보내야 한다.
|
|
- **`voxel_max`는 중립적 손잡이가 아니다.** 모델 동작점의 일부다.
|
|
같은 체크포인트가 검증 프로토콜에 따라 mIoU 17.19 / 4.20으로 갈렸다.
|
|
- **라이선스**: 데이터 CC BY-NC 4.0, 코드 GPL-3.0. 상업 이용은 저자 허락 필요.
|