一、CUDA 是什么?为什么要学 CUDA?

1.1 基本定义

CUDA(Compute Unified Device Architecture)是 NVIDIA 推出的通用并行计算平台与编程模型,允许开发者使用类 C/C++ 语言调用 NVIDIA GPU 的并行计算核心,执行大规模并行任务。

1.2 核心优势

  • 超强并行能力:单 GPU 包含上千个计算核心,适合数据并行、计算密集型任务
  • 开发友好:基于 C/C++ 扩展,学习成本低,支持 C++17 等现代语法
  • 生态完善:深度适配 PyTorch/TensorFlow、cuDNN、NCCL、OpenCV 等库
  • 应用广泛:AI 训练 / 推理、视频编解码、流体仿真、图像处理、量化交易

1.3 适用场景

  • 深度学习模型训练与推理加速
  • 图像滤波、目标检测、特征提取
  • 矩阵运算、FFT、数值求解
  • 大规模数据批处理、科学仿真

二、CUDA 开发环境搭建

2.1 环境要求

  • 硬件:NVIDIA 显卡(算力 ≥ 3.5,推荐 ≥ 7.0)
  • 系统:Windows 10/11 或 Linux(Ubuntu/CentOS)
  • 工具链:Visual Studio(Windows)/ GCC(Linux)
  • CUDA Toolkit:建议选择稳定版(如 11.8 / 12.2)

2.2 Windows 安装步骤

  1. 查看显卡支持的最高 CUDA 版本

    cmd

    nvidia-smi
    
  2. 下载对应版本 CUDA Toolkit 并安装(建议自定义安装,只保留核心组件)
  3. 配置环境变量:确保 CUDA_PATHPath 包含 binlib\x64
  4. 验证安装

    cmd

    nvcc -V
    

出现版本信息即安装成功。

2.3 Linux 简易安装

bash

运行

wget https://developer.download.nvidia.com/compute/cuda/12.2.0/local_installers/cuda_12.2.0_535.54.03_linux.run
sudo sh cuda_12.2.0_535.54.03_linux.run

配置环境变量:

bash

运行

export PATH=/usr/local/cuda-12.2/bin:$PATH
export LD_LIBRARY_PATH=/usr/local/cuda-12.2/lib64:$LD_LIBRARY_PATH

三、CUDA 核心编程模型

3.1 基本概念

  • Host:CPU + 主机内存
  • Device:GPU + 显存
  • Kernel:GPU 上执行的并行函数,由 __global__ 修饰
  • Thread:最小执行单元
  • Block:线程块,内部线程可同步、共享局部内存
  • Grid:多个 Block 组成一个网格

3.2 执行模型

调用格式:

cpp

运行

kernel<<<GridDim, BlockDim>>>(参数...);

常用配置:

  • 一维:<<<N, 256>>>
  • Block 大小常用:32/64/128/256/512(32 的倍数)

3.3 常用内置变量

cpp

运行

threadIdx.x      // 线程在Block内的ID
blockIdx.x       // Block在Grid内的ID
blockDim.x       // 每个Block的线程数
gridDim.x        // Grid的Block数

四、第一个 CUDA 程序:向量加法

4.1 完整代码(vector_add.cu)

cpp

运行

#include <iostream>
#include <cstdio>

// CUDA内核函数:向量加法
__global__ void vectorAdd(const float *a, const float *b, float *c, int n) {
    int i = blockIdx.x * blockDim.x + threadIdx.x;
    if (i < n) {
        c[i] = a[i] + b[i];
    }
}

int main() {
    const int N = 1024;
    const size_t size = N * sizeof(float);

    // 主机端内存
    float *h_a = new float[N];
    float *h_b = new float[N];
    float *h_c = new float[N];

    // 初始化数据
    for (int i = 0; i < N; i++) {
        h_a[i] = i * 1.0f;
        h_b[i] = i * 2.0f;
    }

    // 设备端内存
    float *d_a, *d_b, *d_c;
    cudaMalloc(&d_a, size);
    cudaMalloc(&d_b, size);
    cudaMalloc(&d_c, size);

    // 数据拷贝 Host -> Device
    cudaMemcpy(d_a, h_a, size, cudaMemcpyHostToDevice);
    cudaMemcpy(d_b, h_b, size, cudaMemcpyHostToDevice);

    // 启动内核
    int blockSize = 256;
    int gridSize = (N + blockSize - 1) / blockSize;
    vectorAdd<<<gridSize, blockSize>>>(d_a, d_b, d_c, N);

    // 等待执行完成
    cudaDeviceSynchronize();

    // 结果拷贝 Device -> Host
    cudaMemcpy(h_c, d_c, size, cudaMemcpyDeviceToHost);

    // 输出前10项
    for (int i = 0; i < 10; i++) {
        printf("%.2f + %.2f = %.2f\n", h_a[i], h_b[i], h_c[i]);
    }

    // 释放内存
    delete[] h_a;
    delete[] h_b;
    delete[] h_c;
    cudaFree(d_a);
    cudaFree(d_b);
    cudaFree(d_c);

    return 0;
}

4.2 编译运行

Windows(VS 新建 CUDA 项目)Linux:

bash

运行

nvcc vector_add.cu -o vec_add
./vec_add

五、CUDA 内存模型与优化

5.1 内存层次(速度从快到慢)

  1. 寄存器:线程私有,极快
  2. 共享内存(shared:Block 内共享,延迟低
  3. 常量内存(constant:只读,全局缓存
  4. 全局内存(Global Memory):容量最大,访问延迟高

5.2 常用内存操作 API

cpp

运行

cudaMalloc()           // 分配显存
cudaMemcpy()           // 数据传输
cudaFree()             // 释放显存
__shared__ type var;   // 定义共享内存

5.3 基础优化原则

  • 减少 CPU-GPU 数据拷贝,这是最大性能瓶颈
  • 使用共享内存做数据复用与合并访问
  • 保证全局内存对齐访问、连续访问
  • Block 大小设置为 32 的倍数( warp 大小 = 32)

六、常用调试与性能工具

6.1 错误检查

建议封装宏:

cpp

运行

#define CHECK_CUDA_ERROR(err) \
    if (err != cudaSuccess) { \
        printf("%s:%d error:%s\n", __FILE__, __LINE__, cudaGetErrorString(err)); \
        exit(-1); \
    }

6.2 常用工具

  • nvprof / ncu:性能分析
  • NVIDIA Nsight:VS/VStudio 集成调试
  • nvidia-smi:查看 GPU 状态、占用、算力
Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