Skip to content

Commit ad1a4cc

Browse files
committed
(#13) Added hardware specific configurations
1 parent d05ebe8 commit ad1a4cc

File tree

1 file changed

+77
-16
lines changed

1 file changed

+77
-16
lines changed

runs/icon_etopo_global.py

Lines changed: 77 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -507,10 +507,51 @@ def parallel_wrapper(grid, params, reader, writer, chunk_output_dir, clat_rad, c
507507
from tqdm import tqdm
508508

509509
if __name__ == '__main__':
510+
# ========================================================================
511+
# CONFIGURATION SELECTOR
512+
# ========================================================================
513+
# Choose one: 'generic_laptop', 'dkrz_hpc', 'laptop_performance'
514+
SYSTEM_CONFIG = 'laptop_performance' # ← Edit this line to switch configs
515+
# ========================================================================
516+
517+
CONFIGS = {
518+
'generic_laptop': {
519+
'total_cores': 12, # Conservative: use 12 of 16 threads
520+
'total_memory_gb': 12.0,
521+
'netcdf_chunk_size': 100,
522+
'memory_per_cpu_mb': None, # Will calculate dynamically
523+
'description': 'Generic laptop (16 threads, 16GB RAM)'
524+
},
525+
'dkrz_hpc': {
526+
'total_cores': 128,
527+
'total_memory_gb': 240.0,
528+
'netcdf_chunk_size': 1000,
529+
'memory_per_cpu_mb': 1940, # SLURM quota on interactive partition
530+
'description': 'DKRZ HPC interactive partition (standard memory node)'
531+
},
532+
'laptop_performance': {
533+
'total_cores': 20, # Use 20 of 24 threads (leave 4 for background)
534+
'total_memory_gb': 80.0,
535+
'netcdf_chunk_size': 100,
536+
'memory_per_cpu_mb': None, # Will calculate dynamically
537+
'description': 'AMD Ryzen AI 9 HX 370 (24 threads, 94GB RAM)'
538+
}
539+
}
540+
541+
# Validate configuration selection
542+
if SYSTEM_CONFIG not in CONFIGS:
543+
raise ValueError(f"Invalid SYSTEM_CONFIG '{SYSTEM_CONFIG}'. Choose from: {list(CONFIGS.keys())}")
544+
545+
config = CONFIGS[SYSTEM_CONFIG]
546+
510547
# Set up logging first
511548
log_file = setup_logger(log_dir="logs")
512549
print(f"Logging to: {log_file}")
513550
print("=" * 80)
551+
print(f"SYSTEM CONFIG: {SYSTEM_CONFIG}")
552+
print(f" {config['description']}")
553+
print(f" Cores: {config['total_cores']}, Memory: {config['total_memory_gb']} GB")
554+
print("=" * 80)
514555

515556
# Override/add ETOPO-specific parameters
516557
params.fn_output = "icon_etopo_global"
@@ -578,22 +619,23 @@ def parallel_wrapper(grid, params, reader, writer, chunk_output_dir, clat_rad, c
578619
import multiprocessing
579620
import os
580621

581-
# Determine total system resources
582-
total_cores = os.cpu_count() or 1
583-
584-
# Estimate total available memory for processing
585-
# On laptop: typically 60 GB available (leave some for OS)
586-
# On HPC: typically 240 GB available (256 GB total - 16 GB for OS)
587-
if total_cores >= 64:
588-
# High-performance node
589-
total_memory_gb = 240.0
590-
netcdf_chunk_size = 1000 # 1000 cells per NetCDF file
591-
logger.info(f"HIGH-PERFORMANCE MODE: {total_cores} cores, ~240 GB RAM available")
622+
# Use configuration values
623+
total_cores = config['total_cores']
624+
total_memory_gb = config['total_memory_gb']
625+
netcdf_chunk_size = config['netcdf_chunk_size']
626+
627+
logger.info("=" * 80)
628+
logger.info(f"RESOURCE CONFIGURATION: {SYSTEM_CONFIG}")
629+
logger.info(f" Description: {config['description']}")
630+
logger.info(f" Available cores: {total_cores}")
631+
logger.info(f" Available memory: {total_memory_gb} GB")
632+
logger.info(f" NetCDF chunk size: {netcdf_chunk_size} cells")
633+
if config['memory_per_cpu_mb'] is not None:
634+
logger.info(f" SLURM quota: {config['memory_per_cpu_mb']} MB per CPU")
635+
logger.info(f" Mode: HPC (threads scale with worker memory)")
592636
else:
593-
# Laptop/workstation
594-
total_memory_gb = 60.0
595-
netcdf_chunk_size = 100 # 100 cells per NetCDF file
596-
logger.info(f"STANDARD MODE: {total_cores} cores, ~60 GB RAM available")
637+
logger.info(f" Mode: Laptop (threads distributed evenly)")
638+
logger.info("=" * 80)
597639

598640
# Group cells by memory requirements for dynamic worker allocation
599641
logger.info(f"\nAnalyzing cells by latitude for dynamic memory allocation...")
@@ -678,12 +720,31 @@ def parallel_wrapper(grid, params, reader, writer, chunk_output_dir, clat_rad, c
678720
n_workers = batch_config['n_workers']
679721
memory_per_worker = f"{int(batch_config['memory_per_worker_gb'])}GB"
680722

723+
# Calculate threads per worker based on configuration
724+
if config['memory_per_cpu_mb'] is not None:
725+
# HPC mode: Use SLURM's memory-per-CPU quota
726+
# Each worker gets CPUs proportional to its memory allocation
727+
threads_per_worker = max(1, int(
728+
batch_config['memory_per_worker_gb'] * 1000 / config['memory_per_cpu_mb']
729+
))
730+
else:
731+
# Laptop mode: Calculate based on total available resources
732+
# How many workers can we fit given memory constraints?
733+
max_workers_by_memory = max(1, int(
734+
config['total_memory_gb'] / batch_config['memory_per_worker_gb']
735+
))
736+
# Limit workers to what we actually configured
737+
actual_workers = min(max_workers_by_memory, n_workers)
738+
# Distribute threads evenly across workers
739+
threads_per_worker = max(1, config['total_cores'] // actual_workers)
740+
681741
logger.info(f"\n Starting Dask client for memory batch {mem_batch_idx}:")
682742
logger.info(f" Workers: {n_workers} × {memory_per_worker}")
743+
logger.info(f" Threads per worker: {threads_per_worker}")
683744
logger.info(f" Expected memory per cell: {batch_config['memory_per_cell_gb']:.1f} GB")
684745

685746
client = Client(
686-
threads_per_worker=1,
747+
threads_per_worker=threads_per_worker,
687748
n_workers=n_workers,
688749
processes=True,
689750
memory_limit=memory_per_worker,

0 commit comments

Comments
 (0)