给定元素数组、子列表的偏移量和长度的有效部分约简
Efficient partial reductions given arrays of elements, offsets to and lengths of sublists
对于我的应用程序,我必须处理一堆对象(比如int
s),这些对象随后被划分并排序到更小的桶中。为此,我将元素存储在单个连续阵列中
arr = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14...}
并且关于桶(子列表)的信息通过对相应桶中的第一元素的偏移和子列表的长度来给出。
例如,给定
offsets = {0,3,8,..}
sublist_lengths = {3,5,2,...}
将导致以下分裂:
0 1 2 || 3 4 5 6 7 || 8 9 || ...
我正在寻找一种通用而高效的方法,只使用自定义内核或thrust
库在bucket上运行算法,如reduction。桶的总和应给出:
3 || 25 || 17 || ...
我想到了什么:
选项1:自定义内核需要大量的修补、复制到共享内存、正确选择块和网格大小以及自己的算法实现,如扫描、减少等。此外,每个操作都需要自己的自定义内核。一般来说,我很清楚如何做到这一点,但在过去几天使用
thrust
后,我觉得可能有一种更聪明的方法选项2:根据偏移量(上例中为
{0,0,0,1,1,1,1,1,2,2,3,...}
)生成一个键数组,并使用thrust::reduce_by_key
。不过,我不喜欢额外生成列表。选项3:使用
thrust::transform_iterator
和thrust::counting_iterator
来动态生成上述给定的密钥列表。不幸的是,我无法想出一个不需要对设备上的偏移列表增加索引并破坏并行性的实现。
实现这一点最明智的方法是什么?
在Thrust中,我想不出比选项2更好的解决方案了。性能不会很糟糕,但肯定不是最佳的。
您的数据结构与用于存储稀疏矩阵的压缩稀疏行(CSR)格式相似,因此如果您想要更好的性能,可以使用为计算此类矩阵的稀疏矩阵向量乘(SpMV)而开发的技术。请注意,CSR格式的"offset"数组的长度为(N+1),用于具有N行的矩阵(在您的情况下为bucket),其中最后一个偏移值为arr
的长度。Cusp中的CSR-SpMV代码有点复杂,但它是内核的一个很好的起点。只需从代码中删除对Aj
或x
的任何引用,并将offsets
和arr
分别传递到Ap
和Av
自变量中。
您没有提到水桶有多大。如果bucket足够大,也许您可以将偏移量和sublist_length复制到主机,对它们进行迭代,并为每个bucket执行单独的Thrust调用。费米可以同时有16个内核在飞行,所以在这种架构中,你可能能够处理更小的桶,并且仍然可以获得良好的利用率。
- 有没有办法将谓词中的元素偏移量传递给 std 算法?
- 通过指针偏移量访问结构变量值
- 以线程安全的方式转换 C/C++ 中时区名称字符串的时区偏移量
- librdkafka:rd_kafka_assignment 返回分配分区的偏移量 -1001
- 是否通过向封闭对象的地址添加字节偏移量来访问子对象
- 向指针地址添加 20 个字节偏移量
- glMapBufferRange(..) 中的偏移量关系和 glDrawArraysInstanced(..) 中的第一
- 是否有与 C# Structs/StructLayout 等效的功能,C++中的字段偏移量?
- 我的 sumASCII 函数中的此偏移量是多少?
- boost::序列化中的派生类偏移量计算.有效吗?
- RedisGraph 语法错误在偏移量 8 靠近"创建"
- 胎面偏移量的时间复杂度?
- 如何从 c++ 中的给定标准输入中获取每个字符的偏移量?
- 编译器在构造函数中计算的成员偏移量不正确
- 使用基地址和偏移量获取变量的地址
- c++ 读取进程内存基址 + 偏移量不起作用
- 通过其在 C 中的偏移量调用函数
- C++ 将部分数组(在某些偏移量)转换为其他类型
- 给定元素数组、子列表的偏移量和长度的有效部分约简
- 这是有效的 ANSI C++代码吗?尝试在编译时生成结构成员的偏移量