This framework provides a robust, process-safe infrastructure for distributed machine learning experiments, particularly designed to work correctly with Python's multiprocessing in 'spawn' mode.
The system uses a hierarchical process model:
- Main Process: Coordinates execution and manages trials
- Trial Processes: Run individual experiments (managed by Optuna)
- Worker Processes: Handle data loading and preprocessing
Process tracking is done through src/common/process_registry.py, which:
- Tracks process hierarchies
- Manages initialization across process boundaries
- Provides safe cleanup during termination
The framework follows a manager-based architecture:
-
Base Managers:
BaseManager: Thread-local state managementBaseProcessManager: Process-aware state management
-
Core Managers:
CUDAManager: Device handling and CUDA availabilityTensorManager: Memory management and tensor creationTokenizerManager: Tokenization servicesDirectoryManager: File and directory operations
-
Mid-level Managers:
DataManager: Dataset creationModelManager: Model loading and savingAMPManager: Automatic mixed precision
-
High-level Managers:
BatchManager: Batch processingMetricsManager: Metric trackingWandbManager: Weights & Biases integration
The system uses dependency injection via src/common/containers.py:
- Managers declare dependencies
- The container resolves and initializes in the right order
- Each process gets its own initialized instances
Critical features for multiprocessing safety:
- Process-local state in managers
- Explicit initialization in child processes
- Signal handling for graceful termination
- Ordered cleanup to handle dependencies
from src.common.managers import initialize_factory
initialize_factory(config)from src.common.managers import get_model_manager, get_data_manager
model_manager = get_model_manager()
data_manager = get_data_manager()When starting new processes, always ensure proper initialization:
from src.common.managers.process_init import ensure_process_initialized
ensure_process_initialized(config)from src.common.managers import cleanup_managers
cleanup_managers()If you encounter errors about managers not being initialized:
- Ensure
ensure_process_initialized()is called at the start of the process - Check that you're accessing managers in the right order
If you see memory leaks:
- Add explicit calls to
clear_memory() - Ensure all tensors are properly moved to CPU before passing to child processes
- Check for circular references
┌─────────────────────┐
│ Main Process │
│ ┌───────────────┐ │
│ │ManagerFactory │ │
│ └───────────────┘ │
└────────┬────────────┘
│
▼
┌─────────────────────┐
│ Child Processes │
│ ┌───────────────┐ │
│ │ ProcessInit │──┼─────► Manager Initialization
│ └───────────────┘ │ in correct order
│ │
│ ┌───────────────┐ │
│ │ BaseManager │ │
│ └───────────────┘ │
└────────┬────────────┘
│
▼
┌─────────────────────┐
│ Cleanup │
│ ┌───────────────┐ │
│ │ProcessRegistry│──┼─────► Safe Resource Release
│ └───────────────┘ │
└─────────────────────┘