☰
ColossalAI Accelerator 加速器抽象层:一套 `auto_set_accelerator()` API 跨 NVIDIA GPU / 华为 NPU / CPU 运行分布式训练
2026/10/16 23:33:41 网站建设 项目流程

ColossalAI Accelerator 加速器抽象层:一套auto_set_accelerator()API 跨 NVIDIA GPU / 华为 NPU / CPU 运行分布式训练

【免费下载链接】ColossalAIMaking large AI models cheaper, faster and more accessible项目地址: https://gitcode.com/GitHub_Trending/co/ColossalAI

本篇技术指南以 ColossalAI 的accelerator模块 为主体,深入讲解其作为硬件加速器抽象层(Accelerator Abstraction Layer)的设计动机、源码结构与三大内置后端实现。读完本文将掌握auto_set_accelerator()/set_accelerator()/get_accelerator()三件套 API 的用法与探测优先级,理解BaseAccelerator如何按 PyTorch 原生语义统合设备管理、随机数、显存、流/事件与混合精度接口,并能在自己需要移植大模型到不同硬件平台时,快速接入这一抽象层。

一、为什么 ColossalAI 需要一层"加速器抽象"

当前 AI 硬件生态高度碎片化:既有 NVIDIA GPU(CUDA),也有华为昇腾 NPU(CANN/torch_npu),还有纯 CPU 调试环境。若代码中到处硬编码torch.cuda.*,一旦要迁移到昇腾等平台,就得大面积修改训练与推理代码,维护成本极高。

ColossalAI 的做法是在colossalai/accelerator/目录下提供一层统一的抽象:用户代码只面向抽象接口书写,底层实际调用哪个后端的实现由模块在运行时决定。正如模块 README 所描述,其核心目标是"以极简单的auto_set_accelerator()API 让用户代码在不同硬件平台间可移植",可在 NVIDIA GPU、华为 NPU 等后端之间轻松切换。

该模块对外导出的全部符号见__init__.py,共包含三种内置加速器实现与三个全局管理函数:

导出的符号类型作用
BaseAccelerator抽象基类定义加速器统一接口契约
CudaAccelerator具体实现NVIDIA CUDA GPU 后端
NpuAccelerator具体实现华为昇腾 NPU 后端
CpuAccelerator具体实现CPU 后端(调试/无卡环境)
set_accelerator()全局管理 API显式指定当前进程使用的加速器
auto_set_accelerator()全局管理 API按可用性自动探测并设置加速器
get_accelerator()全局管理 API获取当前进程的加速器单例

二、三个全局 API:设置、自动探测与获取

核心逻辑集中在colossalai/accelerator/api.py,模块内部通过进程级全局变量_ACCELERATOR保存当前加速器实例。

2.1 加速器注册表与探测优先级

关键代码是使用OrderedDict维护的映射表(见 api.py):

# we use ordered dictionary here to associate the # order with device check priority # i.e. auto_set_accelerator will check cuda first _ACCELERATOR_MAPPING = OrderedDict(cuda=CudaAccelerator, npu=NpuAccelerator, cpu=CpuAccelerator)

这里的注释揭示了设计要点:字典的插入顺序即设备检测优先级。auto_set_accelerator()会先探测 CUDA,再探测 NPU,最后回落到 CPU,从而保证在同时具备多类硬件的机器上优先选择算力更强的后端。

2.2auto_set_accelerator():自动探测逻辑

auto_set_accelerator()的实现(见 api.py)逐类实例化并调用后端的is_available():

def auto_set_accelerator() -> None: global _ACCELERATOR for accelerator_name, accelerator_cls in _ACCELERATOR_MAPPING.items(): try: accelerator = accelerator_cls() if accelerator_name == "cpu" or accelerator.is_available(): _ACCELERATOR = accelerator break except: pass if _ACCELERATOR is None: raise RuntimeError("No accelerator is available.")

两点值得注意:

  • CPU 是兜底:CpuAccelerator.is_available()恒返回True(见 cpu_accelerator.py),因此只要前两类都不满足条件,最终一定能选中 CPU,保证在无 GPU/NPU 的环境中代码也能跑起来。
  • 兜底失败会报错:若循环结束后_ACCELERATOR仍为空(例如映射表被自定义逻辑改空),直接抛出RuntimeError("No accelerator is available.")。

2.3set_accelerator():显式指定后端

set_accelerator()(见 api.py)支持两种入参,比字符串更安全的是直接传后端实例:

