Skip to content

Commit df89640

Browse files
committed
feat: add mps support
1 parent 591bcb2 commit df89640

14 files changed

Lines changed: 152 additions & 74 deletions

File tree

config/__base__/config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ seed: 42
2727

2828
# Device Params
2929
gpu:
30+
device: "cuda"
3031
use: 0
3132
multi: false
3233
use_cudnn: true
@@ -35,7 +36,6 @@ gpu:
3536
fsdp:
3637
min_num_params: 100000000
3738
use_cpu_offload: false
38-
use_cpu: false
3939

4040
# AutoMixedPrecision
4141
use_amp: false

script/edit_configs.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ def main() -> None:
88
parser = argparse.ArgumentParser(description="Edit Config")
99
parser.add_argument("config_path_or_dir", type=str, help="Path to the config file or dir")
1010
parser.add_argument(
11-
"override", type=str, help="Override the config file ex: batch=2,use_cpu=True"
11+
"override", type=str, help="Override the config file ex: batch=2,gpu.device=cpu"
1212
)
1313
args = parser.parse_args()
1414

script/show_model.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,19 @@
77
build_batched_transform,
88
build_transforms,
99
)
10+
from src.utils import setup_device
1011

1112

1213
@ConfigManager.argparse
1314
def main(cfg: ExperimentConfig) -> None:
1415
cfg.model.checkpoint = None
1516

16-
if cfg.use_cpu or not torch.cuda.is_available():
17-
device = torch.device("cpu")
18-
else:
19-
device = torch.device("cuda:0")
17+
device = setup_device(
18+
device_type=cfg.gpu.device,
19+
device_index=cfg.gpu.use,
20+
use_cudnn=cfg.gpu.use_cudnn,
21+
verbose=False,
22+
)
2023

2124
model = build_model(cfg.model, phase="train")
2225
model = model.to(device)

script/show_transform.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
def main(cfg: ExperimentConfig) -> None:
2222
phase = cfg.get("phase", "train")
2323
print(f"Phase: {phase}")
24-
cfg.use_cpu = True
24+
cfg.gpu.device = "cpu"
2525

2626
cfg_dataset = cfg.dataset.get(phase)
2727
transform = build_transforms(cfg_dataset.transforms)

src/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
build_dataloader,
2929
build_dataset,
3030
build_sampler,
31+
is_ram_cache_supported,
32+
validate_ram_cache_config,
3133
)
3234

3335
# Evaluation
@@ -104,7 +106,7 @@
104106
save_model,
105107
save_model_info,
106108
save_optimizer,
107-
set_device,
109+
setup_device,
108110
time_synchronized,
109111
worker_init_fn,
110112
)

src/config/config.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -187,14 +187,16 @@ class GPUConfig:
187187
"""Configuration for GPU usage and distributed training.
188188
189189
Attributes:
190-
use: GPU device(s) to use (string or int).
190+
device: Device type to use ("cuda", "mps", "cpu").
191+
use: GPU device(s) to use (string or int). Can be "mps" for MPS.
191192
multi: Whether to use multiple GPUs.
192193
use_cudnn: Whether to use cuDNN backend.
193194
use_tf32: Whether to use TensorFloat-32 format.
194195
multi_strategy: Strategy for multi-GPU training (dp, ddp, fsdp).
195196
fsdp: Configuration for FSDP when using fsdp strategy.
196197
"""
197198

199+
device: str = "cuda"
198200
use: str | int = 0
199201
multi: bool = False
200202
use_cudnn: bool = True
@@ -265,7 +267,6 @@ class ExperimentConfig:
265267
ram_cache_size_gb: Size of RAM cache in GB.
266268
seed: Random seed for reproducibility.
267269
gpu: GPU and distributed training configuration.
268-
use_cpu: Whether to force CPU usage.
269270
use_amp: Whether to use Automatic Mixed Precision.
270271
amp_dtype: Data type for AMP (fp16 or bf16).
271272
amp_init_scale: Initial scale for AMP gradient scaler.
@@ -311,7 +312,6 @@ class ExperimentConfig:
311312

