Cuda 如何减少推力阵中的非连续数段

Cuda 如何减少推力阵中的非连续数段,cuda,nvidia,gpgpu,thrust,Cuda,Nvidia,Gpgpu,Thrust,我有一个一维数组“A”,它由许多数组“A”组成,如下所示: 我正在实现一个代码来汇总非连续段(将“a”中每个数组“a”的相同颜色段中的数字汇总如下: 有什么办法可以有效地利用推力做到这一点吗 多谢各位 注:图片仅代表一个数组“a”。大数组“a”包含多个数组“a”在一般情况下,如果事先不知道数据的顺序和按段分组,一般建议使用推力::按_键排序将类似的段分组在一起,然后使用推力::按_键减少对段进行求和。给出了示例 然而,如果输入数据段遵循一种已知的重复模式,如本文所建议的,我们可以通过使用推力

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

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

有什么办法可以有效地利用推力做到这一点吗

多谢各位


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

在一般情况下,如果事先不知道数据的顺序和按段分组,一般建议使用
推力::按_键排序
将类似的段分组在一起,然后使用
推力::按_键减少
对段进行求和。给出了示例

然而,如果输入数据段遵循一种已知的重复模式,如本文所建议的,我们可以通过使用
推力::置换_迭代器
将类似的段“聚集”在一起来消除排序步骤,作为
推力::按_键减少
的输入

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

0  1  2 9 10 11 18 19 20 3 4 5 12 13 14 21 22 23 ...
然后,该序列将“映射”或重新排列输入数组,以便将所有相似的段分组在一起。我确信有多种方法可以创建这样的序列,但我选择的方法如下。我们将从标准计数迭代器序列开始,然后对其应用变换函子(使用
make\u transform\u 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,
$
$cat t457.cu
#包括
#包括
#包括
#包括
#包括
#包括
#包括
typedef int-dtype;
const int seg_len=3;
const int seg_types=3;
使用命名空间推力::占位符;
int main(){
数据类型数据[]={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_类型)*(seg_len*seg_类型)+1%seg_len+((1/(seg_len*seg_类型)*seg_len
int ads=sizeof(数据)/sizeof(数据[0]);
int num_groups=ads/(seg_len*seg_types);//ads应为可被seg_len*seg_types整除的整数
int ds=num_groups*(seg_len*seg_types);//在不需要时处理该情况
推力:设备矢量数据(数据,数据+ds);
推力:设备矢量d结果(seg类型);
推力:按键减少推力(推力:生成变换迭代器(推力:计数迭代器(0),(ds/seg类型)),推力:生成变换迭代器(推力:计数迭代器(ds),(ds/seg类型)),推力:生成置换迭代器(数据开始(),推力:生成变换迭代器(推力:计数迭代器(0),((1/seg类型)*(seg类型)+_1%seg_len+(_1/(seg_len*seg_类型)*seg_len))),推力::生成/放弃迭代器(),d_结果.开始();
推力::复制(d_result.begin()、d_result.end()、std::ostream_迭代器(std::cout,“,”);

std::cout在一般情况下,如果数据的顺序和按段分组的顺序事先未知,一般建议使用
struch::sort_by_key
将类似的段分组在一起,然后使用
struch::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\u transform\u 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,
$
$cat t457.cu
#包括
#包括
#包括
#包括
#包括
#包括
#包括
typedef int-dtype;
const int seg_len=3;
const int seg_types=3;
使用命名空间推力::占位符;
int main(){
数据类型数据[]={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_类型)*(seg_len*seg_类型)+1%seg_len+((1/(seg_len*seg_类型)*seg_len
int ads=sizeof(数据)/sizeof(数据[0]);
int num_groups=ads/(seg_len*seg_types);//ads应为可被seg_len*seg_types整除的整数
int ds=num_groups*(seg_len*seg_types);//在不需要时处理该情况
推力:设备矢量数据(数据,数据+ds);
推力:设备矢量d结果(seg类型);
推力::按键减少推力(推力::生成变换迭代器(推力::计数迭代器(0),推力::生成变换迭代器(推力::计数迭代器(ds),推力::生成变换迭代器(推力::计数迭代器(ds),推力::生成置换迭代器(数据开始(),推力::生成变换迭代器(推力::计数迭代器(0),推力::生成变换迭代器(推力::计数迭代器)_