由于Thrust库存在一些性能问题(有关详细信息,请参阅this page),我计划将CUDA应用程序重新分解为使用CUB而不是Thrust。具体来说,要替换thrust :: sort_by_key和thrust :: inclusive_scan调用)。在我的应用程序的特定点,我需要按键排序3个数组。这就是我用推力做到这一点的方式:
thrust::sort_by_key(key_iter, key_iter + numKeys, indices);
thrust::gather_wrapper(indices, indices + numKeys,
thrust::make_zip_iterator(thrust::make_tuple(values1Ptr, values2Ptr, values3Ptr)),
thrust::make_zip_iterator(thrust::make_tuple(valuesOut1Ptr, valuesOut2Ptr, valuesOut3Ptr))
);
其中
key iter
是一个thrust :: device_ptr,指向我想要排序的键indices
指向设备内存中的序列(从0到numKeys-1)values{1,2,3}Ptr
是我想要排序的值values{1,2,3}OutPtr
是排序值使用CUB SortPairs函数,我可以对单个值缓冲区进行排序,但不能一次性对所有3个缓冲区进行排序。问题是我没有看到任何CUB“类似聚集”的实用程序。建议?
编辑:
我想我可以实现自己的聚集内核,但是有更好的方法可以做到这一点:
template <typename Index, typename Value>
__global__ void gather_kernel(const unsigned int N, const Index * map,
const Value * src, Value * dst)
{
unsigned int i = blockDim.x * blockIdx.x + threadIdx.x;
if (i < N)
{
dst[i] = src[map[i]];
}
}
非coalesed加载和存储让我感到愤怒,但如果没有map
上的已知结构,它可能是不可避免的。
答案 0 :(得分:4)
您希望实现的目标取决于thrust::zip_iterator
。你可以
thrust::sort_by_key
替换为cub::DeviceRadixSort::SortPairs
并保留thrust::gather
或values{1,2,3}
之前,cub::DeviceRadixSort::SortPairs
到结构数组中
醇>
阅读thrust::gather
的实施,
$CUDA_HOME/include/thrust/system/detail/generic/gather.inl
你可以看到它只是一个天真的内核,如
__global__ gather(int* index, float* in, float* out, int len) {
int i=...;
if (i<len) { out[i] = in[index[i]]; }
}
然后我认为上面的代码可以用一个内核替换而不需要太多努力。
在这个内核中,您可以首先使用CUB block-wize原语cub::BlockRadixSort<...>::SortBlockedToStriped
来获取存储在寄存器中的已排序索引,然后执行一个天真的重新排序副本thrust::gather
来填充{{1} }}
复制values{1,2,3}Out
时,使用SortBlockedToStriped
而非Sort
可以进行合并写入(不是为了阅读)。