vector
Thrust 提供两个向量容器,主机向量和设备向量。主机向量存储在主机内存中,设备向量存储在GPU设备内存中。
Thrust vector 基本操作
元素的访问
int main() {
thrust::host_vector<int> h_arr(4);
for (int i = 0; i < h_arr.size(); i++) {
h_arr[i] = i;
std::cout << h_arr[i] << std::endl;
}
// resize
h_arr.resize(2);
std::cout << "current h_arr size = " << h_arr.size() << std::endl;
thrust::device_vector<int> d_arr = h_arr;
for (int i = 0; i < d_arr.size(); i++) {
d_arr[i] = i;
std::cout << d_arr[i] << std::endl;
}
return 0;
}
如上所示,=运算符可以进行主机向量和设备向量之间的复制。也可以用于主机向量和主机向量之间以及设备向量和设备向量之间的复制。但是对于设备向量来说,使用标准括号访问法的访问需要对每一个访问元素进行cudaMemcpy操作,所以应当谨慎使用。
元素的初始化
int main() {
thrust::host_vector<int> h_arr(10, 1);
for (int i = 0; i < h_arr.size(); i++) std::cout << h_arr[i] << " ";
std::cout << std::endl;
thrust::fill(h_arr.begin(), h_arr.end(), 6);
for (int i = 0; i < h_arr.size(); i++) std::cout << h_arr[i] << " ";
std::cout << std::endl;
thrust::device_vector<int> d_arr(h_arr.begin(), h_arr.begin() + 5);
for (int i = 0; i < d_arr.size(); i++) std::cout << d_arr[i] << " ";
std::cout << std::endl;
thrust::sequence(d_arr.begin(), d_arr.end());
for (int i = 0; i < d_arr.size(); i++) std::cout << d_arr[i] << " ";
std::cout << std::endl;
return 0;
}
对于上述代码中使用到的迭代器,我们不必去在乎运行的是设备迭代器还是主机迭代器,在返回的迭代器中会对其进行类型的检查以确定是主机实现还是设备实现。这样的做法叫做静态分派,即在编译时进行解决,整个分派过程没有运行时开销。
原始指针和设备指针相互转换
原始指针作为参数传递给设备指针
size_t N = 10;
// raw pointer to device memory
int * raw_ptr;
cudaMalloc((void **) &raw_ptr, N * sizeof(int));
// wrap raw pointer with a device_ptr
thrust::device_ptr<int> dev_ptr(raw_ptr);
// use device_ptr in thrust algorithms
thrust::fill(dev_ptr, dev_ptr + N, (int) 0);
设备指针中提取原始指针
size_t N = 10;
// create a device_ptr
thrust::device_ptr<int> dev_ptr = thrust::device_malloc<int>(N);
// extract raw pointer from device_ptr
int * raw_ptr = thrust::raw_pointer_cast(dev_ptr);
迭代器的用途很广泛,可以在很多数据结构之间进行数据传送。下面的代码示例中,介绍了用list元素初始化vector元素,以及用device vector元素初始化std::vector元素:
#include <thrust/device_vector.h>
#include <thrust/host_vector.h>
#include <iostream>
#include <list>
#include <vector>
int main() {
std::list<int> stl_list;
stl_list.push_back(10);
stl_list.push_back(20);
stl_list.push_back(30);
stl_list.push_back(40);
thrust::device_vector<int> d_arr(stl_list.begin(), stl_list.end());
for (auto it : d_arr) std::cout << it << " ";
std::cout << std::endl;
std::vector<int> stl_arr(d_arr.size());
thrust::copy(d_arr.begin(), d_arr.end(), stl_arr.begin());
for (auto it : stl_arr) std::cout << it << " ";
std::cout << std::endl;
// result:
// 10 20 30 40
// 10 20 30 40
return 0;
}