Files
foxhunt/docs/archive/wave_d/agents/AGENT_3_FINAL_REPORT.md
jgrusewski 433af5c25d chore: Major codebase cleanup - remove deprecated files and organize structure
- Docker: Delete 23 deprecated Dockerfiles, fix CI/CD to use Dockerfile.foxhunt-build
- Config: Remove 36 .env files, keep 4 essential, delete config/environments/
- Docs: Archive 614 Wave D files to docs/archive/wave_d/, 95% reduction in root
- Scripts: Delete 56 deprecated scripts, keep 58 production-critical (49% reduction)
- Python: Organize 37 scripts into scripts/python/ subdirectories, delete ml/python/
- Build: Remove 1GB artifacts, delete old venvs, clean Python cache from git
- Migrations: Delete deprecated directory (4,432 lines), remove duplicate database/migrations/
- Infrastructure: Delete deployment/ (61 files), docs/scripts/ (8 files)

Total impact: ~2,500 files cleaned, 750MB+ space freed, zero production impact
All deleted scripts backed up to archives. runpod/ and tests/runpod/ preserved.
data_acquisition_service retained per user request.
2025-10-30 01:02:34 +01:00

5.0 KiB
Raw Blame History

Agent 3: Final Integration Test Report

Date: 2025-10-26 Task: Commit all fixes from Agents 1 & 2, run final integration test Status: FAILED - OOM During Validation


Commits Created

Commit 1: 56956818

fix(ml): Final TFT memory leak fixes - validation cache + CLI defaults

Issue: This commit INCORRECTLY claimed to include Agent 1's cache clearing fix, but the actual code only called sync_cuda_device() which doesn't clear the model's attention cache.

Commit 2: 85e51f6e (CRITICAL FIX)

fix(ml): CRITICAL - Add model.clear_cache() to validation loop

Fix: Added self.model.clear_cache() inside the validation loop every 10 batches. This is the actual fix needed to prevent cache accumulation.


Integration Test Results

Command

cargo run -p ml --example train_tft_parquet --release --features cuda -- \
  --parquet-file test_data/ES_FUT_small.parquet \
  --batch-size 1 \
  --epochs 5 \
  --use-gpu

Results

BUILD: SUCCESS (1m 33s compile) COMMIT: 85e51f6e TRAINING: 0/5 epochs completed VALIDATION: OOM (died at validation start) MEMORY: Peak usage 1611MB before validation → OOM during validation VERDICT: VALIDATION OOM - FIXES INSUFFICIENT


Memory Profile Analysis

[MEMORY] Epoch 0 START: 1291.0MB / 4096.0MB (31.5%)
[Training Phase]
[MEMORY] Epoch 0 AFTER_TRAINING: 1611.0MB / 4096.0MB (39.3%)
[MEMORY] Dropped optimizer before validation to free ~1100MB AdamW state
[MEMORY] Epoch 0 BEFORE_VALIDATION: 1611.0MB / 4096.0MB (39.3%)
[MEMORY] Validation START (Epoch 0): 1611.0MB / 4096.0MB
Error: Training OOM after 0 retries (final batch_size=1)

Problem: Starting validation at 1611MB + 176 validation batches (each adds ~14MB) = ~4000MB total, exceeding 4096MB GPU memory.


Root Cause Analysis

Issue #1: Optimizer Not Actually Dropped

The log says "Dropped optimizer before validation to free ~1100MB AdamW state" but memory stays at 1611MB (39.3%). This means:

  1. The optimizer drop is not actually freeing memory
  2. OR the memory is immediately reallocated by CUDA
  3. OR there's another memory leak preventing the reclaim

Issue #2: Validation Cache Accumulation

Even with model.clear_cache() every 10 batches:

  • 176 validation batches / 10 = 17 cache clears
  • Between clears: 10 batches × ~14MB = 140MB accumulation
  • Total leak over validation: 17 × 140MB = 2380MB

This exceeds available memory (4096MB - 1611MB = 2485MB).

Issue #3: Batch Size = 1 Inefficiency

With batch_size=1, we have 176 separate forward passes instead of batching. Each creates tensors, runs attention, etc., fragmenting GPU memory.


Proposed Solutions

Option A: Aggressive Cache Clearing (QUICK FIX)

Change: Clear cache EVERY batch instead of every 10 batches Impact: Validation slower (~10% overhead) but memory usage <100MB Effort: 2 minutes (change i % 10 to i % 1)

Change: Add explicit CUDA memory clearing:

if i % 10 == 0 && self.device.is_cuda() {
    self.model.clear_cache();

    // Force CUDA to actually free memory
    if let Ok(mut sizer) = AutoBatchSizer::new() {
        sizer.force_memory_cleanup()?;
    }
}

Impact: Ensures memory is actually freed, not just marked for GC Effort: 15 minutes (implement force_memory_cleanup())

Option C: Increase Validation Batch Size

Change: Use validation_batch_size=4 instead of 1 Impact: 176 batches → 44 batches (4× reduction in memory churn) Effort: 1 minute (command line flag) Risk: May still OOM if optimizer isn't actually freed

Option D: Skip Validation on Small Datasets (WORKAROUND)

Change: Don't run validation when dataset <1000 samples Impact: Training completes but no validation metrics Effort: 5 minutes Drawback: Doesn't fix the underlying memory leak


Recommendation

Immediate: Try Option A (clear cache every batch) + Option C (batch_size=4) Next: Implement Option B (force CUDA cleanup) if Option A fails Long-term: Profile optimizer drop to confirm it's actually freeing 1100MB


Test Command for Next Iteration

# Option A + C combined
cargo run -p ml --example train_tft_parquet --release --features cuda -- \
  --parquet-file test_data/ES_FUT_small.parquet \
  --batch-size 4 \
  --validation-batch-size 4 \
  --epochs 5 \
  --use-gpu

# Expected: 704/4=176 train batches, 176/4=44 val batches (75% reduction)

Files Modified

  1. ml/src/trainers/tft.rs

    • Line 1500: Added self.model.clear_cache() every 10 batches
    • Still OOMs due to optimizer not freeing memory
  2. ml/examples/train_tft_parquet.rs (Agent 2, not committed)

    • CLI defaults fix not yet in codebase
    • Needs separate commit

Conclusion

Status: Fixes applied but insufficient Blocker: Optimizer drop not freeing 1100MB as expected Next Steps: Implement aggressive cache clearing (every batch) + larger validation batch size ETA: 15-30 minutes for Option A+C, 1 hour for Option B if needed