nvcc
编译,生成可执行文件后运行。
在Linux系统下进行CUDA编程,可以充分利用NVIDIA GPU的强大计算能力来加速应用程序的运行,以下是一些关于CUDA编程实例的详细内容:
1、环境搭建
安装NVIDIA驱动:确保你的Linux系统已经安装了支持CUDA的NVIDIA显卡驱动,可以通过命令lspci | grep -i nvidia
来查看当前系统的GPU型号,然后根据型号从NVIDIA官网下载并安装相应的驱动程序。
安装CUDA Toolkit:可以从NVIDIA官网下载适合自己系统的CUDA安装包,然后通过命令sudo dpkg -i .deb
和sudo apt-get update
、sudo apt-get install cuda
等命令进行安装,安装完成后,需要重启系统。
配置环境变量:将CUDA的相关路径添加到环境变量中,例如在~/.bashrc
文件中添加以下内容:
export PATH=$PATH:/usr/local/cuda-<版本号>/bin
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/cuda-<版本号>/lib64:/usr/lib/x86_64-linux-gnu
2、简单加法实例
代码实现
定义核函数:使用__global__
关键字定义在GPU上运行且由CPU调用的核函数,例如一个简单的加法核函数,将两个整数相加并将结果存储在内存中。
主函数:在主函数中,声明主机变量和设备变量,使用cudaMalloc
为设备变量分配显存,将数据从主机复制到设备,调用核函数进行计算,然后将结果从设备复制回主机,最后释放设备内存。
完整代码示例
“`c++
#include <iostream>
#include <stdio.h>
__global__ void k_add(int a, int b, int* c) {
*c = a + b;
}
int main() {
int h_c;
int *d_c;
cudaMalloc((void**)&d_c, sizeof(int));
k_add<<<1, 1>>>(2, 7, d_c);
cudaMemcpy(&h_c, d_c, sizeof(int), cudaMemcpyDeviceToHost);
cudaFree(d_c);
printf("%d
", h_c);
return 0;
}
编译与运行:使用nvcc
编译器对上述代码进行编译,命令为nvcc -o add add.cu
,然后运行生成的可执行文件./add
,输出结果应为9。 3、矢量加法实例代码实现定义核函数:定义一个矢量加法的核函数,使用线程的全局索引来计算每个元素的加法。主函数:在主函数中,声明并初始化两个向量a和b,以及结果向量c,为它们在GPU上分配显存,将数据从主机复制到设备,调用核函数进行矢量加法计算,将结果从设备复制回主机,最后释放设备内存。完整代码示例 ```c++ #include <iostream> #include <stdio.h> #define N 65536 __global__ void k_add(int* a, int* b, int* c) { int tid = threadIdx.x + blockIdx.x * blockDim.x; while (tid < N) { c[tid] = a[tid] + b[tid]; tid += blockDim.x * gridDim.x; } } int main() { int a[N], b[N], c[N]; int *d_a, *d_b, *d_c; cudaMalloc((void**)&d_a, N * sizeof(int)); cudaMalloc((void**)&d_b, N * sizeof(int)); cudaMalloc((void**)&d_c, N * sizeof(int)); // 初始化向量a和b的数据 for (int i = 0; i < N; i++) { a[i] = i; b[i] = i; } cudaMemcpy(d_a, a, N * sizeof(int), cudaMemcpyHostToDevice); cudaMemcpy(d_b, b, N * sizeof(int), cudaMemcpyHostToDevice); k_add<<<1, N>>>(d_a, d_b, d_c); cudaMemcpy(c, d_c, N * sizeof(int), cudaMemcpyDeviceToHost); // 打印部分结果进行验证 for (int i = 0; i < 10; i++) { std::cout << c[i] << " "; } std::cout << std::endl; cudaFree(d_a); cudaFree(d_b); cudaFree(d_c); return 0; }
编译与运行:同样使用nvcc
编译器进行编译,命令为nvcc -o vector_add vector_add.cu
,然后运行./vector_add
,可以看到输出的结果向量c中的前10个元素。
4、矩阵乘法实例
代码实现
定义核函数:定义一个矩阵乘法的核函数,使用共享内存来提高计算效率,将矩阵分块存储到共享内存中,然后进行计算。
主函数:在主函数中,声明并初始化两个矩阵A和B,以及结果矩阵C,为它们在GPU上分配显存,将数据从主机复制到设备,调用核函数进行矩阵乘法计算,将结果从设备复制回主机,最后释放设备内存。
完整代码示例
“`c++
#include <iostream>
#include <stdio.h>
#define N 512
__global__ void matrixMulKernel(float *A, float *B, float *C) {
__shared__ float tileA[16][16];
__shared__ float tileB[16][16];
int tx = threadIdx.x;
int ty = threadIdx.y;
int bx = blockIdx.x;
int by = blockIdx.y;
float Csub = 0;
for (int ph = 0; ph < N / 16; ++ph) {
tileA[ty][tx] = A[bx * N + (tx + ph * 16)];
tileB[ty][tx] = B[(by + ph * 16) * N + tx];
__syncthreads();
for (int k = 0; k < 16; ++k) {
Csub += tileA[ty][k] * tileB[k][tx];
}
__syncthreads();
}
C[(by * N + ty) * N + tx] = Csub;
}
int main() {
float A[N][N], B[N][N], C[N][N];
float *d_A, *d_B, *d_C;
cudaMalloc((void**)&d_A, N * N * sizeof(float));
cudaMalloc((void**)&d_B, N * N * sizeof(float));
cudaMalloc((void**)&d_C, N * N * sizeof(float));
// 初始化矩阵A和B的数据
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
A[i][j] = i + j;
B[i][j] = i j;
}
}
cudaMemcpy(d_A, A, N * N * sizeof(float), cudaMemcpyHostToDevice);
cudaMemcpy(d_B, B, N * N * sizeof(float), cudaMemcpyHostToDevice);
dim3 dimBlock(16, 16);
dim3 dimGrid(N / dimBlock.x, N / dimBlock.y);
matrixMulKernel<<<dimGrid, dimBlock>>>(d_A, d_B, d_C);
cudaMemcpy(C, d_C, N * N * sizeof(float), cudaMemcpyDeviceToHost);
// 打印部分结果进行验证
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
std::cout << C[i][j] << " ";
}
std::cout << std::endl;
}
std::cout << std::endl;
cudaFree(d_A);
cudaFree(d_B);
cudaFree(d_C);
return 0;
}
编译与运行:使用nvcc
编译器编译,命令为nvcc -o matrix_mul matrix_mul.cu
,然后运行./matrix_mul
,可以看到输出的结果矩阵C的部分元素。 以上实例展示了在Linux系统下进行CUDA编程的基本步骤和方法,包括环境搭建、简单的加法运算、矢量加法以及矩阵乘法等操作,这些实例可以帮助初学者快速上手CUDA编程,并理解GPU并行计算的基本原理和应用。