Thrust 是构建在 CUDA Runtime 之上的高层模板库,类似 STL 但支持 GPU 和 CPU 双后端;它自动分发操作到对应后端,无需手写 kernel 或显式内存拷贝,但需正确使用设备容器或 device_ptr。

Thrust 是什么,它和 CUDA Runtime 什么关系
Thrust 不是 CUDA 的替代品,而是构建在 CUDA Runtime 之上的高层模板库,类似 STL 但支持设备(GPU)和主机(CPU)双后端。你写 thrust::sort,它会自动判断迭代器指向的是 thrust::device_vector 还是 thrust::host_vector,再调用对应后端(cub::DeviceSegmentedSort 或 std::sort)。不需要手写 kernel,也不用显式调用 cudaMemcpy——前提是数据容器本身已绑定到正确内存空间。
排序:thrust::sort 必须用 thrust::device_vector 才真跑 GPU
常见错误是把 std::vector 直接传给 thrust::sort,结果掉回 CPU 执行且无警告。必须显式使用设备容器:
thrust::device_vector<int> d_vec = {5, 2, 8, 1};
thrust::sort(d_vec.begin(), d_vec.end()); // 真正在 GPU 上排序
- 不能对裸指针(如
int*)直接调用thrust::sort,除非用thrust::device_ptr包装:thrust::sort(thrust::device_ptr<int>(d_ptr), thrust::device_ptr<int>(d_ptr + n))</int></int> -
thrust::sort默认升序;降序需传thrust::greater<int>()</int>作为第三个参数 - 若数据已在 GPU 显存中(比如来自其他 kernel 输出),优先用
thrust::device_ptr包装,避免拷贝到thrust::device_vector再拷出
归约:注意 thrust::reduce 的返回值在主机还是设备内存
thrust::reduce 的结果默认存储在主机内存——即使输入是 thrust::device_vector。这是最容易被忽略的隐式同步点:
thrust::device_vector<int> d_vec = {1, 2, 3, 4};
int sum = thrust::reduce(d_vec.begin(), d_vec.end()); // sum 是 host int,此处隐式同步
- 如果后续还要在 GPU 上继续计算(比如用这个 sum 做归一化),别直接取
sum,改用thrust::device_vector<int> result(1)</int>+thrust::reduce(..., result.begin()),保持全程在设备侧 - 不指定二元操作符时默认用
operator+;自定义操作(如求最大值)要传thrust::maximum<int>()</int> - 对大型向量,
thrust::reduce比手写 reduce kernel 更快,因它内部使用 CUB 优化过的分块归约,但小数组(
编译与链接:头文件够了,但必须链接 -lcudart
Thrust 是纯头文件库,不需要单独编译,但依赖 CUDA Runtime。仅 #include <thrust></thrust> 不足以让链接通过:
立即学习“C++免费学习笔记(深入)”;
- nvcc 编译时必须加
-lcudart(否则报 undefined reference tocudaMalloc等) - 不能用 g++ 直接编译含 Thrust 的 .cpp 文件——即使没写 kernel,Thrust 模板实例化后仍会生成 CUDA Runtime 调用,必须走
nvcc - 若混用 C++17 特性(如
if constexpr),确保 nvcc 版本 ≥ 11.0,并加-std=c++17
设备端算法看似“像 STL”,但内存域、同步点、编译链这些底层契约一点都不能松动。最常卡住的地方不是语法,而是误以为 thrust:: 前缀能自动解决所有 GPU 适配问题。


















