【大模型学习cuda】入们第一个例子-向量和

cpp 复制代码
        `````````#include <stdio.h>
#include <cuda_runtime.h>

// CUDA核函数:向量加法
// 每个线程处理一个元素
__global__ void vectorAdd(const float* a, const float* b, float* c, int n) {
    // 计算全局线程索引
    int idx = blockIdx.x * blockDim.x + threadIdx.x;

    // 确保不越界
    if (idx < n) {
        c[idx] = a[idx] + b[idx];
    }
}

// 主函数
int main() {
    int n = 1024 * 1024;  // 向量大小:1M个元素
    size_t size = n * sizeof(float);

    printf("CUDA向量加法程序\n");
    printf("向量大小: %d\n", n);

    // 1. 分配主机内存
    float *h_a = (float*)malloc(size);
    float *h_b = (float*)malloc(size);
    float *h_c = (float*)malloc(size);

    // 2. 初始化主机数据
    for (int i = 0; i < n; i++) {
        h_a[i] = (float)i;
        h_b[i] = (float)i * 2.0f;
    }

    // 3. 分配设备内存
    float *d_a, *d_b, *d_c;
    cudaMalloc((void**)&d_a, size);
    cudaMalloc((void**)&d_b, size);
    cudaMalloc((void**)&d_c, size);

    // 4. 将数据从主机复制到设备
    cudaMemcpy(d_a, h_a, size, cudaMemcpyHostToDevice);
    cudaMemcpy(d_b, h_b, size, cudaMemcpyHostToDevice);

    // 5. 启动CUDA核函数
    int threadsPerBlock = 256;
    int blocksPerGrid = (n + threadsPerBlock - 1) / threadsPerBlock;

    printf("\n启动核函数...\n");
    printf("每个线程块包含 %d 个线程\n", threadsPerBlock);
    printf("总共启动 %d 个线程块\n", blocksPerGrid);

    vectorAdd<<<blocksPerGrid, threadsPerBlock>>>(d_a, d_b, d_c, n);

    // 6. 等待GPU完成计算并检查错误
    cudaError_t err = cudaGetLastError();
    if (err != cudaSuccess) {
        printf("CUDA错误: %s\n", cudaGetErrorString(err));
        return -1;
    }

    // 7. 将结果从设备复制回主机
    cudaMemcpy(h_c, d_c, size, cudaMemcpyDeviceToHost);

    // 8. 验证结果
    printf("\n验证结果...\n");
    bool success = true;
    for (int i = 0; i < 10; i++) {  // 只检查前10个元素
        float expected = h_a[i] + h_b[i];
        if (fabs(h_c[i] - expected) > 1e-5) {
            printf("错误: a[%d]=%.2f, b[%d]=%.2f, c[%d]=%.2f (期望值: %.2f)\n",
                   i, h_a[i], i, h_b[i], i, h_c[i], expected);
            success = false;
            break;
        }
    }

    if (success) {
        printf("✓ 验证通过!前10个元素计算正确。\n");
        printf("示例: a[0]=%.2f + b[0]=%.2f = c[0]=%.2f\n", h_a[0], h_b[0], h_c[0]);
    }

    // 9. 释放内存
    free(h_a);
    free(h_b);
    free(h_c);
    cudaFree(d_a);
    cudaFree(d_b);
    cudaFree(d_c);

    printf("\n程序执行完成!\n");
    return 0;
}
cpp 复制代码
   > (void**)&d_a  这里为什么是这个样子的?                                                                                                                                                                                    

✦ cudaMalloc 使用 (void**)&d_a 是因为 cudaMalloc 函数的签名要求传入一个 void** 类型的参数。

  让我解释一下原因:

  1. cudaMalloc 函数签名
   cudaError_t cudaMalloc(void** devPtr, size_t size);
   - 第一个参数是 void** 类型(指向指针的指针)
   - 第二个参数是分配的内存大小

  2. 为什么需要指向指针的指针?

  cudaMalloc 需要修改指针 d_a 本身的值(让它指向设备内存地址),而不仅仅是修改指针指向的内容。

  在 C/C++ 中,如果要修改一个变量的值,需要传递它的地址:
   - 修改普通变量 → 传递 &变量(地址)
   - 修改指针变量 → 传递 &指针(指针的地址)

  3. 类型转换过程

   float *d_a;  // d_a 的类型是 float*

   - &d_a 的类型是 float**(指向 float 指针的指针)
   - cudaMalloc 要求 void**
   - 所以需要强制转换:(void**)&d_a

  4. 类比:标准库的 malloc

  对比一下 CPU 端的内存分配:
   // CPU 端 - malloc 返回值
   float *d_a = (float*)malloc(size);  // 直接返回指针

   // GPU 端 - cudaMalloc 通过参数返回
   float *d_a;
   cudaMalloc((void**)&d_a, size);     // 通过参数返回指针地址

  5. 完整示例
   float *d_a;           // 声明一个 float 指针
   cudaMalloc((void**)&d_a, size);  // 将 float** 转换为 void** 传递

   // 执行后,d_a 被赋值为设备内存的地址

✦ 简单来说:因为 `cudaMalloc` 需要修改指针 `d_a` 的值,让它指向新分配的设备内存,所以必须传递 `d_a` 
  的地址(即 `&d_a`),并进行类型转换。

成!编译和执行都已成功。

总结:

  1. 编译命令:

    nvcc vector_add.cu -o vector_add

  2. 执行命令:

    ./vector_add

  3. 程序输出:

    • 程序处理了 1,048,576 (1M) 个元素的向量加法
    • 使用了 256 个线程/块,共 4096 个线程块
    • 计算结果验证通过 ✓

✦ CUDA 程序成功在 GPU 上运行并完成了向量加法计算!

相关推荐
西岸行者3 天前
学习笔记:SKILLS 能帮助更好的vibe coding
笔记·学习
悠哉悠哉愿意3 天前
【单片机学习笔记】串口、超声波、NE555的同时使用
笔记·单片机·学习
别催小唐敲代码3 天前
嵌入式学习路线
学习
毛小茛3 天前
计算机系统概论——校验码
学习
babe小鑫3 天前
大专经济信息管理专业学习数据分析的必要性
学习·数据挖掘·数据分析
winfreedoms3 天前
ROS2知识大白话
笔记·学习·ros2
在这habit之下3 天前
Linux Virtual Server(LVS)学习总结
linux·学习·lvs
我想我不够好。3 天前
2026.2.25监控学习
学习
im_AMBER3 天前
Leetcode 127 删除有序数组中的重复项 | 删除有序数组中的重复项 II
数据结构·学习·算法·leetcode
CodeJourney_J3 天前
从“Hello World“ 开始 C++
c语言·c++·学习