前言
在这篇技术文章中,我将分享我自己成立开发并综合实战经验的开源项目 CUDA-PyCPP-Kit,它是一套面向高性能计算开发者的入门工具集,支持 Python 与 C++/CUDA 混合编程。我经常在实际项目中需要对同样的算法进行 CPU 与 GPU 效能对比,且需要快速原型验证、无缝集成 Python 数据模型系统。CUDA-PyCPP-Kit 刚好是一套能够解决这类需求的体系化设计。
一、项目架构分析
整个 CUDA-PyCPP-Kit 采用分层化、模块化设计,便于维护和扩展。
项目根目录含有如下文件和模块:
CUDA-PyCPP-Kit/
├── bench.py # pytest-benchmark 培育性能对比脚本
├── benchmark_cpu.py # CPU 端矩阵算法效能对比
├── cpu_extension.*.so # pybind11 组合编译的 CPU 扩展
├── gpu_extension.*.so # GPU 扩展模块 (CUDA kernel)
├── helloCPU.cpp # CPU 模拟程序进入
├── main.cpp / mainCPU.cpp # 各端入口
├── matrix_mul.cpp # C++ 矩阵乘法实现
├── starter_kit.cu # CUDA 核心 kernel 文件
├── starter_kit_baseline.py # Python 基准结果对照
├── testCPU.py # CPU 模块测试
├── setupCPU.py # CPU 扩展编译 script
├── requirements-*.txt # 环境依赖
└── README.md
CPU 和 GPU 部分分别独立编译、封装成 Python 可调用扩展,通过 pybind11 进行互操,大大降低了开发门槛和维护成本。
二、Python 与 C++ 融合设计
1. pybind11 封装实现
通过 pybind11,我们可以将 C++ 端算法与 Python 方便经典的数据组织 (numpy.array) 无障连接,示例为一个 CPU 矩阵乘法实现:
#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>
pybind11::array_t<float> matmul(
const pybind11::array_t<float>& a,
const pybind11::array_t<float>& b);
PYBIND11_MODULE(cpu_extension, m) {
m.doc() = "高效 CPU 扩展: 矩阵乘法";
m.def("matmul", &matmul, "矩阵 A*B");
}
Python 端即可通过 import cpu_extension 与内部函数进行操作,无需手动绑定程序控制。
2. 编译脚本
为了便于性能对比,CPU 和 GPU 分别组装成独立扩展,编译脚本示例:
# setupCPU.py
from setuptools import setup
from pybind11.setup_helpers import Pybind11Extension, build_ext
ext_modules = [
Pybind11Extension(
"cpu_extension",
["mainCPU.cpp", "matrix_mul.cpp"],
)
]
setup(
name="cpu_hello",
ext_modules=ext_modules,
cmdclass={"build_ext": build_ext},
)
GPU 部分前提是您已配置 CUDA toolchain,算法核心部分即在 .cu 文件中编写,通过 nvcc 编译后同样与 Python 融合。
三、GPU 加速核心实现
我在项目中提供了 CUDA 封装核心 kernel,实现基础矩阵乘法,通过 grid/block/threadIdx 分组,实现 GPU 线程展开。
__global__ void matmul_kernel(float* A, 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 接口通过 pybind11 进行封装,使用 Python 可直接调用 GPU 进行矩阵乘法操作,在大规模系列中显著提升运行效率。
四、CPU/GPU 性能对比
我通过 benchmark.py 进行了分别对 CPU 和 GPU 矩阵操作进行比较,这个脚本初始化 256~2048 大小的矩阵,分别操作后应用 time 进行效能对比,结果示意,GPU 在大型矩阵上优势明显,但在小型操作上原因于数据传输负担,表现未必优越。
示例输出:
矩阵大小: 1024 x 1024
CPU 耗时:1.31 秒
GPU 耗时:0.09 秒
最大误差: 0.00004
五、应用场景和扩展
这套工具集初期目标是用于性能培育、实验效果对比,但通过模块化设计,我们可以无障扩展到如下场景:
-
AI 深度学习预处理系统、前后端运算对比
-
智能工程方式形式化实现
-
培训环境下的内部实验评估
-
多编译器、多运行平台 CPU/GPU 并行模拟
六、实际操作指南
环境配置
-
Python 3.7+
-
pybind11, numpy, pytest
-
CUDA 11.x+ (如需支持 GPU)
-
nvcc / clang++ 支持 c++17
-
测专可在本地落地测试开发完成
-
CPU 部分,Mac M 系列晶片可运行
第一個 Hello World
6.1 hello.cpp
#include <iostream>
void hello() {
std::cout << "Hello from C++!" << std::endl;
}
6.2 mainCPU.cpp(用 pybind11 封裝)
#include <pybind11/pybind11.h>
void hello_from_cpu(int n);
PYBIND11_MODULE(cpu_extension, m) {
m.def("hello", &hello_from_cpu, "Print Hello from CPU multiple times");
}
6.3 setup.py(编译 pybind11 扩展模块)
from setuptools import setup
from pybind11.setup_helpers import Pybind11Extension, build_ext
ext_modules = [
Pybind11Extension(
"cpu_extension",
["hello.cpp", "helloCPU.cpp"],
),
]
setup(
name="cpu_extension",
version="1.0",
ext_modules=ext_modules,
cmdclass={"build_ext": build_ext},
)
6.4 test.py(Python 调用测试)
import cpu_extension
print("Launching CPU Hello...")
cpu_extension.hello()
cpu_extension.hello_from_cpu(3)
print("Done.")
5. 编译 CPU 模块
python setupCPU.py build_ext --inplace
- 专案文件 build 会产出 cpu_extension.cpp 对应的是单一 .so 模组
6. 测试 CPU
python testCPU.py
Launching CPU Hello...
Hello from C++!
Hello from CPU #1
Hello from CPU #2
Hello from CPU #3
Done.
七、加大力度,针对 CPU RAM 进行矩阵运算,测试结果
7.1 matrix_mul.cpp
#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>
#include <vector>
#include <chrono>
namespace py = pybind11;
// 矩陣乘法 (Naive + 多執行緒可以加強)
py::array_t<float> matmul(const py::array_t<float>& a, const py::array_t<float>& b) {
auto buf_a = a.request(), buf_b = b.request();
if (buf_a.ndim != 2 || buf_b.ndim != 2 || buf_a.shape[1] != buf_b.shape[0])
throw std::runtime_error("形狀不符合乘法規則");
ssize_t M = buf_a.shape[0];
ssize_t K = buf_a.shape[1];
ssize_t N = buf_b.shape[1];
auto result = py::array_t<float>({M, N});
auto buf_r = result.mutable_unchecked<2>();
auto ptr_a = static_cast<float*>(buf_a.ptr);
auto ptr_b = static_cast<float*>(buf_b.ptr);
for (ssize_t i = 0; i < M; ++i) {
for (ssize_t j = 0; j < N; ++j) {
float sum = 0.0f;
for (ssize_t k = 0; k < K; ++k) {
sum += ptr_a[i * K + k] * ptr_b[k * N + j];
}
buf_r(i, j) = sum;
}
}
return result;
}
7.2 测试 GPU 與 CPU
python -c "import gpu_extension; print(gpu_extension.matmul)"
7.3 benchmark_cpu.py
import time
import numpy as np
import cpu_extension
def run_numpy_matmul(A, B):
start = time.time()
C = np.dot(A, B)
return C, time.time() - start
def run_cpp_matmul(A, B):
start = time.time()
C = cpu_extension.matmul(A, B)
return C, time.time() - start
def benchmark(size):
A = np.random.rand(size, size).astype(np.float32)
B = np.random.rand(size, size).astype(np.float32)
print(f"\n🔹 測試矩陣大小: {size} x {size}")
C_np, time_np = run_numpy_matmul(A, B)
print(f" NumPy dot 耗時:{time_np:.4f} 秒")
C_cpp, time_cpp = run_cpp_matmul(A, B)
print(f" C++ matmul 耗時:{time_cpp:.4f} 秒")
diff = np.max(np.abs(C_np - C_cpp))
print(f" 結果最大誤差:{diff:.6f}")
if __name__ == "__main__":
for size in [256, 512, 1024]:
benchmark(size)
7.4 執行
python benchmark_cpu.py
7.5 输出
🔹 測試矩陣大小: 256 x 256
NumPy dot 耗時:0.0017 秒
C++ matmul 耗時:0.0157 秒
結果最大誤差:0.000000
🔹 測試矩陣大小: 512 x 512
NumPy dot 耗時:0.0009 秒
C++ matmul 耗時:0.1493 秒
結果最大誤差:0.000000
🔹 測試矩陣大小: 1024 x 1024
NumPy dot 耗時:0.0018 秒
C++ matmul 耗時:1.3106 秒
結果最大誤差:0.000000
开源地址
🧾 GitCode 開源項目地址:
👉 GitCode - 全球开发者的开源社区,开源代码托管平台
结言
这项工程在我开发过程中,重点规划了较体系化的 CPU/GPU 性能对比培训环境,以及便于后续扩展算法模块。这应该是一套合适开发者、经验者应用、教学实验和研究专题通用的基础工具。
我是一位独立开发者,加入使用者社群,一起讨论私有化 LLM 与 RAG 架构实践,欢迎 Star、Fork、Issue 交流。