|
| 1 | +--- |
| 2 | +title: 'cuda编程基础' |
| 3 | +date: '2024-11-02' |
| 4 | +tags: [] |
| 5 | +draft: false |
| 6 | +summary: |
| 7 | +--- |
| 8 | + |
| 9 | + |
| 10 | +## CUDA编程基础 |
| 11 | + |
| 12 | +CUDA(Compute Unified Device Architecture)是由NVIDIA开发的一种并行计算平台和编程模型,旨在利用GPU的强大计算能力。通过CUDA,开发者能够在GPU上执行计算密集型的任务,从而显著提高程序的性能。以下是CUDA编程的基本概念和步骤。 |
| 13 | + |
| 14 | +****CUDA编程模型概述**** |
| 15 | + |
| 16 | +在CUDA编程中,CPU被称为*host*,而GPU被称为*device*。这两者有各自独立的内存空间。CUDA程序通常包括以下几个步骤: |
| 17 | + |
| 18 | +- **内存分配**:在host和device上分别分配内存。 |
| 19 | + |
| 20 | +- **数据初始化**:在host上初始化数据。 |
| 21 | + |
| 22 | +- **数据传输**:将数据从host传输到device。 |
| 23 | + |
| 24 | +- **核函数执行**:在device上执行核函数(kernel)。 |
| 25 | + |
| 26 | +- **结果传回**:将计算结果从device传回host。 |
| 27 | + |
| 28 | +- **内存释放**:释放在host和device上分配的内存。 |
| 29 | + |
| 30 | +****CUDA核函数**** |
| 31 | + |
| 32 | +核函数是指在GPU上并行执行的函数。使用`__global__`关键字来定义核函数,并通过`<<<grid, block>>>`语法来指定执行配置,其中`grid`表示网格的数量,`block`表示每个网格中的线程块数量。例如: |
| 33 | + |
| 34 | +```cpp |
| 35 | +__global__ void vectorAdd(float *A, float *B, float *C, int N) { |
| 36 | + int i = blockIdx.x * blockDim.x + threadIdx.x; |
| 37 | + if (i < N) { |
| 38 | + C[i] = A[i] + B[i]; |
| 39 | + } |
| 40 | +} |
| 41 | +``` |
| 42 | + |
| 43 | +在这个例子中,`vectorAdd`是一个核函数,它将两个向量相加并将结果存储到第三个向量中。 |
| 44 | + |
| 45 | +****线程和块的概念**** |
| 46 | + |
| 47 | +CUDA中的线程是执行计算的基本单位。每个线程都有一个唯一的ID,可以通过内置变量如`threadIdx`、`blockIdx`和`blockDim`来访问。线程被组织成块(block),多个块组成一个网格(grid)。这种层次结构使得CUDA能够高效地管理大量并行任务。 |
| 48 | + |
| 49 | +****内存管理**** |
| 50 | + |
| 51 | +CUDA提供了多种内存类型,包括: |
| 52 | + |
| 53 | +- **全局内存(Global Memory)**:所有线程都可以访问,但访问速度较慢。 |
| 54 | + |
| 55 | +- **共享内存(Shared Memory)**:同一块中的线程可以共享,速度较快,但容量有限。 |
| 56 | + |
| 57 | +- **局部内存(Local Memory)**:每个线程私有,通常用于存储局部变量。 |
| 58 | + |
| 59 | +使用以下API进行内存管理: |
| 60 | + |
| 61 | +- `cudaMalloc()`:在device上分配内存。 |
| 62 | + |
| 63 | +- `cudaMemcpy()`:在host和device之间传输数据。 |
| 64 | + |
| 65 | +- `cudaFree()`:释放已分配的设备内存。 |
| 66 | + |
| 67 | +例如: |
| 68 | + |
| 69 | +```cpp |
| 70 | +float *d_A, *d_B, *d_C; |
| 71 | +cudaMalloc(&d_A, N * sizeof(float)); |
| 72 | +cudaMalloc(&d_B, N * sizeof(float)); |
| 73 | +cudaMalloc(&d_C, N * sizeof(float)); |
| 74 | +``` |
| 75 | + |
| 76 | +****简单示例:向量加法**** |
| 77 | + |
| 78 | +以下是一个完整的向量加法示例,包括主机代码和设备代码: |
| 79 | + |
| 80 | +```cpp |
| 81 | +#include <stdio.h> |
| 82 | + |
| 83 | +__global__ void vectorAdd(float *A, float *B, float *C, int N) { |
| 84 | + int i = blockIdx.x * blockDim.x + threadIdx.x; |
| 85 | + if (i < N) { |
| 86 | + C[i] = A[i] + B[i]; |
| 87 | + } |
| 88 | +} |
| 89 | + |
| 90 | +int main() { |
| 91 | + int N = 1 << 20; // 1M elements |
| 92 | + size_t size = N * sizeof(float); |
| 93 | + |
| 94 | + // 在主机上分配内存 |
| 95 | + float *h_A = (float *)malloc(size); |
| 96 | + float *h_B = (float *)malloc(size); |
| 97 | + float *h_C = (float *)malloc(size); |
| 98 | + |
| 99 | + // 初始化向量 |
| 100 | + for (int i = 0; i < N; i++) { |
| 101 | + h_A[i] = i; |
| 102 | + h_B[i] = i; |
| 103 | + } |
| 104 | + |
| 105 | + if (h_A == NULL || h_B == NULL || h_C == NULL) { |
| 106 | + printf("Memory allocation failed\n"); |
| 107 | + return 1; |
| 108 | + } |
| 109 | + |
| 110 | + functio |
| 111 | + // 在设备上分配内存 |
| 112 | + float *d_A, *d_B, *d_C; |
| 113 | + cudaMalloc(&d_A, size); |
| 114 | + cudaMalloc(&d_B, size); |
| 115 | + cudaMalloc(&d_C, size); |
| 116 | + |
| 117 | + // 将数据从主机复制到设备 |
| 118 | + cudaMemcpy(d_A, h_A, size, cudaMemcpyHostToDevice); |
| 119 | + cudaMemcpy(d_B, h_B, size, cudaMemcpyHostToDevice); |
| 120 | + |
| 121 | + // 启动核函数 |
| 122 | + int threadsPerBlock = 256; |
| 123 | + int blocksPerGrid = (N + threadsPerBlock - 1) / threadsPerBlock; |
| 124 | + vectorAdd<<<blocksPerGrid, threadsPerBlock>>>(d_A, d_B, d_C, N); |
| 125 | + |
| 126 | + // 将结果从设备复制回主机 |
| 127 | + cudaMemcpy(h_C, d_C, size, cudaMemcpyDeviceToHost); |
| 128 | + |
| 129 | + // 验证结果 |
| 130 | + for (int i = 0; i < N; i++) { |
| 131 | + if (h_C[i] != h_A[i] + h_B[i]) { |
| 132 | + printf("Error: %f != %f\n", h_C[i], h_A[i] + h_B[i]); |
| 133 | + break; |
| 134 | + } |
| 135 | + } |
| 136 | + |
| 137 | + // 释放设备和主机内存 |
| 138 | + cudaFree(d_A); |
| 139 | + cudaFree(d_B); |
| 140 | + cudaFree(d_C); |
| 141 | + free(h_A); |
| 142 | + free(h_B); |
| 143 | + free(h_C); |
| 144 | + |
| 145 | + return 0; |
| 146 | +} |
| 147 | +``` |
| 148 | +
|
| 149 | +这个示例展示了如何使用CUDA进行简单的向量加法,包括内存管理、核函数定义及调用等基本操作。 |
| 150 | +
|
| 151 | +通过以上内容,你可以对CUDA编程有一个初步的了解,并能够编写简单的CUDA程序。随着对CUDA更深入的学习,你将能够掌握更多优化技巧和高级特性,以充分利用GPU的计算能力。 |
| 152 | +
|
| 153 | +Citations: |
| 154 | +[1] https://www.youtube.com/watch?v=IuxJO0HOcH0 |
| 155 | +[2] https://blog.csdn.net/weixin_44966641/article/details/124448102 |
| 156 | +[3] https://godweiyang.com/2021/01/25/cuda-reading/ |
| 157 | +[4] https://developer.nvidia.com/blog/easy-introduction-cuda-c-and-c/ |
| 158 | +[5] https://blog.csdn.net/m0_37870649/article/details/132122059 |
| 159 | +[6] https://hpcwiki.io/gpu/cuda/ |
| 160 | +[7] https://cuda-tutorial.readthedocs.io/en/latest/tutorials/tutorial01/ |
| 161 | +[8] https://developer.nvidia.com/zh-cn/blog/cuda-model-intro-cn/ |
| 162 | +[9] https://cuda-tutorial.github.io/part1_22.pdf |
0 commit comments