312313
# device config
313314
gpu: GPUConfig = field(default_factory=GPUConfig)
314-
use_cpu: bool = False
315315

316316
# AutoMixedPrecision
317317
use_amp: bool = False

src/dataloaders/__init__.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,14 @@
22

33
from ..utils import import_submodules
44
from .base import BaseDataset
5-
from .build import DATASET_REGISTRY, build_dataloader, build_dataset, build_sampler
5+
from .build import (
6+
DATASET_REGISTRY,
7+
build_dataloader,
8+
build_dataset,
9+
build_sampler,
10+
is_ram_cache_supported,
11+
validate_ram_cache_config,
12+
)
613
from .tensor_cache import TensorCache
714
from .types import DatasetOutput
815

src/dataloaders/build.py

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import platform
2+
13
import torch
24
from loguru import logger
35
from torch.utils.data import BatchSampler, DataLoader, Dataset
@@ -18,6 +20,35 @@
1820
"""Registry for dataset classes."""
1921

2022

23+
def is_ram_cache_supported() -> bool:
24+
"""Check if RAM cache is supported on the current platform.
25+
26+
Returns:
27+
bool: True if RAM cache is supported (Linux only), False otherwise.
28+
"""
29+
return platform.system() == "Linux"
30+
31+
32+
def validate_ram_cache_config(use_ram_cache: bool, verbose: bool = True) -> bool:
33+
"""Validate RAM cache configuration for current platform.
34+
35+
Args:
36+
use_ram_cache: Whether RAM cache is requested.
37+
verbose: Whether to log warnings.
38+
39+
Returns:
40+
bool: True if RAM cache can be used, False otherwise.
41+
"""
42+
if use_ram_cache and not is_ram_cache_supported():
43+
if verbose:
44+
logger.warning(
45+
f"RAM cache is only supported on Linux. Current OS: {platform.system()}. "
46+
"Disabling RAM cache."
47+
)
48+
return False
49+
return use_ram_cache
50+
51+
2152
def build_dataset(
2253
cfg: DatasetConfig,
2354
transforms: Compose | None,
@@ -37,11 +68,14 @@ def build_dataset(
3768
3869
Raises:
3970
AssertionError: If RAM cache size exceeds available shared memory.
71+
RuntimeError: If RAM cache is requested on non-Linux systems.
4072
"""
41-
if use_ram_cache:
42-
assert ram_cache_size_gb <= get_free_shm_size() / BYTES_PER_GIB, (
43-
"RAM Cache size is too large"
44-
)
73+
# Validate RAM cache configuration
74+
use_ram_cache = validate_ram_cache_config(use_ram_cache)
75+
76+
if use_ram_cache and ram_cache_size_gb is not None:
77+
if ram_cache_size_gb > get_free_shm_size() / BYTES_PER_GIB:
78+
raise RuntimeError("RAM Cache size is too large")
4579
cache = TensorCache(size_limit_gb=ram_cache_size_gb)
4680
logger.info(f"Use RAM Cache: {ram_cache_size_gb}GB")
4781
else:

src/utils/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
save_model,
1919
save_model_info,
2020
save_optimizer,
21-
set_device,
21+
setup_device,
2222
time_synchronized,
2323
worker_init_fn,
2424
)

src/utils/registry.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,10 @@ def _do_register(self, name: str, obj: object) -> None:
5252
Raises:
5353
AssertionError: If an object with the same name is already registered.
5454
"""
55-
assert name not in self._obj_map, (
56-
f"An object named '{name}' was already registered in '{self._name}' registry!"
57-
)
55+
if name in self._obj_map:
56+
raise RuntimeError(
57+
f"An object named '{name}' was already registered in '{self._name}' registry!"
58+
)
5859
self._obj_map[name] = obj
5960

6061
def register(self, obj: object | None = None, name: str | None = None) -> object | None:

0 commit comments

Comments
 (0)