diff --git a/CHANGELOG.md b/CHANGELOG.md index 904685f3..d115f455 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Change log +## [v1.3.3] 2026-08-dd + +### Enhancement + +- Add device mode synchronization between ModelConfig and QEPConfig. + ## [v1.3.2] 2026-08-24 ### Bug Fix diff --git a/docs/algorithms/lpcd.md b/docs/algorithms/lpcd.md index ffc38546..df30914f 100644 --- a/docs/algorithms/lpcd.md +++ b/docs/algorithms/lpcd.md @@ -71,7 +71,6 @@ lpcd_config = LPCDConfig( perccorr=0.5, percdamp=0.01, use_closed_form=True, - device="cuda:0", ) runner = Runner( @@ -131,7 +130,7 @@ You can use LPCD without QEP, but the common setup in OneComp is `GPTQ + QEP + L | `gd_steps` | `int` | Gradient-descent steps per sub-problem | `20` | | `gd_batch_size` | `int` | Effective batch size for gradient accumulation | `16` | | `gd_base_lr` | `float` | Base learning rate for gradient solver | `1e-4` | -| `device` | `str` | Device for LPCD optimization | `"cuda:0"` | +| `device` | `str` | Device for LPCD optimization | `None` | ## Current Support diff --git a/docs/algorithms/qep.md b/docs/algorithms/qep.md index 2ba04310..355f5a21 100644 --- a/docs/algorithms/qep.md +++ b/docs/algorithms/qep.md @@ -83,7 +83,6 @@ qep_config = QEPConfig( general=False, # Architecture-aware (default) percdamp=0.01, # Hessian damping perccorr=0.5, # Correction strength - device="cuda:0", # GPU for QEP computation exclude_layer_keywords=["mlp.down_proj"], ) @@ -117,7 +116,7 @@ runner.run() | `general` | `bool` | Use generic (architecture-independent) QEP | `False` | | `percdamp` | `float` | Damping percentage for Hessian regularization | `0.01` | | `perccorr` | `float` | Correction strength (0 = no correction, 1 = full)| `0.5` | -| `device` | `str` | GPU device for QEP computation | `"cuda:0"` | +| `device` | `str` | GPU device for QEP computation | `None` | | `exclude_layer_keywords` | `list[str]` | Layer keywords excluded from error propagation | `["mlp.down_proj"]` | !!! note diff --git a/docs/user-guide/configuration.md b/docs/user-guide/configuration.md index 2ba90287..b960b4ee 100644 --- a/docs/user-guide/configuration.md +++ b/docs/user-guide/configuration.md @@ -153,7 +153,7 @@ qep_config = QEPConfig( | `general` | `bool` | Use generic (architecture-independent) QEP | `False` | | `percdamp` | `float` | Damping percentage for Hessian regularization | `0.01` | | `perccorr` | `float` | Correction percentage for error propagation | `0.5` | -| `device` | `str` | Device for QEP computations (`"cuda"`, `"mps"`, `"cpu"`) | `"cuda:0"` | +| `device` | `str` | Device for QEP computations (`"cuda"`, `"mps"`, `"cpu"`) | `None` | | `exclude_layer_keywords` | `list[str]` | Layer keywords excluded from error propagation | `["mlp.down_proj"]` | !!! tip @@ -188,7 +188,7 @@ lpcd_config = LPCDConfig( | `gd_steps` | `int` | Gradient-descent steps per sub-problem | `20` | | `gd_batch_size` | `int` | Effective batch size for gradient accumulation | `16` | | `gd_base_lr` | `float` | Base learning rate for gradient solver | `1e-4` | -| `device` | `str` | Device for LPCD computation | `"cuda:0"` | +| `device` | `str` | Device for LPCD computation | `None` | !!! tip `LPCDConfig()` defaults to residual-only refinement, which is the fastest diff --git a/onecomp/__version__.py b/onecomp/__version__.py index 0919865f..022c0c7e 100644 --- a/onecomp/__version__.py +++ b/onecomp/__version__.py @@ -6,4 +6,4 @@ """ -__version__ = "1.3.2" +__version__ = "1.3.3" diff --git a/onecomp/lpcd/_lpcd_config.py b/onecomp/lpcd/_lpcd_config.py index 6e291ccc..652d6f43 100644 --- a/onecomp/lpcd/_lpcd_config.py +++ b/onecomp/lpcd/_lpcd_config.py @@ -25,7 +25,8 @@ class LPCDConfig: gd_steps: Number of gradient-descent epochs per sub-problem. gd_batch_size: Effective batch size for gradient accumulation. gd_base_lr: Base learning rate for gradient-descent solver. - device: Device to perform LPCD optimisation on. + device: Device to perform LPCD optimisation on. Default is None. + When None, Runner synchronises it with ModelConfig.device. Examples: Minimal (residual correction only, fast):: @@ -53,4 +54,4 @@ class LPCDConfig: gd_steps: int = 20 gd_batch_size: int = 16 gd_base_lr: float = 1e-4 - device: str = "cuda:0" + device: str = None diff --git a/onecomp/qep/_qep_config.py b/onecomp/qep/_qep_config.py index 4e936785..1cd750cb 100644 --- a/onecomp/qep/_qep_config.py +++ b/onecomp/qep/_qep_config.py @@ -25,7 +25,7 @@ class QEPConfig: Default is 0.5. device (str): Device to use for QEP computations (e.g., "cuda", "mps", "cpu"). - Default is "cuda:0". + Default is None. When None, Runner synchronises it with ModelConfig.device. exclude_layer_keywords (list[str]): List of keywords to identify layers excluded from error propagation. Layers whose names contain any of these keywords will be excluded. @@ -52,6 +52,6 @@ class QEPConfig: general: bool = False percdamp: float = 0.01 perccorr: float = 0.5 - device: str = "cuda:0" + device: str = None exclude_layer_keywords: list[str] = field(default_factory=lambda: ["mlp.down_proj"]) # TODO: exclude_layer_keywords depends on the architecture and needs to be fixed diff --git a/onecomp/runner.py b/onecomp/runner.py index 2ffa41d8..60767146 100644 --- a/onecomp/runner.py +++ b/onecomp/runner.py @@ -261,9 +261,13 @@ def __init__( self.qep_config = None if qep: self.qep_config = qep_config if qep_config is not None else QEPConfig() + if self.qep_config.device is None and self.model_config is not None: + self.qep_config.device = str(self.model_config.get_device()) self.lpcd_config = None if lpcd: self.lpcd_config = lpcd_config if lpcd_config is not None else LPCDConfig() + if self.lpcd_config.device is None and self.model_config is not None: + self.lpcd_config.device = str(self.model_config.get_device()) self.report_progress = report_progress def check(self): diff --git a/tests/onecomp/lpcd/test_lpcd_config.py b/tests/onecomp/lpcd/test_lpcd_config.py index 1e99cf4c..dd21835d 100644 --- a/tests/onecomp/lpcd/test_lpcd_config.py +++ b/tests/onecomp/lpcd/test_lpcd_config.py @@ -38,10 +38,9 @@ def test_default_solver_params(self): assert cfg.gd_base_lr > 0.0 def test_default_device(self): - """Default device is a CUDA device string.""" + """Default device is None.""" cfg = LPCDConfig() - assert isinstance(cfg.device, str) - assert cfg.device.startswith("cuda") + assert cfg.device is None class TestLPCDConfigCustomValues: