我有100000个数组,它们存储在一个大的1D数组中。 每个数组的大小为L = 1000,并按降序排列。
每个数组分为m = 5个段。(S1,S2,S3,S4,S5) 例如:
A1=[S1,S2,S3,S4,S5]
A2=[S1,S2,S3,S4,S5]
A3=[S1,S2,S3,S4,S5]
…
A100000=[S1,S2,S3,S4,S5]
我的问题是:
对于w = 10个数组的每个窗口(例如),我想按以下方式重组10个数组: 首先将这10个数组中的每个数组的段S1放置,之后再放置S2段,S3段…。 以下是w = 6的示例:
作为信息L,m和w是可以采用不同值的参数。
是否有使用Thrust的快速方法?
答案 0 :(得分:1)
该方法将与所描述的here非常相似。
thrust::counting_iterator
提供序数序列0、1、2,...,然后使用thrust::transform_iterator
构造映射迭代器。挑战在于为传递给变换迭代器的操作创建正确的算法。下面的代码被广泛注释以解释这一点。 thrust::permutation_iterator
将地图矢量传递到thrust::copy_n
。请注意,有时候好的建议是不要复制数据。如果只使用一次数据的“转换视图”,则只需将该置换迭代器传递给您一次使用的推力算法,而不是实际复制数据。如果您需要多次使用数据的“转换视图”,则一次复制可能会更有效。这是一个可行的示例:
$ cat t5.cu
#include <thrust/sequence.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; // data type
typedef int itype; // indexing type - change to size_t if L*m*s > int
const itype s = 3; // segment_width
const itype m = 2; // number of segments per sub-array
const itype L = 4; // number of sub-arrays per array
const itype w = 2; // width of group (# of sub-arrays) for segment reordering
// S1 S1 S2 S2 S1 S1 S2 S2
// 0 1 2 6 7 8 3 4 5 9 10 11 12 13 14 18 19 20 15 16 17 21 22 23
using namespace thrust::placeholders;
int main(){
// we require data that consists of L*m*s elements
// we also require L to be whole-number divisible by w
thrust::device_vector<dtype> d_data(L*m*s);
thrust::device_vector<dtype> d_result(L*m*s);
thrust::sequence(d_data.begin(), d_data.end());
// we will build up the necessary map iterator progressively
// we will start with an target_index sequence i = 0, 1, 2, 3, 4, 5, ... which defines the location in the target vector
// seg_idx (position within a segment) = i%s 0, 1, 2, 0, 1, 2, ...
// which_seg (which segment within sub-array) = (i/(w*s))%m 0, 0, 0, 0, 0, 0, 1, ...
// which_sub (which sub-array in group) = (i/s)%w 0, 0, 0, 1, 1, 1, 0, ...
// which_grp (which group in array) = i/(w*s*m) 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ...
// map index = which_grp*group_width + which_sub*subarray_width + which_seg*segment_width + seg_idx
// map index = (i/(w*s*m))*(w*s*m) + ((i/s)%w)*(s*m) + ((i/(w*s))%m)*s + i%s
thrust::copy_n(thrust::make_permutation_iterator(d_data.begin(), thrust::make_transform_iterator(thrust::counting_iterator<itype>(0), (_1/(w*s*m))*(w*s*m) + ((_1/s)%w)*(s*m) + ((_1/(w*s))%m)*s + _1%s)), L*m*s, d_result.begin());
thrust::copy(d_result.begin(), d_result.end(), std::ostream_iterator<dtype>(std::cout, ","));
std::cout << std::endl;
}
$ nvcc -o t5 t5.cu
$ ./t5
0,1,2,6,7,8,3,4,5,9,10,11,12,13,14,18,19,20,15,16,17,21,22,23,
$
请注意,如果总数据长度(L*m*s
)大于int
所能容纳的长度,则必须重构以上代码以使用size_t
int
的{{1}}类型定义。