当前位置: 首页 > 工具软件 > Thrust > 使用案例 >

Thrust库理解

鲁泰宁
2023-12-01

 

(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已经被包含你的系统中。因此,已经无需单独安装。

  • Vector(向量)

    #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);

区分迭代器和指针的另一个原因是迭代器可以用来遍历许多类型的数据结构。

  • Algorithms(算法) (thrust/functional.h)

Thrust库提供了大量的通用并行算法。

  1. 许多这样的算法在STL中有直接的类似物,当一个等价的STL函数存在时,我们选择名称。(e.g. thrust::sort and std::sort).
  2. 所有的算法都有对主机和设备的实现。当Thrust算法被主机迭代器调用时,就会发送主机路径。当设备迭代器被用来定义一个范围时,就会调用设备实现。所以区别在于 :迭代器。
  3. 除了Thrust::copy,它可以在主机和设备之间复制数据,所有的迭代器参数都应该在同一个地方:要么全部在主机上,要么在设备上。
  • Fancy Iterators(高级迭代器)
  1. constant_iterator(常量迭代器):返回常数值。
  2. counting_iterator (计算迭代器):一个递增的值序列。

注意:虽然常量迭代器和计数迭代器充当数组,但它们实际上并不需要任何内存存储。每当我们取消其中一个迭代器时,它就会动态地生成适当的值,并将其返回给呼叫函数。

  1. transform iterator(变换迭代器):没理解,感觉是用于数学计算的,但是用法多样。
  2. permutation_iterator(排列迭代器):或者说是匹配迭代器
  3. zip_iterator(压缩迭代器):重点,允许我们将许多独立的序列组合成一个单一的元组序列,这可以由一组广泛的算法来处理。
 类似资料: