(deepseek!)deepspeed中C++关联部分

您指出了一个重要点:DeepSpeed 的核心性能优化**确实依赖于 C++ 和 CUDA 代码**。虽然 Python 提供了用户友好的接口,但所有性能关键路径都是用 C++/CUDA 实现的。以下是 DeepSpeed 中关键 C++ 实现的详细位置和代码分析:


1. **核心 C++ 代码目录结构**

DeepSpeed 的 C++ 代码主要位于:

```

deepspeed/ops/csrc/

├── adam/ # 融合优化器内核

├── aio/ # 异步 I/O (ZeRO-Infinity)

├── cuda/ # CUDA 工具函数

├── inference/ # 推理优化

├── memory/ # 内存管理

├── nccl/ # NCCL 通信优化

├── quantization/ # 量化内核

├── sparse/ # 稀疏计算

├── transformer/ # Transformer 内核

└── utils/ # 工具函数

```


2. **关键性能优化点的 C++ 实现**

(1) **融合优化器内核 (Fused Adam)**

**文件**: `deepspeed/ops/csrc/adam/custom_fused_adam.cpp`

**实现**:

```cpp

void fused_adam(

at::Tensor& params, // 参数张量

at::Tensor& grads, // 梯度张量

at::Tensor& exp_avg, // 一阶动量

at::Tensor& exp_avg_sq, // 二阶动量

float lr, // 学习率

float beta1, // 一阶动量衰减率

float beta2, // 二阶动量衰减率

float eps, // 数值稳定项

float weight_decay, // 权重衰减

bool amsgrad) // 是否使用 AMSGrad 变体

{

// 启动 CUDA 内核

fused_adam_kernel<<<blocks, threads>>>(

params.data_ptr<float>(),

grads.data_ptr<float>(),

exp_avg.data_ptr<float>(),

exp_avg_sq.data_ptr<float>(),

lr, beta1, beta2, eps, weight_decay, amsgrad

);

}

```

**优化点**:将参数更新、动量计算、权重衰减等操作融合为单个 CUDA 内核,减少内存访问次数。


(2) **异步 I/O (ZeRO-Infinity Offload)**

**文件**: `deepspeed/ops/csrc/aio/py_lib.cc`

**核心实现**:

```cpp

// 异步读取参数分片

void deepspeed_aio_read(

torch::Tensor& buffer, // 目标缓冲区 (GPU 内存)

const std::string& filename, // 参数文件路径

int64_t num_bytes, // 读取字节数

bool validate) // 是否校验

{

// 提交异步读请求

auto req = aio_context->submit_read(

filename,

buffer.data_ptr(),

num_bytes

);

// 注册回调处理完成事件

req->set_callback([&](void* param) {

// 将数据异步拷贝到 GPU

cudaMemcpyAsync(..., cudaMemcpyHostToDevice);

});

}

```


(3) **内存碎片整理**

**文件**: `deepspeed/ops/csrc/memory/memory_ops.cpp`

**核心算法**:

```cpp

void defragment_memory(

void** pointers, // 需要整理的指针数组

size_t* sizes, // 每个指针的大小

int num_tensors, // 张量数量

cudaStream_t stream) // 执行流

{

// 1. 计算最优内存布局

auto layout = compute_optimal_layout(pointers, sizes, num_tensors);

// 2. 创建临时缓冲区

void* temp_buffer = cudaMalloc(total_size);

// 3. 异步拷贝到新布局

for (int i = 0; i < num_tensors; ++i) {

cudaMemcpyAsync(

layout.new_addresses[i],

pointers[i],

sizes[i],

cudaMemcpyDeviceToDevice,

stream

);

}

// 4. 更新指针地址

update_ptrs(pointers, layout.new_addresses);

}

```


(4) **通信原语优化**

**文件**: `deepspeed/ops/csrc/nccl/nccl_frontend.cpp`

**AllReduce 优化**:

```cpp

void coalesced_allreduce(

std::vector<at::Tensor>& tensors, // 需要聚合的张量列表

ncclComm_t comm, // NCCL 通信器

cudaStream_t stream) // CUDA 流

{

// 1. 合并小张量

auto coalesced = _coalesce_tensors(tensors);

// 2. 执行单次大张量通信

NCCL_CHECK(ncclAllReduce(

coalesced.data_ptr(),

coalesced.data_ptr(),

coalesced.numel(),

ncclFloat,

ncclSum,

comm,

stream

));

// 3. 等待完成并解包

cudaStreamSynchronize(stream);

_uncoalesce_tensors(coalesced, tensors);

}

```


3. **Python 到 C++ 的调用路径**

以 ZeRO 优化器为例:

```python

Python 层 (deepspeed/runtime/zero/stage2.py)

class DeepSpeedZeroOptimizer:

def step(self):

调用 C++ 融合内核

self.fused_adam_step()

```

↓ 通过 pybind11 绑定

