Cuda Thrust获得分段中的前一个元素
Cuda Thrust get previous element in a segment
我有一个值向量和键向量(表示段)
v = [1, 1, 1, 2, 3, 5, 6]
k = [0, 0, 1, 1, 0, 2, 2]
对于每个元素,我想知道它的前一个元素(在同一段)。它可以是值,也可以是原向量的下标。
所以结果应该是(对于value)
r = [nan, 1, nan, 1, 1, nan, 5]
你可以使用任何元素代替nan
,对于算法的剩余部分没有关系。
也许我可以存档它与独家分段扫描和max
操作,而不是sum
。两个问题:
- 我的进近正确吗?
- 有更优雅或更有效的解决方案吗?
所需的功能可以通过以下步骤实现:
-
按
k
排序v
以获得相邻相等的键值;这必须通过stable_sort_by_key
来完成,因为您想要检索"前一个"元素,因此必须保留具有相等键的元素之间的顺序。 -
对排序后的数据应用以下转换:
if (previous element has the same key)
then return value of previous element
else
return -1
以下代码实现了这些步骤:
#include <cstdint>
#include <iostream>
#include <thrust/host_vector.h>
#include <thrust/device_vector.h>
#include <thrust/sort.h>
#include <thrust/transform.h>
#include <thrust/iterator/counting_iterator.h>
#include <thrust/iterator/zip_iterator.h>
#define PRINTER(name) print(#name, (name))
template <template <typename...> class V, typename T, typename ...Args>
void print(const char* name, const V<T,Args...> & v)
{
std::cout << name << ":t";
thrust::copy(v.begin(), v.end(), std::ostream_iterator<T>(std::cout, "t"));
std::cout << std::endl;
}
template<typename... Iterators>
__host__ __device__
thrust::zip_iterator<thrust::tuple<Iterators...>> zip(Iterators... its)
{
return thrust::make_zip_iterator(thrust::make_tuple(its...));
}
template <typename IteratorType, typename Integer>
struct prev_value
{
prev_value(IteratorType first) : first(first){}
template <typename Tuple>
__host__ __device__
Integer operator()(const Tuple& t)
{
const auto& index = thrust::get<0>(t);
const auto& previousValue = thrust::get<1>(t);
Integer result = -1;
const auto& currentKey = *(first+index);
const auto& previousKey = *(first+index-1);
if(currentKey == previousKey)
{
result = previousValue;
}
return result;
}
IteratorType first;
};
template <typename Integer, typename IteratorType>
prev_value<IteratorType, Integer> make_prev_value(IteratorType first)
{
return prev_value<IteratorType, Integer>(first);
}
int main(int argc, char** argv)
{
using Integer = std::int32_t;
using HostVec = thrust::host_vector<Integer>;
using DeviceVec = thrust::device_vector<Integer>;
Integer v[] = {1, 1, 1, 2, 3, 5, 6};
Integer k[] = {0, 0, 1, 1, 0, 2, 2};
Integer size = sizeof(k)/sizeof(k[0]);
HostVec h_k(k, k+size);
HostVec h_v(v, v+size);
// copy data to device
DeviceVec d_k = h_k;
DeviceVec d_v = h_v;
std::cout << "---- input data ----" << std::endl;
PRINTER(d_k);
PRINTER(d_v);
thrust::stable_sort_by_key(d_k.begin(), d_k.end(), d_v.begin());
std::cout << "---- after sorting ----" << std::endl;
PRINTER(d_k);
PRINTER(d_v);
DeviceVec d_r(size, -1);
auto op = make_prev_value<Integer>(d_k.begin());
thrust::transform(zip(thrust::make_counting_iterator(Integer(1)), d_v.begin()),
zip(thrust::make_counting_iterator(size), d_v.end()),
d_r.begin()+1,
op);
std::cout << "---- result ----" << std::endl;
PRINTER(d_r);
return 0;
}
输出:---- input data ----
d_k: 0 0 1 1 0 2 2
d_v: 1 1 1 2 3 5 6
---- after sorting ----
d_k: 0 0 0 1 1 2 2
d_v: 1 1 3 1 2 5 6
---- result ----
d_r: -1 1 1 -1 1 -1 5
相关文章:
- lower_bound()返回最后一个元素
- 使用std::transform将一个范围的元素添加到另一个范围中
- 我想访问std::unique_ptr中的一个特定元素
- 基于范围的 for 循环:迭代使用一个元素扩展的向量
- 使用运算符 [] 引用 std::vector 上最后一个元素时出现问题<>
- 删除映射和分割错误中的一个过去结束元素
- Lower_bound不适用于具有 3 个元素的向量的最后一个元素
- 查找数组中第一个最小值和最后一个最大值元素之间的算术平均值
- 检查 2D 网格的某个元素是否与另一个元素共享对角线、水平线或垂直线
- 如何创建一个所有行大小不同的 2D 数组,并且用户将指定每行将有多少个元素?
- 仅显示链表的最后一个元素
- 为什么在 std::map 上移动无法将元素从一个映射移动到另一个映射
- 查找最小的下一个更大的元素
- push_back通过自行创建的对象获取最后一个元素的向量
- 使用 map.end() 访问 map 的最后一个元素
- 如何知道地图中的最后一个元素是否被删除?
- 选择一个元素而不是一个对象的数组的原因
- std::矢量保存 只推送最后一个元素
- 为什么这个选择排序算法仍然切换一个元素,当它已经是其他元素中最小的元素时?
- 动态分配列表 - 创建一个函数,用于删除所有包含偶数值的元素