def set_accelerator(accelerator: Union[str, BaseAccelerator]) -> None: global _ACCELERATOR if isinstance(accelerator, str): _ACCELERATOR = _ACCELERATOR_MAPPING[accelerator]() elif isinstance(accelerator, BaseAccelerator): _ACCELERATOR = accelerator else: raise TypeError("accelerator must be either a string or an instance of BaseAccelerator")
  • 传入字符串时,以该字符串为 key 从_ACCELERATOR_MAPPING取类并实例化;
  • 传入BaseAccelerator子类实例时直接采纳,便于注入自定义实现;
  • 其他类型抛出TypeError。

2.4get_accelerator():惰性单例获取

全仓库范围内,业务代码并不需要关心加速器是如何被初始化的,统一通过get_accelerator()拿到实例(见 api.py)。若此前未初始化,它会自动调用auto_set_accelerator()完成探测:

def get_accelerator() -> BaseAccelerator: global _ACCELERATOR if _ACCELERATOR is None: auto_set_accelerator() return _ACCELERATOR

三、BaseAccelerator:按 PyTorch 原生语义划分的五类抽象接口

BaseAccelerator是全部后端的抽象基类(base_accelerator.py),继承自abc.ABC,通过@abstractmethod强制每个后端实现完整接口。它在设计上有意让API 命名与 PyTorch 原生 API 对齐,例如current_device()、synchronize()、manual_seed()、empty_cache()、Stream()、Event()、autocast()等,用户只需把torch.cuda.xxx换成get_accelerator().xxx即可完成适配。

3.1 不可变属性:后端的"身份证"

基类构造时接收三个参数并对外暴露为只读属性(见 base_accelerator.py),同时实现了__repr__便于调试输出:

属性含义各后端取值
name加速器名称cuda/npu/cpu
communication_backend对应的分布式通信库nccl/hccl/gloo
is_synchronous是否为同步设备三者当前均为False

另外基类定义了类属性support_set_device: bool = True,用于标示该设备是否支持"进程绑定设备"操作,CPU 后端会将其覆写为False(见 cpu_accelerator.py)。

3.2 五类抽象接口

基类把加速器能力抽象为五组接口,每一组都能在 PyTorch 原生 API 中找到一一对应:

1) 设备管理 API(Device APIs)get_version()、get_current_device()、current_device()、set_device()、get_device_name()、synchronize()、is_available()、device_count()、get_device_capability()、get_device_properties()、utilization(),外加一个非抽象工具方法set_to_device()(见 base_accelerator.py),它支持把单个模型或模型列表统一搬到当前设备:

def set_to_device(self, models: Any) -> Any: if isinstance(models, list) and len(models) > 1: ret = [] for model in models: ret.append(model.to(self.get_current_device())) return ret elif isinstance(models, list): return models[0].to(self.get_current_device()) else: return models.to(self.get_current_device())

2) 随机数发生器 API(Random Number Generator APIs)get_rng_state()/get_rng_state_all()、set_rng_state()/set_rng_state_all()、manual_seed()/manual_seed_all()、seed()/seed_all()、initial_seed()。这些接口保证了跨后端做分布式训练时随机性可复现、各进程随机状态可同步。

3) 内存管理 API(Memory Management APIs)empty_cache()、memory_stats()、memory_summary()、memory_snapshot()、memory_allocated()、max_memory_allocated()、reset_max_memory_allocated()、memory_reserved()、max_memory_reserved()、set_per_process_memory_fraction()、reset_peak_memory_stats()。这些是 Gemini、低比特 Zero 等显存优化策略做内存监控的数据来源。

4) 流与事件 API(Streams and Events APIs)Stream()、Event()、current_stream()、default_stream()、set_stream()、stream(),用于内核并行调度与异步执行。

5) 混合精度 API(AMP APIs)autocast(enabled=True, dtype=torch.float16, cache_enabled=True)(见 base_accelerator.py),返回当前设备上的自动混精度上下文管理器。

四、三大内置后端实现对比

4.1CudaAccelerator:NVIDIA GPU 后端

cuda_accelerator.py的构造参数为name="cuda"、communication_backend="nccl"、is_synchronous=False(第 19 行)。所有方法都是对torch.cuda.*的直接转发:

  • get_version()返回torch.version.cuda,即当前 PyTorch 编译所基于的 CUDA 版本;
  • get_current_device()返回torch.device(f"cuda:{torch.cuda.current_device()}");
  • autocast()最终落到torch.amp.autocast(device_type="cuda", ...);
  • set_device()在未传入具体设备时有一个分布式约定:若dist已初始化,则用dist.get_rank() % self.device_count()推导本进程应绑定的卡号(见 cuda_accelerator.py),该逻辑与 NPU 后端完全一致。

