Cuda 如何减少推力阵中的非连续数段
我有一个一维数组“A”,它由许多数组“A”组成,如下所示: 我正在实现一个代码来汇总非连续段(将“a”中每个数组“a”的相同颜色段中的数字汇总如下: 有什么办法可以有效地利用推力做到这一点吗 多谢各位Cuda 如何减少推力阵中的非连续数段,cuda,nvidia,gpgpu,thrust,Cuda,Nvidia,Gpgpu,Thrust,我有一个一维数组“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),推力::生成变换迭代器(推力::计数迭代器)_