Skip to content

Commit d680b86

Browse files
slurm cpu
1 parent bf11c2d commit d680b86

3 files changed

Lines changed: 103 additions & 3 deletions

File tree

cybench/runs/run_experiments.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,13 @@
2121
from cybench.datasets.dataset import PandasDataset
2222
from cybench.evaluation.eval import evaluate_predictions
2323
from cybench.evaluation.aggregated_metrics import compute_report_metrics, format_report_metrics
24-
from cybench.util.config_utils import adjust_model_cfg_to_dataset, set_seed, remove_search_keys
24+
from cybench.util.config_utils import (
25+
adjust_model_cfg_to_dataset,
26+
apply_force_cpu_to_frozen_model_cfg,
27+
remove_search_keys,
28+
set_seed,
29+
walk_forward_force_cpu,
30+
)
2531
from cybench.util.optuna_hyper_opt import OptunaOptimizer
2632
from cybench.util.store_and_cache import make_folder, save_preds, save_meta_dict
2733
from cybench.util.feature_selection import (
@@ -218,6 +224,14 @@ def main(cfg):
218224
fs_cfg: DictConfig | None = None
219225
if is_walk_forward:
220226
model_cfg = cast(DictConfig, OmegaConf.create(OmegaConf.to_container(frozen_model_cfg)))
227+
if walk_forward_force_cpu(cfg):
228+
prev_device = OmegaConf.select(model_cfg, "device")
229+
model_cfg = apply_force_cpu_to_frozen_model_cfg(model_cfg)
230+
if prev_device and prev_device != "cpu":
231+
log.info(
232+
"Walk-forward force CPU: frozen model device %s → cpu",
233+
prev_device,
234+
)
221235
fs_cfg = (
222236
cast(DictConfig, OmegaConf.create(OmegaConf.to_container(frozen_fs_cfg)))
223237
if frozen_fs_cfg is not None

cybench/util/config_utils.py

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,46 @@ def _clean(obj):
5252

5353
return cast(DictConfig, OmegaConf.create(_clean(cfg_dict)))
5454

55+
5556
def remove_search_keys(model_cfg: DictConfig) -> DictConfig:
5657
return remove_keys(model_cfg, key="_search_")
5758

5859

60+
def is_cybench_force_cpu() -> bool:
61+
"""True when Slurm submit_array.sh --cpu exported CYBENCH_FORCE_CPU=1."""
62+
val = os.environ.get("CYBENCH_FORCE_CPU", "").strip().lower()
63+
return val in ("1", "true", "yes", "on")
64+
65+
66+
def walk_forward_force_cpu(cfg: DictConfig) -> bool:
67+
"""Whether walk-forward should override device in frozen optimal_model.yaml."""
68+
if is_cybench_force_cpu():
69+
return True
70+
if OmegaConf.select(cfg, "model.device") == "cpu":
71+
return True
72+
return OmegaConf.select(cfg, "experiment.device") == "cpu"
73+
74+
75+
def apply_force_cpu_to_frozen_model_cfg(model_cfg: DictConfig) -> DictConfig:
76+
"""
77+
Override device fields baked into screening optimal_model.yaml for CPU runs.
78+
79+
Walk-forward loads the frozen config wholesale; without this, TabDPT and other
80+
GPU-screened models keep device=cuda even on the main partition.
81+
"""
82+
cfg_out = cast(DictConfig, OmegaConf.create(OmegaConf.to_container(model_cfg)))
83+
with open_dict(cfg_out):
84+
if "device" in cfg_out:
85+
cfg_out.device = "cpu"
86+
if "allow_cpu_fallback" in cfg_out:
87+
cfg_out.allow_cpu_fallback = True
88+
torch_model = cfg_out.get("torch_model")
89+
if torch_model is not None and "device" in torch_model:
90+
with open_dict(torch_model):
91+
torch_model.device = "cpu"
92+
return cfg_out
93+
94+
5995
def reload_config_with_overrides(
6096
config_dir: Path,
6197
config_name: str,
@@ -74,7 +110,6 @@ def reload_config_with_overrides(
74110
return cfg
75111

76112

77-
78113
def get_run_description(overrides_path: pathlib.Path) -> str:
79114
"""Loads and formats the list of Hydra overrides into a unique string."""
80115
try:

tests/util/test_config_utils.py

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,12 @@
88
from hydra import compose, initialize_config_dir
99
from omegaconf import OmegaConf
1010

11-
from cybench.util.config_utils import adjust_model_cfg_to_dataset
11+
from cybench.util.config_utils import (
12+
adjust_model_cfg_to_dataset,
13+
apply_force_cpu_to_frozen_model_cfg,
14+
is_cybench_force_cpu,
15+
walk_forward_force_cpu,
16+
)
1217

1318

1419
class _FakeTorchDataset:
@@ -45,3 +50,49 @@ def test_adjust_model_cfg_sets_missing_placeholder_dims():
4550
assert adjusted.torch_model.temporal_in_dim == 12
4651
assert adjusted.torch_model.context_in_dim == 5
4752
assert not OmegaConf.is_missing(adjusted.torch_model, "temporal_in_dim")
53+
54+
55+
def test_is_cybench_force_cpu(monkeypatch):
56+
monkeypatch.delenv("CYBENCH_FORCE_CPU", raising=False)
57+
assert is_cybench_force_cpu() is False
58+
monkeypatch.setenv("CYBENCH_FORCE_CPU", "1")
59+
assert is_cybench_force_cpu() is True
60+
monkeypatch.setenv("CYBENCH_FORCE_CPU", "yes")
61+
assert is_cybench_force_cpu() is True
62+
63+
64+
def test_walk_forward_force_cpu_from_hydra_overrides(monkeypatch):
65+
monkeypatch.delenv("CYBENCH_FORCE_CPU", raising=False)
66+
cfg = OmegaConf.create({"model": {"device": "cpu"}, "experiment": {"device": "cuda"}})
67+
assert walk_forward_force_cpu(cfg) is True
68+
cfg = OmegaConf.create({"model": {"device": "auto"}, "experiment": {"device": "cpu"}})
69+
assert walk_forward_force_cpu(cfg) is True
70+
cfg = OmegaConf.create({"model": {"device": "auto"}, "experiment": {"device": "cuda"}})
71+
assert walk_forward_force_cpu(cfg) is False
72+
73+
74+
def test_apply_force_cpu_to_frozen_model_cfg():
75+
frozen = OmegaConf.create(
76+
{
77+
"_target_": "cybench.models.tabular_foundation_model.TabDPTModel",
78+
"name": "tabdpt",
79+
"device": "cuda",
80+
"allow_cpu_fallback": False,
81+
}
82+
)
83+
out = apply_force_cpu_to_frozen_model_cfg(frozen)
84+
assert out.device == "cpu"
85+
assert out.allow_cpu_fallback is True
86+
87+
88+
def test_apply_force_cpu_to_frozen_torch_model_cfg():
89+
frozen = OmegaConf.create(
90+
{
91+
"framework": "torch",
92+
"device": "cuda",
93+
"torch_model": {"input_size": 6, "device": "cuda"},
94+
}
95+
)
96+
out = apply_force_cpu_to_frozen_model_cfg(frozen)
97+
assert out.device == "cpu"
98+
assert out.torch_model.device == "cpu"

0 commit comments

Comments
 (0)