4.2NpuAccelerator:华为昇腾 NPU 后端

npu_accelerator.py的构造参数为name="npu"、communication_backend="hccl"。它在上层做了可选依赖保护——文件开头try: import torch_npu except ImportError: pass(第 10-13 行),即只有安装torch_npu的环境中相关 API 才会真正可用。

NPU 后端的实现几乎与 CUDA 后端一一镜像,只是把命名空间换成torch.npu.*,并新增两类差异:

  • 设备字符串为npu:{index},版本号取自torch.version.cann(CANN 版本);
  • autocast()对应昇腾实现torch.npu.amp.autocast(enabled=..., dtype=..., cache_enabled=...)。

注意:NpuAccelerator一旦被实例化即可能触发对torch_npu的访问,因此该后端应与torch_npu环境配套使用。

4.3CpuAccelerator:CPU 兜底后端

cpu_accelerator.py与前两者风格不同,它把support_set_device覆写为False,并且对设备强相关的操作统一抛出RuntimeError(如current_device()、set_device()、synchronize()、device_count()、各类显存统计与 Stream/Event)。可以推断,CPU 后端主要用于无卡环境下的代码调试与纯数据流水线测试,而不是模拟真正的设备行为。

它真正实现的能力包括:

  • is_available()恒为True(兜底语义);
  • RNG 部分退化为torch.get_rng_state()/torch.set_rng_state()的 CPU 语义;
  • 内存统计被映射为主机内存:memory_reserved()返回psutil.Process().memory_info().rss,max_memory_reserved()返回resource.getrusage(...).ru_maxrss;
  • set_per_process_memory_fraction()通过resource.setrlimit(resource.RLIMIT_AS, ...)限制进程地址空间(见 cpu_accelerator.py);
  • autocast()返回nullcontext(空上下文管理器),即 CPU 上不做任何自动精度转换。

下表汇总三个内置后端的核心差异:

维度CudaAcceleratorNpuAcceleratorCpuAccelerator
namecudanpucpu
通信后端ncclhcclgloo
底层命名空间torch.cudatorch.npu(需torch_npu)主机资源(psutil/resource)
is_available()torch.cuda.is_available()torch.npu.is_available()恒True
set_device()支持,可据 rank 推导支持,可据 rank 推导抛RuntimeError
autocast()torch.amp.autocast("cuda", ...)torch.npu.amp.autocast(...)nullcontext
support_set_deviceTrueTrueFalse

五、抽象层在 ColossalAI 各模块中的落地证据

这套抽象并非"纸面设计",而是贯穿于 ColossalAI 训练、零冗余优化、混合精度与推理等核心链路。仓库内大量模块统一通过from colossalai.accelerator import get_accelerator获取设备能力,例如:

  • Gemini/Chunk 显存管理:在 chunk.py 中,Chunk 的device_type属性通过get_accelerator().name上报当前设备类型,供显存统计与调度策略判断张量驻留位置。
  • 低比特 Zero:在 low_level_optim.py 中直接断言get_accelerator().name in ["cuda", "npu"],从源码结构看,该模块的算子实现目前仅覆盖 CUDA 与 NPU 两类后端。
  • Booster 插件:gemini_plugin.py 会在get_accelerator().name == "npu"时走昇腾专属的初始化分支;而 Chunk 的chunk_init_device默认值直接取自get_accelerator().get_current_device()。类似模式同样出现在 hybrid_parallel_plugin.py 中。
  • AMP 梯度缩放:naive AMP 的梯度缩放器 base_grad_scaler.py 与 dynamic_grad_scaler.py 均依赖加速器抽象完成设备同步。
  • Kernel 适配与 JIT:kernel/jit/option.py 在选项探测阶段通过get_accelerator().get_current_device()把输入张量放到正确设备上做基准测试;这印证了 README 中"kernel 模块会自动匹配加速器与其对应内核实现"的模块解耦思路。

可以看到,同一份高层代码(如 Gemini、梯度缩放)在换用不同set_accelerator后,就可在不同硬件上获得对应语义,这正是抽象层价值的直接体现。

六、与 DeepSpeed accelerator 的关系及两处本地化改进

