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>
6.0 KiB
2단계 — 학습 (GPU 필요)
SETUP.md가 끝난 뒤 실행한다. SETUP_DONE 마커가 없으면 거부한다.
GPU가 아직 바빠도 지금 걸어둘 수 있다. 카드가 빌 때까지 기다렸다가 알아서 시작한다.
이 단계가 하는 것
| 작업 | 시간 |
|---|---|
| GPU 대기 (VRAM 확보될 때까지) | 가변 |
voxel_max 실측 선택 |
10분 |
| 학습 100 epoch | 3~6시간 |
| 평가 (val + test + 4클래스 통합) | 10분 |
1. 사전점검
cd sum-parts-test
RUN_DRYRUN=1 bash scripts/run_train.sh
preflight OK 가 나와야 한다. 검사 항목:
| 항목 | 실패하면 |
|---|---|
SETUP_DONE 마커 |
SETUP.md 먼저 |
conda 환경 sumparts |
동상 |
데이터 24 / 8 / 8 |
동상 |
nvidia-smi + GPU 인식 |
드라이버 문제 — 여기서 해결 |
GPU가 바쁜 것은 실패가 아니다. 인식만 되면 통과한다.
2. 실행
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시간.
조정:
GPU_FREE_MB=20000 GPU_WAIT_MINUTES=1440 \
setsid nohup bash scripts/keepalive.sh train > ~/keepalive-train.out 2>&1 &
상한을 넘기면 실패시키지 않고 그냥 진행한다. 그 시점의 가용 VRAM에 맞춰
voxel_max가 측정되므로, 작게라도 학습은 된다.
3. 확인
cat ~/sum-parts/runs/train/STATUS
state : running
phase : train
cfg : pointvector-xl
voxel_max: 64000
| state | 뜻 |
|---|---|
DONE |
완료 |
waiting |
GPU 비기를 기다리는 중 |
running / retrying |
진행 중 |
FAILED |
note 줄에 원인 |
상세:
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별 소요, 감속 지점
결과:
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 재기동 상한 |
예:
CFG=pointnext-xl EPOCHS=50 \
setsid nohup bash scripts/keepalive.sh train > ~/keepalive-train.out 2>&1 &
중단
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. 상업 이용은 저자 허락 필요.