
什么是CUDA?
CUDA(Compute Unified Device Architecture)是NVIDIA推出的并行计算平台和编程模型,它允许开发者利用NVIDIA GPU的并行计算能力进行通用计算(即GPGPU,General-Purpose computing on Graphics Processing Units)。
传统上,GPU主要用于图形渲染,而CUDA通过扩展C/C++等语言,让开发者可以直接编写代码控制GPU的大规模并行线程,从而加速需要高并行度的任务(如深度学习、科学计算、图像处理等)。其核心是核函数(Kernel)——在GPU上并行执行的函数,由成百上千个线程同时运行。
如何入门CUDA开发?
入门CUDA开发需要掌握基础概念、搭建环境,并通过实践逐步深入,步骤如下:
1. 前置知识
- C/C++基础:CUDA基于C扩展,核心语法与C兼容;
- 并行计算概念:理解“线程(Thread)、线程块(Block)、网格(Grid)”的层次结构(GPU的并行单元组织方式);
- GPU架构基础:了解GPU与CPU的差异(GPU核心数量远多于CPU,适合数据并行任务)。
2. 环境搭建
- 硬件要求:需要支持CUDA的NVIDIA显卡(查看显卡型号是否在NVIDIA兼容列表中,计算能力≥3.0即可入门);
- 软件安装:
- 安装CUDA Toolkit(包含编译器
nvcc、调试工具Nsight、示例代码等); - 验证安装:终端运行
nvcc --version查看版本,或运行/usr/local/cuda/samples/1_Utilities/deviceQuery检测设备是否正常。
- 安装CUDA Toolkit(包含编译器
3. 学习路径
- 官方文档:CUDA C++ Programming Guide(最权威的入门资料);
- 实践入门:从简单的并行任务(如向量加法、矩阵乘法)开始,理解核函数调用、内存管理;
- 深入优化:学习GPU内存模型(全局内存、共享内存、常量内存等)、线程同步、指令优化等。
优秀的CUDA开源库
CUDA生态有大量成熟的开源库,可避免重复开发,直接复用高性能并行算法:
| 库名称 | 用途 | 特点 |
|---|---|---|
| Thrust | 并行算法库(类似STL) | 接口简单,支持排序、reduce、transform等 |
| cuBLAS | 线性代数运算(矩阵/向量) | 高度优化,比CPU版本快10-100倍 |
| cuFFT | 快速傅里叶变换 | 支持多维FFT,适合信号处理 |
| cuSPARSE | 稀疏矩阵运算 | 针对稀疏数据的高效计算 |
| TensorRT | 深度学习推理加速 | 优化神经网络模型,提升推理速度 |
示例代码
下面通过两个例子展示CUDA开发:原生CUDA向量加法(理解核函数)和Thrust库实现(简化开发)。
示例1:原生CUDA实现向量加法
功能:计算两个向量a和b的和,结果存到c(即c[i] = a[i] + b[i])。
#include <iostream>
#include <cassert>
// 核函数:在GPU上并行执行,每个线程处理一个元素
__global__ void vectorAdd(const float* a, const float* b, float* c, int n) {
// 计算当前线程的全局索引(每个线程处理一个元素)
int i = blockIdx.x * blockDim.x + threadIdx.x;
// 避免索引越界(当n不是线程块大小的整数倍时)
if (i < n) {
c[i] = a[i] + b[i];
}
}
int main() {
const int n = 1000000; // 向量长度
size_t size = n * sizeof(float);
// 1. 主机(CPU)内存分配
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] = static_cast<float>(i);
h_b[i] = static_cast<float>(i * 2);
}
// 2. 设备(GPU)内存分配
float* d_a;
float* d_b;
float* d_c;
cudaMalloc(&d_a, size); // 分配GPU全局内存
cudaMalloc(&d_b, size);
cudaMalloc(&d_c, size);
// 3. 数据从CPU传输到GPU
cudaMemcpy(d_a, h_a, size, cudaMemcpyHostToDevice);
cudaMemcpy(d_b, h_b, size, cudaMemcpyHostToDevice);
// 4. 启动核函数(配置线程结构)
int blockSize = 256; // 每个线程块的线程数(通常取128/256/512)
int gridSize = (n + blockSize - 1) / blockSize; // 网格中的线程块数
vectorAdd<<<gridSize, blockSize>>>(d_a, d_b, d_c, n); // 核函数调用语法
// 检查核函数是否执行成功
cudaError_t err = cudaGetLastError();
if (err != cudaSuccess) {
std::cerr << "Kernel launch failed: " << cudaGetErrorString(err) << std::endl;
return 1;
}
// 5. 结果从GPU传输回CPU
cudaMemcpy(h_c, d_c, size, cudaMemcpyDeviceToHost);
// 验证结果(检查前10个和最后10个元素)
for (int i = 0; i < 10; ++i) {
assert(h_c[i] == h_a[i] + h_b[i]);
}
for (int i = n - 10; i < n; ++i) {
assert(h_c[i] == h_a[i] + h_b[i]);
}
std::cout << "Vector addition successful!" << std::endl;
// 6. 释放内存
delete[] h_a;
delete[] h_b;
delete[] h_c;
cudaFree(d_a); // 释放GPU内存
cudaFree(d_b);
cudaFree(d_c);
return 0;
}
关键说明:
- 核函数用
__global__修饰,必须通过<<<gridSize, blockSize>>>指定线程结构(网格包含多少块,每块包含多少线程); - 线程索引计算:
blockIdx.x(块编号)、threadIdx.x(块内线程编号),组合得到全局索引i; - 内存管理:
cudaMalloc分配GPU内存,cudaMemcpy在CPU和GPU间传输数据。
示例2:Thrust库简化实现
Thrust提供了类似STL的接口,无需手动编写核函数,直接调用并行算法:
#include <thrust/device_vector.h>
#include <thrust/transform.h>
#include <thrust/functional.h>
#include <iostream>
int main() {
const int n = 1000000;
// 1. 初始化CPU数据
float* h_a = new float[n];
float* h_b = new float[n];
for (int i = 0; i < n; ++i) {
h_a[i] = static_cast<float>(i);
h_b[i] = static_cast<float>(i * 2);
}
// 2. 用Thrust的device_vector管理GPU内存(自动分配/释放)
thrust::device_vector<float> d_a(h_a, h_a + n); // 从CPU数据初始化
thrust::device_vector<float> d_b(h_b, h_b + n);
thrust::device_vector<float> d_c(n);
// 3. 调用thrust::transform执行并行加法(内部自动优化核函数)
thrust::transform(d_a.begin(), d_a.end(), // 输入1
d_b.begin(), // 输入2
d_c.begin(), // 输出
thrust::plus<float>()); // 加法操作
// 4. 验证结果(复制回CPU)
thrust::host_vector<float> h_c = d_c; // host_vector自动从GPU复制数据
for (int i = 0; i < 10; ++i) {
std::cout << h_c[i] << " "; // 输出:0 3 6 ... 27
}
std::cout << std::endl;
// 自动释放内存(无需手动free)
delete[] h_a;
delete[] h_b;
return 0;
}
编译运行:
两个示例均用nvcc编译(CUDA编译器):
nvcc vector_add.cu -o vector_add # 原生CUDA版本
nvcc thrust_add.cu -o thrust_add # Thrust版本
./vector_add # 运行
总结
CUDA是利用NVIDIA GPU并行能力的核心工具,入门需掌握线程模型和内存管理,通过简单示例(如向量加法)实践;开源库(如Thrust、cuBLAS)可大幅简化开发,建议优先复用。随着实践深入,可逐步学习性能优化(如共享内存利用、指令重排),应对更复杂的并行任务。
137

被折叠的 条评论
为什么被折叠?