README 明确说明本模块的接口设计"深受 DeepSpeed accelerator 启发",并致谢 DeepSpeed 团队;ColossalAI 的实现在此基础上从零编写,并做了两点针对性改造:

  1. API 命名与 PyTorch 原生 API 对齐:相比 DeepSpeed 自有的抽象命名,ColossalAI 的接口(set_device、synchronize、manual_seed、Stream、Event、autocast等)让熟悉 PyTorch 的开发者几乎零成本迁移,也降低了各后端实现之间的心智负担。
  2. 不在 accelerator 中内嵌 op builder:DeepSpeed 将算子构建器一并收敛进 accelerator;ColossalAI 则将其从 accelerator 中剥离,独立维护kernel模块(colossalai/kernel),由内核模块按当前加速器自动选择对应的 CUDA/Triton 扩展实现,使各模块职责更清晰、耦合更低。

七、如何在代码中使用这套抽象

7.1 最小使用范式

在训练脚本入口处(通常在initialize前后),让 ColossalAI 自动完成后端选择:

from colossalai.accelerator import auto_set_accelerator, get_accelerator auto_set_accelerator() # 自动探测:cuda -> npu -> cpu acc = get_accelerator() # 之后全代码共享同一个加速器实例 print(acc) # 例如 CudaAccelerator(name=cuda, communication_backend=nccl, is_synchronous=False) print(acc.name) # 'cuda' / 'npu' / 'cpu'

7.2 与既有分布式初始化的配合

ColossalAI 的分布式启动通常经由colossalai.launch/colossalai.initialize完成,其中会按上述探测流程设置好全局加速器。若需手动指定,可显式调用set_accelerator("cuda")或set_accelerator("npu");在分布式已初始化且未指定具体设备时,CUDA/NPU 后端的set_device()会按local_rank = dist.get_rank() % device_count自动绑定设备。

7.3 典型迁移写法对比

PyTorch 硬编码写法跨平台写法(推荐)
torch.cuda.set_device(rank)get_accelerator().set_device(rank)
torch.device("cuda")get_accelerator().get_current_device()
torch.cuda.is_available()get_accelerator().is_available()
torch.cuda.manual_seed_all(seed)get_accelerator().manual_seed_all(seed)
torch.cuda.empty_cache()get_accelerator().empty_cache()
torch.cuda.amp.autocast()get_accelerator().autocast()

八、如何为新的硬件后端做扩展

从源码结构可以推断,要接入一个新后端(例如 XPU、TPU 或自研加速器),只需完成四步:

  1. 继承抽象基类:新建xxx_accelerator.py,实现BaseAccelerator中全部@abstractmethod方法,覆盖设备、RNG、内存、流/事件、AMP 五组接口;对不适用的能力直接抛RuntimeError(可参考CpuAccelerator的写法)。
  2. 补齐可选依赖:仿照NpuAccelerator对torch_npu的处理,用try: import xxx except ImportError: pass声明新硬件的 Python 绑定。
  3. 注册到映射表:将新类按"探测优先级从高到低"插入 api.py 的_ACCELERATOR_MAPPING,使auto_set_accelerator()与字符串形式的set_accelerator()均可识别。
  4. 在对外__init__.py中导出:参照init.py 补全__all__。

九、使用与扩展时的注意事项

  • CPU 后端的语义限定:CpuAccelerator并非"模拟 GPU",其set_device、Stream、Event、显存分配统计等一律抛RuntimeError。若希望跑通真正的前向/反向训练,仍应依赖 CUDA/NPU 后端或纯 PyTorch CPU 逻辑。
  • NPU 后端依赖昇腾软件栈:使用前需确认环境已安装torch_npu且 CANN 版本与 PyTorch 匹配,否则导入相关路径会在调用时失败。
  • 分布式后端与硬件要对应:name与communication_backend(nccl/hccl/gloo)是绑定的,在异构集群中启动分布式训练时应保证进程组后端与所选加速器匹配,例如 NPU 场景使用 HCCL 而非 NCCL。
  • 第三方后端需先自测:接入新加速器时,建议先用get_accelerator()的__repr__输出与is_available()做冒烟验证,再接入 Gemini、Low-Level Zero 等对设备类型有显式断言(如assert name in ["cuda", "npu"])的模块。

总而言之,ColossalAI 的accelerator模块把"设备能力"收敛为一份与 PyTorch 对齐的统一契约,让上层大规模训练、优化与推理代码可以做到硬件无关,是理解 ColossalAI 多硬件兼容性设计的核心入口。

【免费下载链接】ColossalAIMaking large AI models cheaper, faster and more accessible项目地址: https://gitcode.com/GitHub_Trending/co/ColossalAI

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询