这是一个使用 CUDA 进行编程的实际例子,对比 CPU 和 GPU 在执行矩阵乘法时的性能差异。

运行效果

(base) root@gpu-1095cf160ec353b4e35a9-1-zqa76jnvthlx:~/data/CUDA/first# ./gpu_matrix_mult
GPU 执行时间: 0.000475046 秒
(base) root@gpu-1095cf160ec353b4e35a9-1-zqa76jnvthlx:~/data/CUDA/first# ./cpu_matrix_mult 
CPU 执行时间: 14.3784 秒

程序实例

示例:矩阵乘法

矩阵乘法是一个非常适合用 GPU 加速的计算密集型任务。我们将实现一个简单的矩阵乘法,分别在 CPU 和 GPU 上运行,并比较它们的执行时间。

1. CPU 实现 (C++)

#include <iostream>
#include <vector>
#include <chrono>

// CPU 矩阵乘法
std::vector<float> cpuMatrixMult(const std::vector<float>& a, const std::vector<float>& b, int n) {
    std::vector<float> c(n * n, 0.0f);
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            for (int k = 0; k < n; ++k) {
                c[i * n + j] += a[i * n + k] * b[k * n + j];
            }
        }
    }
    return c;
}

int main() {
    int n = 1024; // 矩阵大小
    std::vector<float> a(n * n, 1.0f);
    std::vector<float> b(n * n, 1.0f);

    // 计时开始
    auto start = std::chrono::high_resolution_clock::now();
    std::vector<float> c = cpuMatrixMult(a, b, n);
    auto end = std::chrono::high_resolution_clock::now();
    std::chrono::duration<double> duration = end - start;

    std::cout << "CPU 执行时间: " << duration.count() << " 秒" << std::endl;

    return 0;
}

编译和运行 CPU 代码:

g++ cpu_matrix_mult.cpp -o cpu_matrix_mult
./cpu_matrix_mult

2. GPU 实现 (CUDA)

#include <iostream>
#include <vector>
#include <chrono>
#include <cuda_runtime.h>

// CUDA 核函数
__global__ void gpuMatrixMultKernel(const float* a, const float* b, float* c, int n) {
    int row = blockIdx.y * blockDim.y + threadIdx.y;
    int col = blockIdx.x * blockDim.x + threadIdx.x;

    if (row < n && col < n) {
        float sum = 0.0f;
        for (int k = 0; k < n; ++k) {
            sum += a[row * n + k] * b[k * n + col];
        }
        c[row * n + col] = sum;
    }
}

// GPU 矩阵乘法
std::vector<float> gpuMatrixMult(const std::vector<float>& a, const std::vector<float>& b, int n) {
    std::vector<float> c(n * n, 0.0f);
    float *dev_a, *dev_b, *dev_c;

    // 分配 GPU 内存
    cudaMalloc((void**)&dev_a, n * n * sizeof(float));
    cudaMalloc((void**)&dev_b, n * n * sizeof(float));
    cudaMalloc((void**)&dev_c, n * n * sizeof(float));

    // 将数据从 CPU 复制到 GPU
    cudaMemcpy(dev_a, a.data(), n * n * sizeof(float), cudaMemcpyHostToDevice);
    cudaMemcpy(dev_b, b.data(), n * n * sizeof(float), cudaMemcpyHostToDevice);

    // 定义线程块和网格大小
    int blockSize = 32;
    dim3 blockDim(blockSize, blockSize);
    dim3 gridDim((n + blockSize - 1) / blockSize, (n + blockSize - 1) / blockSize);

    // 计时开始
    auto start = std::chrono::high_resolution_clock::now();

    // 调用 CUDA 核函数
    gpuMatrixMultKernel<<<gridDim, blockDim>>>(dev_a, dev_b, dev_c, n);

    // 等待 GPU 完成
    cudaDeviceSynchronize();

    auto end = std::chrono::high_resolution_clock::now();
    std::chrono::duration<double> duration = end - start;

    // 将结果从 GPU 复制回 CPU
    cudaMemcpy(c.data(), dev_c, n * n * sizeof(float), cudaMemcpyDeviceToHost);

    // 释放 GPU 内存
    cudaFree(dev_a);
    cudaFree(dev_b);
    cudaFree(dev_c);

    std::cout << "GPU 执行时间: " << duration.count() << " 秒" << std::endl;

    return c;
}

int main() {
    int n = 1024; // 矩阵大小
    std::vector<float> a(n * n, 1.0f);
    std::vector<float> b(n * n, 1.0f);

    gpuMatrixMult(a, b, n);

    return 0;
}

编译和运行 CUDA 代码:

  1. 安装 CUDA Toolkit: 确保你已经安装了 CUDA Toolkit,并且设置了正确的环境变量。
  2. 编译:

    nvcc gpu_matrix_mult.cu -o gpu_matrix_mult
  3. 运行:

    ./gpu_matrix_mult

    3. 性能对比分析

通常情况下,你会发现 GPU 的执行时间远小于 CPU 的执行时间,尤其是在矩阵大小 n 较大时。这是因为 GPU 具有大量的并行处理单元,可以同时处理矩阵中的多个元素。

影响性能的因素:

  • 矩阵大小: 矩阵越大,GPU 的优势越明显。
  • GPU 架构: 不同的 GPU 架构具有不同的性能。
  • 线程块大小: 合适的线程块大小可以提高 GPU 的利用率。
  • 内存传输: CPU 和 GPU 之间的数据传输会影响整体性能。

总结

这个例子展示了如何使用 CUDA 加速矩阵乘法。通过将计算任务转移到 GPU 上,可以显著提高程序的性能。请注意,实际的加速效果取决于你的硬件和具体的实现方式。 5

希望这个例子能帮助你入门 CUDA 编程!

最后修改:2025 年 04 月 19 日
如果觉得我的文章对你有用,请随意赞赏