CUDA11-VS2015安装-工具链测试-Helloworld程序

文章目录

1.下载工具链

下载cuda_11.0.2_451.48_win10,如下图所示:

2.安装

按默认指引安装。

3.新建cuda运行时控制台程序

4.默认代码分析

cpp 复制代码
#include "cuda_runtime.h"
#include "device_launch_parameters.h"

#include <stdio.h>

cudaError_t addWithCuda(int *c, const int *a, const int *b, unsigned int size);

__global__ void addKernel(int *c, const int *a, const int *b)
{
    int i = threadIdx.x;
    c[i] = a[i] + b[i];
}

int main()
{
    const int arraySize = 5;
    const int a[arraySize] = { 1, 2, 3, 4, 5 };
    const int b[arraySize] = { 10, 20, 30, 40, 50 };
    int c[arraySize] = { 0 };

    // Add vectors in parallel.
    cudaError_t cudaStatus = addWithCuda(c, a, b, arraySize);
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "addWithCuda failed!");
        return 1;
    }

    printf("{1,2,3,4,5} + {10,20,30,40,50} = {%d,%d,%d,%d,%d}\n",
        c[0], c[1], c[2], c[3], c[4]);

    // cudaDeviceReset must be called before exiting in order for profiling and
    // tracing tools such as Nsight and Visual Profiler to show complete traces.
    cudaStatus = cudaDeviceReset();
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "cudaDeviceReset failed!");
        return 1;
    }

    return 0;
}

// Helper function for using CUDA to add vectors in parallel.
cudaError_t addWithCuda(int *c, const int *a, const int *b, unsigned int size)
{
    int *dev_a = 0;
    int *dev_b = 0;
    int *dev_c = 0;
    cudaError_t cudaStatus;

    // Choose which GPU to run on, change this on a multi-GPU system.
    cudaStatus = cudaSetDevice(0);
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "cudaSetDevice failed!  Do you have a CUDA-capable GPU installed?");
        goto Error;
    }

    // Allocate GPU buffers for three vectors (two input, one output)    .
    cudaStatus = cudaMalloc((void**)&dev_c, size * sizeof(int));
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "cudaMalloc failed!");
        goto Error;
    }

    cudaStatus = cudaMalloc((void**)&dev_a, size * sizeof(int));
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "cudaMalloc failed!");
        goto Error;
    }

    cudaStatus = cudaMalloc((void**)&dev_b, size * sizeof(int));
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "cudaMalloc failed!");
        goto Error;
    }

    // Copy input vectors from host memory to GPU buffers.
    cudaStatus = cudaMemcpy(dev_a, a, size * sizeof(int), cudaMemcpyHostToDevice);
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "cudaMemcpy failed!");
        goto Error;
    }

    cudaStatus = cudaMemcpy(dev_b, b, size * sizeof(int), cudaMemcpyHostToDevice);
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "cudaMemcpy failed!");
        goto Error;
    }

    // Launch a kernel on the GPU with one thread for each element.
    addKernel<<<1, size>>>(dev_c, dev_a, dev_b);

    // Check for any errors launching the kernel
    cudaStatus = cudaGetLastError();
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "addKernel launch failed: %s\n", cudaGetErrorString(cudaStatus));
        goto Error;
    }
    
    // cudaDeviceSynchronize waits for the kernel to finish, and returns
    // any errors encountered during the launch.
    cudaStatus = cudaDeviceSynchronize();
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "cudaDeviceSynchronize returned error code %d after launching addKernel!\n", cudaStatus);
        goto Error;
    }

    // Copy output vector from GPU buffer to host memory.
    cudaStatus = cudaMemcpy(c, dev_c, size * sizeof(int), cudaMemcpyDeviceToHost);
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "cudaMemcpy failed!");
        goto Error;
    }

Error:
    cudaFree(dev_c);
    cudaFree(dev_a);
    cudaFree(dev_b);
    
    return cudaStatus;
}

