Thrust库可用于对数据进行排序。调用可能看起来像这样(带有键和值向量):
thrust::sort_by_key(d_keys.begin(), d_keys.end(), d_values.begin());
在CPU上调用,d_keys
和d_values
在CPU内存中;并且大部分执行都发生在GPU上。
但是,我的数据已经在GPU上?如何使用Thrust库直接在GPU上执行高效排序,即从内核调用sort_by_key
函数?
此外,我的数据包含其中的键
unsigned long long int
或unsigned int
以及始终为unsigned int
的数据。我应该如何对这些类型进行推力调用?
答案 0 :(得分:8)
如Talonmies链接的问题所述,您无法通过CUDA函数调用Thrust(例如__device__
或__global__
)。但是,这并不意味着您不能使用Thrust使用设备内存中已有的数据。而是使用包裹原始数据的Thrust向量从主机调用所需的Thrust函数。 e.g。
//raw pointer to device memory
unsigned int * raw_data;
unsigned int * raw_keys;
//allocate device memory for data and keys
cudaMalloc((void **) &raw_data, N_data * sizeof(int));
cudaMalloc((void **) &raw_keys, N_keys * sizeof(int));
//populate your device pointers in your kernel
kernel<<<...>>>(raw_data, raw_keys, ...);
...
//wrap raw pointer with a device_ptr to use with Thrust functions
thrust::device_ptr<unsigned int> dev_data_ptr(raw_data);
thrust::device_ptr<unsigned int> dev_keys_ptr(raw_keys);
//use the device memory with a thrust call
thrust::sort_by_key(d_keys, d_keys + N_keys, dev_data_ptr);
raw_data
和raw_keys
指向的设备内存在用Thrust::device_ptr
包装时仍然在设备内存中,所以当你从主机调用Thrust函数时,它不必将任何内存从主机复制到设备,反之亦然。也就是说,您使用设备内存直接在GPU上进行排序;你唯一的开销就是启动Thrust内核并包装原始设备指针。
当然,如果你需要在之后的常规CUDA内核中使用它们,你可以得到你的原始指针:
unsigned int * raw_ptr = thrust::raw_pointer_cast(dev_data_ptr);
至于使用unsigned long long int
或unsigned int
作为unsigned int
数据的密钥,这不是问题,因为Thrust是模板化的。也就是说,sort_by_key
的签名是
template<typename RandomAccessIterator1 , typename RandomAccessIterator2 >
void thrust::sort_by_key(
RandomAccessIterator1 keys_first,
RandomAccessIterator1 keys_last,
RandomAccessIterator2 values_first )
意味着您可以为键和数据设置不同的类型。只要您的所有键类型对于给定的调用都是同质的,Thrust应该能够自动推断类型,并且您不必执行任何特殊操作。希望这是有道理的