Skip to content

Commit 2d5b2b6

Browse files
FightingZhennoemotiovon
authored andcommitted
feat: add initial support for Ascend devices with unified device abstraction
This commit introduces native support for Ascend NPUs in the ROLL project, while preserving compatibility with existing CUDA-based infrastructure. Key changes include: - Introduced a unified device abstraction interface to encapsulate device initialization, memory management, and synchronization, enabling extensibility for both CUDA and Ascend devices. - Replaced direct usage of and Ray CUDA resource APIs with the new abstraction layer to support multi-device environments. - Integrated Ascend inference backend via vLLM + vLLM-ascend. - Added experimental support for training with MindSpeed on Ascend hardware. This enhancement lays the groundwork for seamless switching across CUDA and Ascend devices. Signed-off-by: noemotiovon <757486878@qq.com> # Conflicts: # roll/distributed/executor/cluster.py # roll/distributed/executor/worker.py # roll/distributed/scheduler/initialize.py
1 parent bf06136 commit 2d5b2b6

4 files changed

Lines changed: 69 additions & 14 deletions

File tree

roll/distributed/executor/cluster.py

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
collect_all_to_all,
1818
dispatch_one_to_all,
1919
)
20+
from roll.platforms import current_platform
2021
from roll.utils.constants import RAY_NAMESPACE
2122
from roll.distributed.scheduler.resource_manager import ResourceManager
2223
from roll.utils.import_utils import safe_import_class
@@ -114,22 +115,32 @@ def _create_workers(self):
114115
env_vars["MASTER_PORT"] = str(self.master_port)
115116
if deploy_pg["gpu_rank"] is not None:
116117
RayUtils.update_env_vars_for_visible_devices(
117-
env_vars=env_vars,
118+
env_vars=env_vars,
118119
gpu_ranks=pg_zero_gpu_ranks)
119120
if "ROLL_LOG_DIR" in os.environ:
120121
env_vars["ROLL_LOG_DIR"] = os.environ["ROLL_LOG_DIR"]
121122
env_vars.update(self.worker_config.system_envs)
122123

123124
runtime_env = RuntimeEnv(env_vars=env_vars)
124125
self.worker_config.resource_placement_groups = pgs
125-
worker = self.worker_cls.options(
126-
scheduling_strategy=PlacementGroupSchedulingStrategy(placement_group=deploy_pg["placement_group"]),
127-
name=worker_name,
128-
namespace=RAY_NAMESPACE,
129-
runtime_env=runtime_env,
130-
num_cpus=0.01,
131-
num_gpus=0.01 if self.worker_config.device_mapping else 0,
132-
).remote(worker_config=self.worker_config)
126+
127+
worker_options = {
128+
"scheduling_strategy": PlacementGroupSchedulingStrategy(placement_group=deploy_pg["placement_group"]),
129+
"name": worker_name,
130+
"namespace": RAY_NAMESPACE,
131+
"runtime_env": runtime_env,
132+
"num_cpus": 0.01,
133+
}
134+
135+
if current_platform.ray_device_key == "GPU":
136+
worker_options.update({"num_gpus": 0.01 if self.worker_config.device_mapping else 0})
137+
elif current_platform.ray_device_key == "NPU":
138+
worker_options.update({
139+
"num_cpus": 0,
140+
"resources": {current_platform.ray_device_key: 0.01 if self.worker_config.device_mapping else 0},
141+
})
142+
143+
worker = self.worker_cls.options(**worker_options).remote(worker_config=self.worker_config)
133144
self.workers.append(worker)
134145
if rank == 0:
135146
self.master_addr, self.master_port = ray.get(worker.get_master_addr_and_port.remote())

roll/distributed/executor/worker.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from roll.utils.offload_states import OffloadStateType
1919
from roll.platforms import current_platform
2020
from roll.utils.ray_utils import RayUtils
21+
from roll.platforms import current_platform
2122

2223

2324
@dataclass

roll/utils/gpu_utils.py

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,51 @@
11
import torch
22
from enum import Enum
33

