深度学习中的C++实现:如何使用CUDA加速张量运算

在现代深度学习框架中,CPU与GPU之间的协同工作已成为标准做法。C++作为底层语言,在性能关键部件中占据重要位置。本文将介绍如何在C++项目中使用CUDA库,对张量运算进行加速,并给出完整的代码示例与最佳实践。

  1. 环境准备

    • CUDA Toolkit 12.x(或对应版本)
    • cuBLAS、cuDNN(可选)
    • CMake 3.18+
    • 支持NVCC的编译器(gcc、clang、MSVC等)
  2. 项目结构

    tensor-cuda/
    ├── CMakeLists.txt
    ├── src/
    │   ├── main.cpp
    │   ├── tensor.hpp
    │   └── tensor.cu
    └── include/
     └── tensor.hpp
  3. 关键代码

tensor.hpp

#pragma once
#include <vector>
#include <cuda_runtime.h>

class Tensor {
public:
    Tensor(const std::vector <int>& shape);
    ~Tensor();

    float* device_ptr() const { return d_data_; }
    const std::vector <int>& shape() const { return shape_; }

    // 简单的矩阵乘法示例
    static Tensor matmul(const Tensor& a, const Tensor& b);

private:
    std::vector <int> shape_;
    float* d_data_;
};

tensor.cu

#include "tensor.hpp"
#include <iostream>

__global__ void matmul_kernel(const float* a, const float* b, float* c,
                              int M, int N, int K) {
    int row = blockIdx.y * blockDim.y + threadIdx.y;
    int col = blockIdx.x * blockDim.x + threadIdx.x;
    if (row < M && col < N) {
        float sum = 0.0f;
        for (int i = 0; i < K; ++i)
            sum += a[row * K + i] * b[i * N + col];
        c[row * N + col] = sum;
    }
}

Tensor Tensor::matmul(const Tensor& a, const Tensor& b) {
    assert(a.shape().size() == 2 && b.shape().size() == 2);
    int M = a.shape()[0], K = a.shape()[1];
    int N = b.shape()[1];
    Tensor result({M, N});

    dim3 blockSize(16, 16);
    dim3 gridSize((N + blockSize.x - 1) / blockSize.x,
                  (M + blockSize.y - 1) / blockSize.y);
    matmul_kernel<<<gridSize, blockSize>>>(a.device_ptr(), b.device_ptr(),
                                           result.device_ptr(), M, N, K);
    cudaDeviceSynchronize();
    return result;
}

main.cpp

#include "tensor.hpp"
#include <iostream>

int main() {
    Tensor A({2, 3});
    Tensor B({3, 4});

    // 这里略过数据初始化,假设已在 GPU 端填充数据
    Tensor C = Tensor::matmul(A, B);

    std::cout << "矩阵乘法完成,结果形状为 (" << C.shape()[0] << ", " << C.shape()[1] << ")\n";
    return 0;
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.18)
project(TensorCUDA LANGUAGES CXX CUDA)

set(CMAKE_CXX_STANDARD 17)
find_package(CUDA REQUIRED)

add_library(tensor SHARED
    src/tensor.cpp
    src/tensor.cu
)

target_include_directories(tensor PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
target_link_libraries(tensor PUBLIC CUDA::cudart)

add_executable(tensor_demo src/main.cpp)
target_link_libraries(tensor_demo PUBLIC tensor)
  1. 编译与运行

    mkdir build && cd build
    cmake .. -DCMAKE_BUILD_TYPE=Release
    make -j$(nproc)
    ./tensor_demo
  2. 性能优化要点

    • 内存对齐:使用 cudaMallocPitchcudaMallocManaged 进行对齐,提升内存访问效率。
    • 核函数优化:根据 GPU 架构选择合适的线程块尺寸(例如 32 或 64 的倍数),避免 warp 资源浪费。
    • 流并行:使用 cudaStream_t 并行执行多个核函数,减少 CPU 等待时间。
    • cuBLAS 接口:在实际项目中,可以直接调用 cublasSgemm 进行矩阵乘法,性能更优。
  3. 进一步阅读

    • 《CUDA by Example》
    • 《深入理解 C++ 20 并行 STL》
    • 官方 cuBLAS 文档

通过上述示例,你可以在 C++ 项目中轻松实现 GPU 加速的张量运算,为深度学习模型训练和推理提供强大支持。

发表评论