Buckets:

glennmatlin's picture
|
download
raw
10.6 kB
# SOC-91 PACE ICE GPU Enrichment — Full Handoff (2026-03-15)
## What the pipeline does
SOC-91 enriches ~56,514 deduplicated Dolma3 shards with WebOrganizer labels (topic + format classification) using GPU jobs on Georgia Tech's PACE ICE HPC cluster. The pipeline runs 4 classifiers per document: TopicClassifier, TopicClassifier-NoURL, FormatClassifier, FormatClassifier-NoURL. Output is labels-only Parquet sidecars uploaded to Cloudflare R2.
**Architecture:**
- A **launcher job** (`soc91_launcher`, sbatch wrapper around `launch_dual.sh`) runs on a CPU node and submits GPU enrichment tasks in batches of 5
- Each **enrichment task** (`soc91_enrich`) gets 1 GPU, reads a line from the manifest (~20 shard paths per line), downloads each shard from R2, runs 4 classifiers, uploads Parquet sidecar + `.done` marker + `.stats.json` back to R2
- **Idempotency**: before processing a shard, checks if `.done` marker exists in R2. Safe to resubmit any task
- **State file**: `logs/soc91_enrich/launcher_state_coe-ice.txt` tracks which manifest line the launcher will submit next. Launcher reads this on restart to resume
- **Manifest indexing**: `enrich_sidecar.py` reads manifest line N via `manifest.read_text().splitlines()[task_id]`. The `TASK_OFFSET` env var maps SLURM array indices to manifest line numbers (since SLURM array indices are capped at 1000)
## State at handoff (~22:35 EDT 2026-03-15)
- **R2 progress**: 19,348/56,514 shards done (34.2%)
- **Running GPUs**: 8 (severely underutilized, down from 144+ earlier in the week)
- **Pending jobs**: 0 (396 blocked pending jobs were just cancelled)
- **Launcher**: alive (job 4461161, ~4.1h into 8h walltime), at task 2,372/2,826
- **Launcher log shows**: it's now submitting again since pending slots were freed. Was stuck repeating `"At cap (404/400 active, 8 running), waiting..."` before the cancel
---
## Known problems
### Problem 1: Hidden maintenance reservation blocking all pending jobs
- All 396 pending jobs were stuck with reason `ReqNodeNotAvail, Reserved for maintenance`
- SLURM's `PrivateData = accounts,jobs,reservations,usage,users` setting hides reservation details from non-admin users. We cannot see when maintenance starts/ends or which nodes are affected
- Our jobs request `--time=16:00:00` (16h walltime). If maintenance starts within 16h, SLURM won't schedule any new jobs because it can't guarantee completion before maintenance begins
- Result: pending jobs consume submit slots (QOS limit = 500) but never run
- **Key question**: would shorter walltime (4h or 8h) allow jobs to schedule? Each GPU processes ~10 shards/hr, so a 4h job can complete its ~20 shards if the GPU is fast enough
### Problem 2: Submit slot exhaustion (QOSMaxSubmitJobPerUserLimit = 500)
- QOS `coe-ice` allows max 500 submitted jobs (running + pending combined)
- 396 dead-weight pending jobs + 8 running = 404 active, leaving almost no room
- Launcher has its own `MAX_ACTIVE=400` cap (line 9 of `launch_dual.sh`) and was stuck because active count exceeded it
- As running jobs completed, GPU count declined with no replacements: 144 → 138 → 132 → 127 → 122 → 115 → 12 → 8
- **Fix applied**: cancelled all 396 pending jobs via `scancel -u gmatlin3 --name=soc91_enrich -t PENDING`
### Problem 3: Shard selection bias (sequential manifest)
- The manifest (`r2_shard_manifest.txt`) is alphabetically sorted: 2,826 lines, ~20 shards each
- Launcher processes sequentially (task 0, 1, 2...), so all 19,348 completed shards are from `common_crawl` subcategories starting with letters A-S
- **Zero coverage** of: `olmocr_science_pdfs` (21,429 shards, 0%), `phase2_nonpool` (256 shards, 0%), and 7 common_crawl subcategories (software, software_development, sports_and_fitness, transportation, travel_and_tourism, social_life, fashion_and_beauty)
- 8 common_crawl subcategories are at 100% while others are at 0%
- **Fix built but not deployed**: `build_prioritized_manifest.py` creates a new manifest with 7 tiers by category completion rate, shuffled within tiers, skipping 100%-done categories. Dry-run verified: 39,294 remaining shards across ~1,965 lines
### Problem 4: Draining/drained nodes
- 6 GPU nodes currently unavailable (4 drained, 1 drained*, 1 draining)
- As running jobs on draining nodes complete, those GPUs become permanently unavailable until maintenance ends
- This causes the steady decline in running GPUs
### Resolved misdiagnosis: "Ghost GPU allocations"
- Initially appeared that 89 GPUs on H100/H200 nodes had zero jobs
- Root cause: `PrivateData = jobs` hides other users' jobs from `squeue`
- The allocations were real jobs from other users, not a bug
---
## What was done on 2026-03-15
1. Diagnosed the hidden maintenance reservation as root cause (not a misconfiguration on our end)
2. Built `manifest_coverage.py` — reports per-subcategory completion rates vs R2
3. Built `build_prioritized_manifest.py` — prioritized manifest with 7 tiers. Dry-run output:
- T0: 28,879 shards (0% done, 16 categories including all olmocr + phase2)
- T1: 2,130 shards (0-15% done)
- T2: 5,350 shards (15-35% done)
- T3: 2,176 shards (35-60% done)
- T4: 180 shards (60-80% done)
- T5: 538 shards (80-95% done)
- T6: 41 shards (95-100% done)
- Skipped: 8,130 shards from 100% complete categories
4. Cancelled 396 blocked pending jobs to free submit slots
---
## Action items for next session
1. **Test shorter walltime**: Submit a single test job with `--time=4:00:00` to see if it schedules. If it does, the maintenance window is >4h away and shorter walltimes bypass the scheduling block:
```
ssh pace-ice "cd ~/dev/data-attribution-soc91 && sbatch --qos=coe-ice --time=4:00:00 --array=0-0 scripts/slurm/enrich_sidecar_gpu.sbatch"
```
Check if it goes to RUNNING or PENDING with `squeue -u gmatlin3 -h -t PENDING -o '%i %r'`
2. **Deploy the prioritized manifest**:
```
ssh pace-ice "cd ~/dev/data-attribution-soc91 && source ~/.r2_credentials && python3 scripts/slurm/build_prioritized_manifest.py"
```
This writes `scripts/slurm/r2_shard_manifest_prioritized.txt`. Then update the launcher to use it by either:
- Setting `MANIFEST=scripts/slurm/r2_shard_manifest_prioritized.txt` in the sbatch environment
- Or editing `enrich_sidecar_gpu.sbatch` line 102: change `MANIFEST="${MANIFEST:-scripts/slurm/r2_shard_manifest.txt}"` to point at the prioritized manifest
- Reset the state file: `echo 0 > logs/soc91_enrich/launcher_state_coe-ice.txt`
3. **Resubmit launcher** when the current one expires (~3.9h remaining on job 4461161):
```
ssh pace-ice "cd ~/dev/data-attribution-soc91 && sbatch --qos=coe-ice --partition=ice-cpu --time=8:00:00 scripts/slurm/launcher.sbatch"
```
If using shorter walltime for GPU jobs, also update `enrich_sidecar_gpu.sbatch` line 8 (`--time=16:00:00`) before resubmitting
4. **Monitor GPU recovery**: after cancelling pending jobs the launcher should be submitting new tasks. Verify with:
```
ssh pace-ice "squeue -u gmatlin3 -h --name=soc91_enrich -t RUNNING | wc -l"
ssh pace-ice "squeue -u gmatlin3 -h -r --name=soc91_enrich -t PENDING | wc -l"
ssh pace-ice "tail -5 ~/dev/data-attribution-soc91/logs/soc91_launcher/4461161.out"
```
5. **Determine maintenance window**: try `scontrol show reservation` (may return nothing due to PrivateData), check https://pace.gatech.edu for announcements, or email pace-support@oit.gatech.edu
6. **R2 completion check**:
```
ssh pace-ice "source ~/.r2_credentials && python3 -c \"import boto3,os;s3=boto3.client('s3',endpoint_url='https://0934ab8e84ac8f4e81decaf3eb121337.r2.cloudflarestorage.com',aws_access_key_id=os.environ['R2_ACCESS_KEY_ID'],aws_secret_access_key=os.environ['R2_SECRET_ACCESS_KEY'],region_name='auto');p=s3.get_paginator('list_objects_v2');d=sum(1 for pg in p.paginate(Bucket='soc127-dedup',Prefix='soc91-labels/') for o in pg.get('Contents',[]) if o['Key'].endswith('.done'));print(f'r2_done={d}/56514 ({d/56514*100:.1f}%)');\""
```
---
## Key files on cluster (`~/dev/data-attribution-soc91/`)
| File | Purpose |
|------|---------|
| `scripts/slurm/r2_shard_manifest.txt` | Current manifest (alphabetical, 2,826 lines, 56,514 shards) |
| `scripts/slurm/r2_shard_manifest_prioritized.txt` | Output of prioritized builder (not yet generated) |
| `scripts/slurm/build_prioritized_manifest.py` | Builds prioritized manifest from R2 .done state |
| `scripts/slurm/manifest_coverage.py` | Reports per-subcategory completion rates |
| `scripts/slurm/launch_dual.sh` | Launcher logic (MAX_ACTIVE=400, BATCH=5, state checkpoint) |
| `scripts/slurm/launcher.sbatch` | Launcher sbatch wrapper (CPU node, 18h walltime) |
| `scripts/slurm/enrich_sidecar_gpu.sbatch` | GPU enrichment job (1 GPU, 16h walltime, auto-detects VRAM/dtype) |
| `scripts/enrich_sidecar.py` | Enrichment worker (reads manifest by task_id, runs 4 classifiers) |
| `logs/soc91_enrich/launcher_state_coe-ice.txt` | Current state: 2372 (line number in manifest) |
| `logs/soc91_launcher/4461161.out` | Current launcher log |
## Key constants and infrastructure
| Item | Value |
|------|-------|
| R2 bucket | `soc127-dedup` |
| R2 output prefix | `soc91-labels/` |
| R2 endpoint | `https://0934ab8e84ac8f4e81decaf3eb121337.r2.cloudflarestorage.com` |
| R2 credentials | `source ~/.r2_credentials` on cluster |
| QOS | `coe-ice` (max submit: 500, max GPUs: 960) |
| SLURM partitions | `ice-gpu,coe-gpu,ice-bw-gpu` |
| GPU constraint | `-C nvidia-gpu` (any NVIDIA GPU) |
| Excluded nodes | `atl1-1-03-014-16-0` (bad GPU) |
| Username | `gmatlin3` |
| Worktree path | `~/dev/data-attribution-soc91` |
| Launcher MAX_ACTIVE | 400 (in launch_dual.sh) |
| Launcher BATCH | 5 tasks per submission |
| GPU job walltime | 16:00:00 (may need reduction) |
| Batch size | Auto-detected by VRAM (128/64/32/16) |
| Classifier max_length | 8192 tokens |
| Dtype | bf16 (auto-downgrades to fp16 for compute capability < 8.0) |
## SSH access pattern
All cluster interaction is via `ssh pace-ice "command"`. Each invocation is a fresh login shell. No state persists between calls. The user must have an active SSH control socket (ControlMaster). If SSH times out or hangs, the user needs to re-authenticate in a separate terminal with `ssh pace-ice`.
## Throughput baseline
- Each GPU processes ~10 shards/hr (varies by GPU type and shard size)
- At 144 GPUs: ~1,440 shards/hr (~39h for remaining 37,166 shards)
- At 8 GPUs: ~80 shards/hr (~464h, not viable)
- Target: get GPU count back above 100 by fixing the scheduling issue

Xet Storage Details

Size:
10.6 kB
·
Xet hash:
f3ef86b5ccd1a9dc564e1523a9676989b81ce750090fe2f1c99c837e38d695a5

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.