4+
5+
def is_torch_npu_available() -> bool:
6+
"""Check the availability of NPU"""
7+
try:
8+
import torch_npu # noqa: F401
9+
10+
return torch.npu.is_available()
11+
except ImportError:
12+
return False
13+
14+
15+
is_cuda_available = torch.cuda.is_available()
16+
is_npu_available = is_torch_npu_available()
17+
18+
19+
def get_device_name() -> str:
20+
"""Get device type name"""
21+
if is_cuda_available:
22+
return torch.cuda.get_device_name().upper()
23+
elif is_npu_available:
24+
return torch.npu.get_device_name().upper()
25+
else:
26+
raise RuntimeError("Can not find device type.")
27+
28+
429
class DeviceType(Enum):
530
NONE = "NONE"
631
NVIDIA = "NVIDIA"
732
AMD = "AMD"
33+
ASCEND = "ASCEND"
834
UNKNOWN = "UNKNOWN"
935

36+
1037
class GPUUtils:
1138
@staticmethod
1239
def get_device_type() -> DeviceType:
13-
if not torch.cuda.is_available():
40+
if not is_cuda_available and not is_npu_available:
1441
return DeviceType.NONE
15-
device_name = torch.cuda.get_device_name().upper()
42+
43+
device_name = get_device_name()
1644
if "NVIDIA" in device_name:
1745
return DeviceType.NVIDIA
18-
if "AMD" in device_name:
46+
elif "AMD" in device_name:
1947
return DeviceType.AMD
48+
elif "ASCEND" in device_name:
49+
return DeviceType.ASCEND
50+
2051
return DeviceType.UNKNOWN
21-

roll/utils/ray_utils.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,12 @@ def get_custom_env_env_vars(
4141
"TORCHINDUCTOR_COMPILE_THREADS": "2",
4242
"PYTORCH_HIP_ALLOC_CONF": "expandable_segments:True",
4343
}
44+
elif DeviceType.ASCEND == device_type:
45+
env_vars = {
46+
"TORCHINDUCTOR_COMPILE_THREADS": "2",
47+
"PYTORCH_NPU_ALLOC_CONF": "expandable_segments:True",
48+
"PYTHONPATH": os.environ.get("PYTHONPATH", ""),
49+
}
4450
elif DeviceType.UNKNOWN == device_type:
4551
env_vars = {
4652
"TORCHINDUCTOR_COMPILE_THREADS": "2",
@@ -63,6 +69,11 @@ def update_env_vars_for_visible_devices(
6369
"HIP_VISIBLE_DEVICES": ",".join(map(str, gpu_ranks)),
6470
"RAY_EXPERIMENTAL_NOSET_HIP_VISIBLE_DEVICES": "1",
6571
}
72+
elif DeviceType.ASCEND == device_type:
73+
visible_devices_env_vars = {
74+
"ASCEND_RT_VISIBLE_DEVICES": ",".join(map(str, gpu_ranks)),
75+
"RAY_EXPERIMENTAL_NOSET_ASCEND_RT_VISIBLE_DEVICES": "1",
76+
}
6677
else:
6778
visible_devices_env_vars = {
6879
"CUDA_VISIBLE_DEVICES": ",".join(map(str, gpu_ranks)),
@@ -77,6 +88,8 @@ def get_visible_gpus(device_type: DeviceType | None = None) -> list:
7788
device_type = GPUUtils.get_device_type()
7889
if DeviceType.AMD == device_type:
7990
return os.environ.get("HIP_VISIBLE_DEVICES", "").split(",")
80-
if DeviceType.NVIDIA == device_type or DeviceType.UNKNOWN == device_type:
91+
elif DeviceType.ASCEND == device_type:
92+
return os.environ.get("ASCEND_RT_VISIBLE_DEVICES", "").split(",")
93+
elif DeviceType.NVIDIA == device_type or DeviceType.UNKNOWN == device_type:
8194
return os.environ.get("CUDA_VISIBLE_DEVICES", "").split(",")
8295
return []

0 commit comments

Comments
 (0)