在现代深度学习框架中,CPU与GPU之间的协同工作已成为标准做法。C++作为底层语言,在性能关键部件中占据重要位置。本文将介绍如何在C++项目中使用CUDA库,对张量运算进行加速,并给出完整的代码示例与最佳实践。
-
环境准备
- CUDA Toolkit 12.x(或对应版本)
- cuBLAS、cuDNN(可选)
- CMake 3.18+
- 支持NVCC的编译器(gcc、clang、MSVC等)
-
项目结构
tensor-cuda/ ├── CMakeLists.txt ├── src/ │ ├── main.cpp │ ├── tensor.hpp │ └── tensor.cu └── include/ └── tensor.hpp -
关键代码
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)
-
编译与运行
mkdir build && cd build cmake .. -DCMAKE_BUILD_TYPE=Release make -j$(nproc) ./tensor_demo -
性能优化要点
- 内存对齐:使用
cudaMallocPitch或cudaMallocManaged进行对齐,提升内存访问效率。 - 核函数优化:根据 GPU 架构选择合适的线程块尺寸(例如 32 或 64 的倍数),避免 warp 资源浪费。
- 流并行:使用
cudaStream_t并行执行多个核函数,减少 CPU 等待时间。 - cuBLAS 接口:在实际项目中,可以直接调用
cublasSgemm进行矩阵乘法,性能更优。
- 内存对齐:使用
-
进一步阅读
- 《CUDA by Example》
- 《深入理解 C++ 20 并行 STL》
- 官方 cuBLAS 文档
通过上述示例,你可以在 C++ 项目中轻松实现 GPU 加速的张量运算,为深度学习模型训练和推理提供强大支持。