【问题标题】:How to reduce nonconsecutive segments of numbers in array with Thrust如何使用 Thrust 减少数组中不连续的数字段
【发布时间】:2019-04-27 21:34:51
【问题描述】:

我有一个一维数组“A”,它由许多数组“a”组成,如下所示:

我正在实现一个代码来总结非连续段(总结“A”中每个数组“a”的相同颜色的段中的数字如下:

有什么想法可以通过推力有效地做到这一点吗?

非常感谢

注意:图片仅代表一个数组“a”。大数组“A”包含许多数组“a”

【问题讨论】:

  • 按键排序以将相似的部分组合在一起。然后通过键减少来创建段总和。
  • 还有另一种解决方案可以不使用排序操作,因为它很昂贵,而且段具有固定大小。? @RobertCrovella
  • 段总是大小为 3 吗? (换句话说,如果段的大小是固定的,那么这个固定大小是先验已知的吗?)是否只有 3 种不同类型的段(粉色、黄色和绿色)?段是否总是按粉-黄-绿-粉-黄-绿的顺序出现...?
  • 段的大小是先验已知的(它是固定的),段的类型(''a'' 中的段数是固定的)也已知是先验的。大数组“A”中的数组“a”的数量是先验固定的。大数组“A”包含数千个“a”类型的数组。 @RobertCrovella
  • 细分是否始终遵循相同的粉-黄-绿顺序?

标签: cuda nvidia gpgpu thrust


【解决方案1】:

在一般情况下,如果事先不知道数据的排序和按段分组,一般建议是使用thrust::sort_by_key 将相似段分组在一起,然后使用thrust::reduce_by_key 对段求和。示例为here

但是,如果输入数据段遵循已知的重复模式,如此处建议的那样,我们可以通过使用 thrust::permutation_iterator 将类似的段“收集”在一起来消除排序步骤,作为 thrust::reduce_by_key 的输入.

使用问题中的示例数据,难点在于创建置换迭代器。为此,使用问题中给出的段类型 (3)、段长度 (3) 和每个段类型的段数 (3) 的特定数量,我们需要一个映射“向量”(即迭代器)用于我们的置换迭代器具有以下顺序:

0  1  2 9 10 11 18 19 20 3 4 5 12 13 14 21 22 23 ...

然后,此序列将“映射”或重新排列输入数组,以便将所有相似的段组合在一起。我确信有多种方法可以创建这样的序列,但我选择的方法如下。我们将从标准计数迭代器序列开始,然后对其应用一个变换函子(使用make_transform_iterator),以便我们创建上述序列。我选择使用以下方法进行操作,按逐步顺序排列,显示添加在一起的组件:

counting iterator: (_1)                         0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 ...
---------------------------------------------------------------------------------------------------
((_1/seg_len)%seg_types)*(seg_len*seg_types):   0  0  0  9  9  9 18 18 18  0  0  0  9  9  9 18 18 18 ...
 _1%seg_len:                                    0  1  2  0  1  2  0  1  2  0  1  2  0  1  2  0  1  2 ...
_1/(seg_len*seg_types)*seg_len:                 0  0  0  0  0  0  0  0  0  3  3  3  3  3  3  3  3  3 ...
 Sum:                                           0  1  2  9 10 11 18 19 20  3  4  5 12 13 14 21 22 23 ...            

这是一个完整的例子:

$ cat t457.cu
#include <thrust/reduce.h>
#include <thrust/iterator/permutation_iterator.h>
#include <thrust/iterator/transform_iterator.h>
#include <thrust/iterator/discard_iterator.h>
#include <thrust/device_vector.h>
#include <thrust/copy.h>
#include <iostream>

typedef int dtype;
const int seg_len = 3;
const int seg_types = 3;

using namespace thrust::placeholders;

int main(){

  dtype data[] = {10,16,14,2,4,4,1,2,1,8,2,10,3,1,6,8,0,2,9,1,0,3,5,2,3,2,1};
  //                0   1  2 9 10 11 18 19 20 3 4 5 12 13 14 21 22 23 ...
  //              ((_1/seg_len)%seg_types)*(seg_len*seg_types) + _1%seg_len + (_1/(seg_len*seg_types)*seg_len

  int ads = sizeof(data)/sizeof(data[0]);
  int num_groups = ads/(seg_len*seg_types); // ads is expected to be whole-number divisible by seg_len*seg_types
  int ds = num_groups*(seg_len*seg_types);  // handle the case when it is not
  thrust::device_vector<dtype> d_data(data, data+ds);
  thrust::device_vector<dtype> d_result(seg_types);
  thrust::reduce_by_key(thrust::make_transform_iterator(thrust::counting_iterator<int>(0), _1/(ds/seg_types)), thrust::make_transform_iterator(thrust::counting_iterator<int>(ds), _1/(ds/seg_types)), thrust::make_permutation_iterator(d_data.begin(), thrust::make_transform_iterator(thrust::counting_iterator<int>(0), ((_1/seg_len)%seg_types)*(seg_len*seg_types) + _1%seg_len + (_1/(seg_len*seg_types)*seg_len))), thrust::make_discard_iterator(), d_result.begin());
  thrust::copy(d_result.begin(), d_result.end(), std::ostream_iterator<dtype>(std::cout, ","));
  std::cout << std::endl;
}
$ nvcc -o t457 t457.cu
$ ./t457
70,30,20,
$

【讨论】:

    猜你喜欢
    • 2018-02-09
    • 2014-09-11
    • 1970-01-01
    • 2018-07-03
    • 2019-10-17
    • 2021-03-25
    • 1970-01-01
    • 2015-08-31
    • 2021-08-07
    相关资源
    最近更新 更多