使用 cuda 实现向量加法
·
在传统 CPU 计算中,向量加法通常通过顺序遍历数组并逐个计算结果来实现,这种方式是串行的,计算效率受限于 CPU 的核心数量和单线程性能。
而在 CUDA 中,向量加法可以通过核函数(Kernel Function)实现并行计算。每个线程独立地处理数组中的一个元素,通过获取当前线程的全局索引(globalIdx)来确定其操作的数据位置。这种方式充分利用了 GPU 的并行计算能力,显著提高了计算效率。
CUDA 代码文件后缀名是.cu,使用 nvcc 编译后会得到可执行文件。
#include <stdio.h>
void initialData(float *addr, int elemCount)
{
for (int i = 0; i < elemCount; i++)
{
addr[i] = (float)(rand() % 100) / 10.f;
}
return;
}
__device__ float add(const float a, const float b){
return a + b;
}
__global__ void gpuAdd(float *a, float *b, float *c, const int N){
const int bid = blockIdx.x;
const int tid = threadIdx.x;
const int id = tid + bid*blockDim.x;
if (id < N){
c[id] = add(a[id], b[id]); //传统cpu计算需要遍历,而gpu计算则是通过获取当前
}
else{
return;
}
}
int main() {
// 1、设置设备
int iDeviceCount = 0;
cudaError_t error = cudaGetDeviceCount(&iDeviceCount);
if (error != cudaSuccess || iDeviceCount == 0){
printf("No CUDA device found\n");
exit(-1);
}
else{
printf("Found %d CUDA devices\n", iDeviceCount);
}
int iDevice = 0;
error = cudaSetDevice(iDevice);
if (error != cudaSuccess){
printf("fail to set");
exit(-1);
}
else{
printf("set sucuccess\n");
}
// 2、分配内存,初始化数据
int iElemCount = 333; //向量长度
size_t iBytes = iElemCount * sizeof(float);
float *h_A = (float *)malloc(iBytes);
float *h_B = (float *)malloc(iBytes);
float *h_C = (float *)malloc(iBytes);
if (h_A == NULL || h_B == NULL || h_C == NULL){
printf("malloc failed\n");
exit(-1);
}
else{
memset(h_A, 0, iBytes);
memset(h_B, 0, iBytes);
memset(h_C, 0, iBytes);
}
float *d_A, *d_B, *d_C;
cudaMalloc((float**)&d_A, iBytes);
cudaMalloc((float**)&d_B, iBytes);
cudaMalloc((float**)&d_C, iBytes);
if (d_A == NULL || d_B == NULL || d_C == NULL){
printf("gpu malloc failed\n");
free(h_A);
free(h_B);
free(h_C);
exit(-1);
}
else{
cudaMemset(d_A, 0, iBytes);
cudaMemset(d_B, 0, iBytes);
cudaMemset(d_C, 0, iBytes);
}
// 3、初始化主机数据
srand(666);
initialData(h_A, iElemCount);
initialData(h_B, iElemCount);
// 4、数据传输(主机到设备)
cudaMemcpy(d_A, h_A, iBytes, cudaMemcpyHostToDevice);
cudaMemcpy(d_B, h_B, iBytes, cudaMemcpyHostToDevice);
cudaMemcpy(d_C, h_C, iBytes, cudaMemcpyHostToDevice);
// 5、调用核函数进行计算
dim3 block(32);
dim3 grid((iElemCount + block.x - 1) / block.x);
gpuAdd<<<grid, block>>>(d_A, d_B, d_C, iElemCount);
// 6、数据传输(设备到主机)
cudaMemcpy(h_C, d_C, iBytes, cudaMemcpyDeviceToHost);
for (int i = 0; i < iElemCount; i++){ // 打印
printf("idx=%2d\tmatrix_A:%.1f\tmatrix_B:%.1f\tresult=%.1f\n", i+1, h_A[i], h_B[i], h_C[i]);
}
// 7、释放内存
free(h_A);
free(h_B);
free(h_C);
cudaFree(d_A);
cudaFree(d_B);
cudaFree(d_C);
cudaDeviceReset();
return 0;
}
更多推荐
所有评论(0)