这是一个标准的CUDA向量加法示例代码。我来详细分析其结构和关键点:

4.1.代码整体功能

实现两个整型向量的并行加法:c[i] = a[i] + b[i]

4.2.核心组件分析

a. Kernel函数(第8-11行)

cuda 复制代码
__global__ void addKernel(int *c, const int *a, const int *b)
{
    int i = threadIdx.x;  // 获取线程在block中的索引
    c[i] = a[i] + b[i];
}
  • __global__:表示在GPU上执行,从CPU调用
  • 使用threadIdx.x作为数组索引,限制:只能处理单个block内的线程数(通常≤1024)

b. 主函数流程

  • 定义输入数组a、b和输出数组c(大小5)
  • 调用addWithCuda执行GPU计算
  • 打印结果
  • 重置设备

c. 辅助函数 addWithCuda (第51-121行)

主要步骤:
  1. 设备选择cudaSetDevice(0)
  2. 内存分配cudaMalloc分配GPU显存
  3. 数据传输cudaMemcpy将数据从主机复制到设备
  4. 内核启动addKernel<<<1, size>>>
    • 1个block
    • size个线程(这里是5)
  5. 同步等待cudaDeviceSynchronize()
  6. 结果回传cudaMemcpy将结果从设备复制回主机
  7. 资源释放cudaFree

4.4.关键问题与改进建议

⚠️ 主要缺陷

cuda 复制代码
int i = threadIdx.x;  // 仅适用于小数据量

问题 :当arraySize > 1024时会失败(单个block线程数限制)

✅ 改进版本

cuda 复制代码
__global__ void addKernel(int *c, const int *a, const int *b, int size)
{
    int i = blockIdx.x * blockDim.x + threadIdx.x;
    if (i < size) {
        c[i] = a[i] + b[i];
    }
}

// 调用方式
int blockSize = 256;
int gridSize = (size + blockSize - 1) / blockSize;
addKernel<<<gridSize, blockSize>>>(dev_c, dev_a, dev_b, size);

4.5.错误处理机制

  • 使用goto Error统一错误处理
  • 每个CUDA API调用都检查返回值
  • 内核启动后检查cudaGetLastError()
  • 使用cudaDeviceSynchronize()捕获执行错误

4.6.性能观察点

  1. 数据传输开销:小数据量(5个整数)时,GPU并行优势不明显
  2. 未使用流:所有操作在默认流中顺序执行
  3. 内存访问模式:合并访问良好(连续线程访问连续地址)

4.7.代码规范

  • 使用cudaError_t类型检查错误
  • 资源清理使用goto集中处理
  • 包含必要的头文件和注释

这个代码是学习CUDA编程的良好起点,完整展示了GPU编程的典型流程:分配内存 → 传输数据 → 启动内核 → 同步 → 回传结果 → 释放资源。

相关推荐
攻城狮Soar2 小时前
STL源码解析之deque
开发语言·c++
Rabitebla3 小时前
C++ 多态详解:从概念到虚表底层原理(代码轰炸)
开发语言·c++
charlie1145141913 小时前
通用GUI编程技术——图形渲染实战(五十)——命中测试与鼠标事件路由:精确交互
c++·windows·架构·交互·图形渲染
hetao17338373 小时前
2026-05-25~06-11 hetao1733837 的刷题记录
c++·算法
洛水水3 小时前
【力扣100题】82.有效的括号
c++·算法·leetcode
初中就开始混世的大魔王4 小时前
7 Fast DDS-持久化服务
c++·人工智能·中间件·自动驾驶·信息与通信
爱吃生蚝的于勒4 小时前
QT开发第三章——常用控件
linux·服务器·开发语言·前端·javascript·c++·qt
Shadow(⊙o⊙)4 小时前
QT常用控件1.0,enabled() geometry() QIcon的.qrc文件导入
开发语言·c++·qt
wuminyu4 小时前
Java锁膨胀机制之偏向锁到轻量级锁源码剖析
java·linux·c语言·jvm·c++