在传统 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;
}
Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