```cpp

// C++ 绑定 (deepspeed/ops/csrc/adam/adam_binding.cpp)

PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) {

m.def("fused_adam", &fused_adam, "Fused Adam optimizer");

}

```

↓ 实际 CUDA 内核

```cpp

// CUDA 内核 (deepspeed/ops/csrc/adam/custom_fused_adam_kernel.cu)

global void fused_adam_kernel(

float* params, float* grads, ...)

{

// 每个线程处理一个参数

const int idx = blockIdx.x * blockDim.x + threadIdx.x;

// 1. 更新一阶动量

exp_avg[idx] = beta1 * exp_avg[idx] + (1 - beta1) * grads[idx];

// 2. 更新二阶动量

exp_avg_sq[idx] = beta2 * exp_avg_sq[idx] + (1 - beta2) * grads[idx] * grads[idx];

// 3. 计算参数更新

float denom = sqrtf(exp_avg_sq[idx]) + eps;

float step = lr * exp_avg[idx] / denom;

// 4. 应用权重衰减

step += weight_decay * params[idx];

// 5. 更新参数

params[idx] -= step;

}

```


4. **性能关键设计**

  1. **零拷贝设计**:

```cpp

// 直接操作 PyTorch 张量内存 (utils.h)

template <typename T>

T* get_ptr(at::Tensor& tensor) {

return tensor.data_ptr<T>(); // 无额外拷贝

}

```

  1. **流并行化**:

```cpp

// 同时使用多个 CUDA 流

cudaStream_t compute_stream;

cudaStream_t comm_stream;

cudaEvent_t comm_event;

// 计算与通信重叠

launch_compute_kernel(compute_stream);

ncclAllReduce(..., comm_stream);

cudaEventRecord(comm_event, comm_stream);

cudaStreamWaitEvent(compute_stream, comm_event); // 同步点

```

  1. **内存访问优化**:

```cpp

// 合并内存访问 (coalesced_access.cuh)

device float4 load_coalesced(float* addr) {

return *reinterpret_cast<float4*>(addr); // 128位宽加载

}

```


5. **编译构建系统**

DeepSpeed 使用混合构建系统:

```mermaid

graph TD

A[Python setup.py] --> B[Cmake]

B --> C[Ninja 构建]

C --> D[编译 CUDA 内核]

D --> E[生成 pybind11 模块]

E --> F[Python 可导入扩展]

```

关键编译指令(`deepspeed/ops/op_builder/fused_adam.py`):

```python

class FusedAdamBuilder(OpBuilder):

def sources(self):

return [

'csrc/adam/custom_fused_adam.cpp', # C++ 入口

'csrc/adam/custom_fused_adam_kernel.cu' # CUDA 内核

]

def extra_ldflags(self):

return ['-lnccl'] # 链接 NCCL 库

```


总结:DeepSpeed 的性能来源

  1. **C++/CUDA 核心**:所有性能关键路径用 C++ 实现

  2. **内核融合**:将多个操作合并为单个 CUDA 内核

  3. **零拷贝架构**:直接操作 PyTorch 内存,避免数据移动

  4. **异步流水线**:计算/通信/I/O 三重重叠

  5. **内存优化**:定制化碎片整理和访问模式

  6. **硬件原语**:直接调用 NCCL/CUBLAS 底层 API

> **关键对比**:

> - PyTorch DDP:主要用 Python 实现,依赖纯 NCCL 调用

> - DeepSpeed:深度定制 C++/CUDA 内核,实现系统级优化

> 这正是 DeepSpeed 能在超大规模模型上超越 DDP 2-5 倍性能的根本原因。

相关推荐
珑墨33 分钟前
【唯一随机数】如何用JavaScript的Set生成唯一的随机数?
开发语言·前端·javascript·ecmascript
周杰伦fans43 分钟前
C# - Task 是什么?想象一下你在餐厅点餐
服务器·开发语言·c#
芳草萋萋鹦鹉洲哦1 小时前
【tauri+rust】App会加载白屏,有时显示在左上角显示一小块,如何优化
开发语言·后端·rust
前端世界1 小时前
float 还是 double?用储罐体积计算带你看懂 C 语言浮点数的真实世界坑
java·c语言·开发语言
豐儀麟阁贵1 小时前
8.5在方法中抛出异常
java·开发语言·前端·算法
Bro_cat1 小时前
Java基础
java·开发语言·面试
滨HI01 小时前
C++ opencv简化轮廓
开发语言·c++·opencv
小青龙emmm1 小时前
2025级C语言第二次周测(国教专用)题解
c语言·开发语言·算法
学习路上_write2 小时前
FREERTOS_互斥量_创建和使用
c语言·开发语言·c++·stm32·单片机·嵌入式硬件
一起养小猫2 小时前
《Java数据结构与算法》第三篇(下)队列全解析:从基础概念到高级应用
java·开发语言·数据结构