【问题标题】:Reduce by Keys performance using linear index to rows index使用行索引的线性索引降低键性能
【发布时间】:2014-07-01 09:10:25
【问题描述】:

我一直在检查推力示例中的代码 rows_sum.cu,但我无法理解 linear_index_to_rows_index 中到底发生了什么。

谁能用一些例子解释一下将线性索引转换为行索引是什么意思?

参考:https://github.com/thrust/thrust/blob/master/examples/sum_rows.cu

【问题讨论】:

    标签: performance cuda thrust


    【解决方案1】:

    thrust 中,常见的存储格式是矢量容器(例如device_vectorhost_vector)。在典型使用中,这些容器是一维存储格式。 “行”和“列”的概念并不真正适用于一维向量。我们只讨论元素的index。在这种情况下,它是一个线性 (1D) 索引。

    为了存储二维项目,例如矩阵,其中元素的“行”和“列”索引的概念适用,在推力中使用 1D 容器的常见方法是“展平”或“线性化”存储:

    Matrix A:
            column:
            0    1 
    row: 0  1    2
         1  3    4
    
    
    Vector A:
    index:   0    1    2    3
    element: 1    2    3    4
    

    此时,我们可以方便地使用推力操作。但是如果我们想对原始矩阵的特定行或列进行操作呢?当我们将其线性化或展平为一维向量时,该信息(行、列)会“丢失”。但是如果我们知道原始矩阵的维度,我们可以用它来转换线性索引:

      0     1     2     3
    

    进入行/列索引:

    (0,0) (0,1) (1,0) (1,1)
    

    反之亦然(行/列到线性索引)。

    在您链接的推力示例中,仿函数 linear_index_to_row_index 将给定的线性索引转换为其关联的行索引。这允许程序员编写一个对特定数据行起作用的推力操作,例如对原始矩阵的“行”求和,即使它现在存储在线性一维向量中。

    具体来说,当给出以下线性指标时:

      0    1    2    3
    

    对于我的例子,仿函数会返回:

      0    0    1    1
    

    因为表示向量中特定元素所属的原始矩阵的行。

    如果我想将每一行的所有元素加在一起,每行产生一个总和,那么我可以使用该仿函数生成的行索引来标识每个元素的行。此时,reduce_by_key 可以轻松地将具有相同行索引的元素相加,每行产生一个结果。

    【讨论】:

    • 谢谢罗伯特,很好的例子,在同一个函数中,i 的值究竟是多少? T operator()(T i) { return i / C; }
    • i 是传递给函子的线性索引。函子返回线性索引i处的元素所属的对应行(i/C}。
    • 你好罗伯特,回到 rows_sum.cu 的 Reduce_by_keys 实现,我注意到通过这种方式实现也可以获得相同的结果(每列总行数):thrust::counting_iterator第一个(0);推力::counting_iterator last = first + nR; repeat_range<:counting_iterator> > keys(first, last, nC) //列数。获取用作输入的键向量后:thrust_reduce_by_key(key.begin(), key.end(), tempVector.begin(), Vector_indices.begin(), Vector.begin());
    • 使用counting_iterator 提到的这个实现也可以帮助我生成输入键。但是与linear_index_to_row_index相比,计算速度非常慢,实际上或多或少慢了两倍。你知道可能是什么原因吗?是不是使用counting_iterator,实现不知道什么时候停止做reduce,直到找到一个不同的key,并且在linear_index_to_row_index中,它确切地知道什么时候停止reduce?
    • 我相信你偶然发现了一个典型的“融合”优化/比较。这些问题(例如减少)都将在 GPU 上受内存限制。所以较慢的方法首先生成键的向量并将其存储在内存中,然后使用这个生成的向量来选择归约点。如果我们使用函子 (linear_index_to_row_index) “即时”生成密钥向量,则这个两步过程将融合为一个过程,该函子不需要生成(和存储在全局内存中)密钥向量。两步过程大约使内存绑定问题的时间加倍。
    猜你喜欢
    • 2015-03-04
    • 1970-01-01
    • 2012-07-06
    • 2013-09-05
    • 1970-01-01
    • 1970-01-01
    • 2011-02-06
    • 1970-01-01
    • 2016-04-16
    相关资源
    最近更新 更多