Skip to content

Commit 6a051c7

Browse files
committed
fixed runtime estimate function and default grid size. 1000x1000 grid on 15 reps would take approx 3 hours
1 parent f381791 commit 6a051c7

3 files changed

Lines changed: 36 additions & 19 deletions

File tree

docs/HPC_GUIDE.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ scancel <JOBID>
3939
4040
tail -f logs_<JOBID>.err
4141
42+
# Watch task completetion
43+
44+
watch -n 10 "ls -1 results_JOBID | wc -l"
45+
4246
# Fetching the results once the job is done
4347
4448
scp -r kanagnostopoul@snellius.surf.nl:~/results_18532145 ~/Downloads/

hpc/run_analysis.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ echo "Output directory: $OUTPUT_DIR"
6464
echo ""
6565

6666
# Run the full analysis
67-
python3 pp_analysis.py \
67+
python3 -u scripts/pp_analysis.py \
6868
--mode full \
6969
--output $OUTPUT_DIR \
7070
--cores $SLURM_CPUS_PER_TASK

scripts/pp_analysis.py

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
from pathlib import Path
3232
from typing import Dict, List, Tuple, Optional
3333
import warnings
34+
from tqdm import tqdm
3435

3536
project_root = str(Path(__file__).parents[1])
3637
if project_root not in sys.path:
@@ -83,7 +84,7 @@ class Config:
8384
predator_birth: float = 0.2
8485

8586
# Replicates
86-
n_replicates: int = 50
87+
n_replicates: int = 15
8788

8889
# Simulation timing
8990
warmup_steps: int = 200
@@ -130,22 +131,36 @@ def get_prey_births(self) -> np.ndarray:
130131
return np.linspace(self.prey_birth_min, self.prey_birth_max, self.n_prey_birth)
131132

132133
def estimate_runtime(self, n_cores: int = 32) -> str:
133-
"""Estimate total runtime."""
134+
"""Estimate total runtime based on benchmark data."""
134135
n_sweep = self.n_prey_birth * self.n_prey_death * self.n_replicates * 2
135136
n_sens = len(self.sensitivity_sd_values) * self.sensitivity_replicates
136137

137-
# Base time per simulation (with optimized PCF)
138-
base_time_s = 0.8 # ~800ms with cell-list PCF
139-
pcf_overhead = 0.1 if self.collect_pcf else 0 # Much smaller with cell-list
138+
# --- Scaling Logic ---
139+
# Benchmark shows 1182 steps/sec for 100x100 grid
140+
ref_size = 100
141+
ref_steps_per_sec = 1182
140142

143+
# Scale throughput by area (L^2)
144+
# A 1000x1000 grid is (1000/100)^2 = 100x slower per step
145+
size_scaling = (self.default_grid / ref_size) ** 2
146+
actual_steps_per_sec = ref_steps_per_sec / size_scaling
147+
148+
# Calculate time for one full simulation (warmup + measurement)
149+
total_steps_per_sim = self.warmup_steps + self.measurement_steps
150+
base_time_s = total_steps_per_sim / actual_steps_per_sec
151+
152+
# Account for PCF overhead (Cell-list PCF is ~8ms for 100x100)
153+
pcf_time_s = (0.008 * size_scaling) if self.collect_pcf else 0
154+
# ---------------------
155+
141156
# FSS with size scaling
142157
fss_time = 0
143158
for L in self.fss_grid_sizes:
144-
scale = (L / self.default_grid) ** 2
145-
warmup_scale = L / self.default_grid
146-
fss_time += self.fss_replicates * base_time_s * scale * warmup_scale
159+
l_scale = (L / self.default_grid) ** 2
160+
l_warmup_scale = L / self.default_grid # Time also scales with warmup duration
161+
fss_time += self.fss_replicates * base_time_s * l_scale * l_warmup_scale
147162

148-
sweep_time = n_sweep * (base_time_s + pcf_overhead * self.pcf_sample_rate)
163+
sweep_time = n_sweep * (base_time_s + pcf_time_s * self.pcf_sample_rate)
149164
sens_time = n_sens * base_time_s
150165

151166
total_seconds = (sweep_time + sens_time + fss_time) / n_cores
@@ -154,8 +169,6 @@ def estimate_runtime(self, n_cores: int = 32) -> str:
154169

155170
n_total = n_sweep + n_sens + sum(self.fss_replicates for _ in self.fss_grid_sizes)
156171
return f"{n_total:,} sims, ~{hours:.1f}h on {n_cores} cores (~{core_hours:.0f} core-hours)"
157-
158-
159172
# =============================================================================
160173
# HELPER FUNCTIONS
161174
# =============================================================================
@@ -571,10 +584,10 @@ def run_2d_sweep(cfg: Config, output_dir: Path, logger: logging.Logger) -> List[
571584
logger.info(f" Replicates: {cfg.n_replicates}")
572585
logger.info(f" PCF sample rate: {cfg.pcf_sample_rate:.0%}")
573586

574-
results = Parallel(n_jobs=cfg.n_jobs, verbose=10)(
587+
results = Parallel(n_jobs=cfg.n_jobs, verbose=0)(
575588
delayed(run_single_simulation)(pb, pd, gs, seed, evo, cfg)
576-
for pb, pd, gs, seed, evo in jobs
577-
)
589+
for pb, pd, gs, seed, evo in tqdm(jobs, desc="2D Sweep Progress", mininterval=30)
590+
)
578591

579592
# Save results
580593
output_file = output_dir / "sweep_results.npz"
@@ -610,9 +623,9 @@ def run_sensitivity(cfg: Config, output_dir: Path, logger: logging.Logger) -> Li
610623
logger.info(f"Sensitivity: {len(jobs)} simulations")
611624
logger.info(f" SD values: {cfg.sensitivity_sd_values}")
612625

613-
results = Parallel(n_jobs=cfg.n_jobs, verbose=5)(
626+
results = Parallel(n_jobs=cfg.n_jobs, verbose=0)(
614627
delayed(run_single_simulation)(pb, pd, gs, seed, evo, cfg, evolve_sd=sd, compute_pcf=True)
615-
for pb, pd, gs, seed, evo, sd in jobs
628+
for pb, pd, gs, seed, evo, sd in tqdm(jobs, desc="Sensitivity Progress", mininterval=10)
616629
)
617630

618631
output_file = output_dir / "sensitivity_results.json"
@@ -665,9 +678,9 @@ def run_fss(cfg: Config, output_dir: Path, logger: logging.Logger) -> List[Dict]
665678
logger.info(f"FSS: {len(jobs)} simulations")
666679
logger.info(f" Grid sizes: {cfg.fss_grid_sizes}")
667680

668-
results = Parallel(n_jobs=cfg.n_jobs, verbose=5)(
681+
results = Parallel(n_jobs=cfg.n_jobs, verbose=0)(
669682
delayed(run_single_simulation_fss)(pb, pd, gs, seed, cfg, ws, ms)
670-
for pb, pd, gs, seed, ws, ms in jobs
683+
for pb, pd, gs, seed, ws, ms in tqdm(jobs, desc="FSS Progress", mininterval=10)
671684
)
672685

673686
output_file = output_dir / "fss_results.json"

0 commit comments

Comments
 (0)