Performance
GPU sizing
Section titled “GPU sizing”Adjust batch size
Section titled “Adjust batch size”pheno.process_images(wrapper, batch_size=16)pheno.process_images(wrapper, batch_size=64)Higher is faster but uses more memory. Drop on OOM.
Check GPU availability
Section titled “Check GPU availability”import torch
print(f"CUDA available: {torch.cuda.is_available()}")print(f"CUDA device: {torch.cuda.get_device_name(0)}")total = torch.cuda.get_device_properties(0).total_memory / 1e9print(f"GPU memory: {total:.1f} GB")
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")Multi-GPU selection
Section titled “Multi-GPU selection”device = torch.device("cuda:0")device = torch.device("cuda:1")Pass the same device to load_dinov2_model(...) and PhenoMe(...).
Memory management
Section titled “Memory management”Clear GPU memory
Section titled “Clear GPU memory”import gcimport torch
def clear_gpu_memory() -> None: """Free GPU memory between stages.""" gc.collect() torch.cuda.empty_cache()
clear_gpu_memory()Process in chunks
Section titled “Process in chunks”For very large datasets:
file_df = pheno.find_files("path/to/images")
chunk_size = 1000chunks = [file_df[i:i + chunk_size] for i in range(0, len(file_df), chunk_size)]
for i, chunk_df in enumerate(chunks): print(f"Processing chunk {i + 1}/{len(chunks)}") pheno.set_file_df(chunk_df) pheno.process_images( wrapper, batch_size=32, append=(i > 0), ) clear_gpu_memory()Monitor memory usage
Section titled “Monitor memory usage”import psutilimport torch
def print_memory_status() -> None: process = psutil.Process() cpu_mem = process.memory_info().rss / 1e9 print(f"CPU memory: {cpu_mem:.2f} GB")
if torch.cuda.is_available(): gpu_mem = torch.cuda.memory_allocated() / 1e9 gpu_max = torch.cuda.max_memory_allocated() / 1e9 print(f"GPU memory: {gpu_mem:.2f} GB (max {gpu_max:.2f} GB)")Throughput tips
Section titled “Throughput tips”Choose num_workers
Section titled “Choose num_workers”import os
num_workers = min(4, (os.cpu_count() or 2) - 1)pheno.process_images(wrapper, num_workers=num_workers)Filter early
Section titled “Filter early”Do not process what you will not use later.
pheno.process_images( wrapper, filters={"condition": ["Control", "Drug1"]}, batch_size=32,)Checkpoint and reload
Section titled “Checkpoint and reload”pheno.process_images(wrapper, checkpoint_path="results/run.h5")pheno.save_results("results.h5")
pheno.find_files("path/to/images")pheno.load_results("results.h5")Troubleshooting
Section titled “Troubleshooting”GPU out of memory
Section titled “GPU out of memory”Symptom: RuntimeError: CUDA out of memory.
Fixes (in order):
- Reduce
batch_size. - Pick a smaller model (for example
vits14). gc.collect(); torch.cuda.empty_cache()between stages.- Process in chunks (see above).
pheno.process_images(wrapper, batch_size=8)Slow processing
Section titled “Slow processing”Symptom: jobs take much longer than expected.
Fixes:
- Increase
batch_sizeif GPU has headroom. - Increase
num_workers. - Use SSD storage.
- Pre-filter to the subset you actually need.
print(f"Device: {wrapper.device}") # should say cuda:Xpheno.process_images(wrapper, batch_size=64, num_workers=8)DR on GPU runs out of memory
Section titled “DR on GPU runs out of memory”Install pykeops so t-SNE / UMAP use memory-efficient GPU kernels:
pip install pykeopsPCA is already batched through ExactIncrementalPCA.
Wrap processing with fallback
Section titled “Wrap processing with fallback”try: pheno.process_images(wrapper, batch_size=32)except RuntimeError as e: if "out of memory" in str(e): clear_gpu_memory() pheno.process_images(wrapper, batch_size=16) else: raiseLogging for long runs
Section titled “Logging for long runs”import logging
logging.basicConfig( level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s", handlers=[logging.FileHandler("processing.log"), logging.StreamHandler()],)
logger = logging.getLogger(__name__)
logger.info("Starting processing")try: pheno.process_images(wrapper) logger.info("Processing complete")except Exception: logger.exception("Processing failed") raiseSee also
Section titled “See also”- Reproducibility - trade-offs with CPU DR backends.
- Data organization - avoid re-processing what you do not need.
- External checkpoints - load embeddings computed elsewhere.
