Joblib#
The JoblibParallelization class in pymoo leverages the popular joblib library to provide powerful and flexible parallelization with multiple execution strategies. This built-in feature offers fine-grained control over parallel execution with support for different backends and advanced configuration options.
Key Features:
Multiple backends: threading, multiprocessing, and loky
Advanced memory mapping for large datasets
Automatic batch sizing and load balancing
Timeout and error handling support
Basic Usage#
[1]:
import os
from pymoo.core.problem import ElementwiseProblem
from pymoo.parallelization.joblib import JoblibParallelization
from pymoo.optimize import minimize
from pymoo.algorithms.soo.nonconvex.ga import GA
class MyProblem(ElementwiseProblem):
def __init__(self, **kwargs):
super().__init__(n_var=10, n_obj=1, n_ieq_constr=0, xl=-5, xu=5, **kwargs)
def _evaluate(self, X, out, *args, **kwargs):
out["F"] = (X ** 2).sum()
# Create joblib runner with default settings (uses all cores)
runner = JoblibParallelization()
problem = MyProblem(elementwise_runner=runner)
res = minimize(problem, GA(), termination=("n_gen", 200), seed=1)
print(f'Joblib runtime: {res.exec_time:.2f} sec with {os.cpu_count()} cores')
Joblib runtime: 3.32 sec with 8 cores
Configuration Options#
The JoblibParallelization class offers extensive configuration options:
Backend Selection#
[2]:
# Use threading backend (good for NumPy operations)
runner_threading = JoblibParallelization(backend="threading")
# Use multiprocessing backend (good for pure Python code)
runner_multiprocessing = JoblibParallelization(backend="multiprocessing")
# Use loky backend (default, robust process-based backend)
runner_loky = JoblibParallelization(backend="loky")
Controlling Number of Jobs#
[3]:
# Use all available cores
runner = JoblibParallelization(n_jobs=-1)
# Use specific number of cores
runner = JoblibParallelization(n_jobs=4)
# Leave one core free
runner = JoblibParallelization(n_jobs=-2)
Advanced Options#
[4]:
# Configure with timeout and verbosity
runner = JoblibParallelization(
n_jobs=4,
backend="loky",
timeout=10.0, # 10 second timeout per task
verbose=10, # Show progress information
batch_size="auto" # Automatic batch sizing
)
# Use generator for streaming results
runner = JoblibParallelization(
return_as="generator", # Get results as they complete
pre_dispatch="2*n_jobs" # Control task pre-dispatching
)
Example with Complex Configuration#
[5]:
# Advanced configuration for production use
runner = JoblibParallelization(
n_jobs=-1, # Use all cores
backend="loky", # Robust process-based backend
timeout=30.0, # 30 second timeout
batch_size="auto", # Automatic batching
verbose=0, # No progress output
max_nbytes="100M", # Memory map large arrays
pre_dispatch="2*n_jobs", # Optimal pre-dispatching
return_as="list" # Wait for all results
)
problem = MyProblem(elementwise_runner=runner)
res = minimize(problem, GA(), termination=("n_gen", 100), seed=1)
print(f'Advanced config runtime: {res.exec_time:.2f} sec')
Advanced config runtime: 1.72 sec