CUDA编程入门代码
一、CUDA核心概念
-
Host与Device
- Host:CPU及其内存,负责控制流程和复杂逻辑。
- Device:GPU及其显存,专为并行计算设计,需通过PCIe总线与Host通信。
-
Kernel函数
- 用
__global__
修饰,在GPU上并行执行的函数,通过<<<grid, block>>>
语法指定线程规模。
- 用
-
线程层次结构
- Thread:最小执行单元,通过
threadIdx
定位。 - Block:包含多个线程(最多1024个),块内线程可共享内存(Shared Memory)并通过
__syncthreads()
同步。 - Grid:多个Block的集合,通过
blockIdx
定位。
- Thread:最小执行单元,通过
-
内存模型
- 全局内存(Global Memory):所有线程可访问,容量大但延迟高。
- 共享内存(Shared Memory):Block内共享,速度接近寄存器。
- 常量内存 (Constant Memory):只读内存,适用于在内核执行期间不改变的值。访问速度较快(当所有线程访问相同地址时)。
- 纹理内存 (Texture Memory):专门用于处理图像和纹理数据的只读内存。提供缓存机制,适合进行空间局部性访问。支持各种过滤和坐标变换。
- 寄存器(Registers):线程私有,访问最快。
二、CUDA编程步骤
-
环境配置
- 安装CUDA Toolkit(如v11.8或更高)并验证
nvidia-smi
输出。
- 安装CUDA Toolkit(如v11.8或更高)并验证
-
第一个CUDA程序,比如test.cu文件
#include "cuda_runtime.h" #include "device_launch_parameters.h" #include <stdio.h> __global__ void vector_add(float *a, float *b, float *c, int size){ int tid = blockIdx.x*blockDim.x + threadIdx.x; if(tid < size){ c[tid] = a[tid] + b[tid]; } } int main() { int size = 1000; float *a, *b, *c, *c_host; c_host = (float*)malloc(sizeof(float)*size); //设备内存分配 cudaMalloc(&a, sizeof(float)*size); cudaMalloc(&b, sizeof(float)*size); cudaMalloc(&c, sizeof(float)*size); //初始化及数据传输 float a_host[1000]; float b_host[1000]; int n = 0; for(n=0; n<size; n++){ a_host[n] = 1.0; b_host[n] = 99.0; } cudaMemcpy(a,a_host,sizeof(float)*size,cudaMemcpyHostToDevice); cudaMemcpy(b,b_host,sizeof(float)*size,cudaMemcpyHostToDevice); // dim3 block(256); //每Block 256线程 dim3 grid((size+256-1)/256);//计算所需Block数(这里根据size计算) vector_add<<<grid,block>>>(a,b,c,size); //结果回传到主机内存 cudaMemcpy(c_host,c,sizeof(float)*size,cudaMemcpyDeviceToHost); cudaDeviceSynchronize(); // 等待GPU执行完成 printf("host data head:%.2f tail:%.2f\n", c_host[0], c_host[size-1]); cudaFree(a); cudaFree(b); cudaFree(c); free(c_host); return 0; }
编译命令:
nvcc test.cu -o test
-
内存管理
使用cudaMalloc
分配设备内存,cudaFree释放设备内存。
使用cudaMallocHost/malloc分配主机内存,使用cudaFreeHost/free释放主机内存。
cudaMemcpy
在Host与Device间传输数据。
cudaMemcpy(deviceA, hostA, size, cudaMemcpyHostToDevice); 从主机到设备复制数据。
cudaMemcpy(hostB, deviceB, size, cudaMemcpyDeviceToHost);从设备到主机复制暑假。