(https://docs.nvidia.com/cuda/thrust/index.html)
Thrust 是一个类似于STL的针对CUDA的C++模板库。Trust提供与CUDA C完全兼容的接口,可以使我们高效地编写高性能并行程序。
Thrust提供了丰富的数据并行算法,例如scan、sort、reduce等,可以简单快捷地构成复杂算法,并使得代码获得更高的可读性。使用这些高度抽象的方法来表达计算,可以隐藏细节,并且Trust会自动选择最有效率的算法实现。因此,程序员得以快速构建CUDA程序,并能够获得极高的稳定性和性能与精度。
此文档简述了如何使用Trust开发CUDA程序。即使你的C++与CUDA经验有限,也能够顺利学习该指导。
安装与版本
在安装CUDA Toolkit时,Trust已经被包含你的系统中。因此,已经无需单独安装。
#include <thrust/host_vector.h>
#include <thrust/device_vector.h>
#include <thrust/copy.h>
#include <thrust/fill.h>
#include <thrust/sequence.h>
1.Trust 提供了两个vector容器:host_vector 与 device_vector。按照命名规则,host_vector位于主机端,device_vector位于GPU设备端。Trust的vector容器与STL中的容器类似,是通用的容器,可以存储任何数据类型,可以动态调整大小。
同时有一些自带的向量函数,比如 :
thrust::device_vector<int> D(10, 1);
// set the first seven elements of a vector to 9
thrust::fill(D.begin(), D.begin() + 7, 9);
// initialize a host_vector with the first five elements of D
thrust::host_vector<int> H(D.begin(), D.begin() + 5);
// set the elements of H to 0, 1, 2, 3, ...
thrust::sequence(H.begin(), H.end());
// copy all of H back to the beginning of D
thrust::copy(H.begin(), H.end(), D.begin());
2.Thrust名称空间 :
“thrust::“告诉C++编译器,我们想要查看特定函数或类的Thrust名称空间。名称空间是避免名称冲突的好方法。thrust::copy不同于在STL中提供的std::copy。
3. 迭代器和静态调度
我们使用了诸如H.begin()和H.end()或偏移量之类的表达式,如D.begin()+7。begin()和end()的结果称为C++中的迭代器。在向量容器的例子中,实际上只是数组,迭代器可以被看作是指向数组元素的指针。因此,H.begin()是一个迭代器,它指向存储在H向量中的数组的第一个元素。,H.end()指向元素1,经过H向量的最后一个元素。尽管向量迭代器与指针相似,但它们携带更多的信息。我们不需要告诉Thrust::fill它在device_vector(设备向量)迭代器上操作。当一个Thrust函数被调用时,它会检查迭代器的类型,以确定是否使用主机或设备实现。这个过程被称为静态分派,因为主机/设备分派在编译时解析。这意味着分派过程没有运行时开销。
Thtrust库函数也可以调用 指针,但是与STL一样,推力允许这种用法,它将分派算法的主机路径。如果问题中的指针实际上是一个指向设备内存的指针,那么您需要在调用原函数之前将其包装::deviceptr。
例如: // wrap raw pointer with a device_ptr
thrust::device_ptr<int> dev_ptr(raw_ptr);
如果从设备内存中提取一个常用指针,需要
// extract raw pointer from device_ptr
int * raw_ptr = thrust::raw_pointer_cast(dev_ptr);
区分迭代器和指针的另一个原因是迭代器可以用来遍历许多类型的数据结构。
Thrust库提供了大量的通用并行算法。
注意:虽然常量迭代器和计数迭代器充当数组,但它们实际上并不需要任何内存存储。每当我们取消其中一个迭代器时,它就会动态地生成适当的值,并将其返回给呼叫函数。