本人 CUDA小白一枚,要是有什么不对,还望各位大佬指点。
本文及后面的几篇将分别从几个方面来大概阐述一下Thrust的一些接口。原来的网址在这里。
1.5 Partitioning
1.5.1 partition
template__host__ __device__ ForwardIterator thrust::partition( const thrust::detail::execution_policy_base< DerivedPolicy > & exec, ForwardIterator first, ForwardIterator last, Predicate pred ); template ForwardIterator thrust::partition( ForwardIterator first, ForwardIterator last, Predicate pred ); template __host__ __device__ ForwardIterator thrust::partition( const thrust::detail::execution_policy_base< DerivedPolicy > & exec, ForwardIterator first, ForwardIterator last, InputIterator stencil, Predicate pred ); template ForwardIterator thrust::partition( ForwardIterator first, ForwardIterator last, InputIterator stencil, Predicate pred );
按照一定的pred对[first, last)中的数据进行重排序,可以指定对应的stencil,使得pred判断的时候是针对stencil中的元素进行判断,然后按照判断结果对[first, last)中的数据进行重排序。
例子:
struct is_even {
__host__ __device__
bool operator()(const int &x) {
return (x % 2) == 0;
}
}
int A[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
const int N = sizeof(A)/sizeof(int);
thrust::partition(thrust::host, A, A + N, is_even());
// thrust::partition(A, A + N, is_even());
// A {2, 4, 6, 8, 10, 1, 3, 5, 7, 9}
int B[] = {0, 1, 0, 1, 0, 1, 0, 1, 0, 1};
int S[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
thrust::partition(thrust::host, B, B + N, S, is_even());
// thrust::partition(B, B + N, S, is_even());
// B {1, 1, 1, 1, 1, 0, 0, 0, 0, 0}
1.5.2 partition_copy
template__host__ __device__ thrust::pair< OutputIterator1, OutputIterator2 > thrust::partition_copy( const thrust::detail::execution_policy_base< DerivedPolicy > & exec, InputIterator first, InputIterator last, OutputIterator1 out_true, OutputIterator2 out_false, Predicate pred ); template thrust::pair< OutputIterator1, OutputIterator2 > thrust::partition_copy( InputIterator first, InputIterator last, OutputIterator1 out_true, OutputIterator2 out_false, Predicate pred ); template __host__ __device__ thrust::pair< OutputIterator1, OutputIterator2 > thrust::partition_copy( const thrust::detail::execution_policy_base< DerivedPolicy > & exec, InputIterator1 first, InputIterator1 last, InputIterator2 stencil, OutputIterator1 out_true, OutputIterator2 out_false, Predicate pred ); template thrust::pair< OutputIterator1, OutputIterator2 > thrust::partition_copy( InputIterator1 first, InputIterator1 last, InputIterator2 stencil, OutputIterator1 out_true, OutputIterator2 out_false, Predicate pred );
基于partition的基础上增加了一个将结果分别保存在out_true和out_false中,同样的也可以指定stenctil。
例子:
struct is_even {
__host__ __device__
bool operator()(const int &x) {
return (x % 2) == 0;
}
}
int A[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int result[10];
const int N = sizeof(A)/sizeof(int);
int *evens = result;
int *odds = result + 5;
thrust::partition_copy(thrust::host, A, A + N, evens, odds, is_even());
// thrust::partition_copy(A, A + N, evens, odds, is_even());
// A {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
// result {2, 4, 6, 8, 10, 1, 3, 5, 7, 9}
// evens {2, 4, 6, 8, 10}
// odds {1, 3, 5, 7, 9}
int B[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int S[] = {0, 1, 0, 1, 0, 1, 0, 1, 0, 1};
int result2[10];
const int N2 = sizeof(B)/sizeof(int);
int *evens2 = result2;
int *odds2 = result2 + 5;
thrust::partition_copy(thrust::host, B, B + N2, S, evens2, odds2, thrust::identity());
// B {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
// S {0, 1, 0, 1, 0, 1, 0, 1, 0, 1}
// result2 {2, 4, 6, 8, 10, 1, 3, 5, 7, 9}
// evens2 {2, 4, 6, 8, 10}
// odds2 {1, 3, 5, 7, 9}
1.5.3 stable_partition
template__host__ __device__ ForwardIterator thrust::stable_partition( const thrust::detail::execution_policy_base< DerivedPolicy > & exec, ForwardIterator first, ForwardIterator last, Predicate pred ); template ForwardIterator thrust::stable_partition( ForwardIterator first, ForwardIterator last, Predicate pred ); template __host__ __device__ ForwardIterator thrust::stable_partition( const thrust::detail::execution_policy_base< DerivedPolicy > & exec, ForwardIterator first, ForwardIterator last, InputIterator stencil, Predicate pred ); template ForwardIterator thrust::stable_partition( ForwardIterator first, ForwardIterator last, InputIterator stencil, Predicate pred );
stable_partition与partition很像。与partition不同的是,stable可以保证两个重新排序的顺序还是跟之前的顺序保持一致。
例子基本上跟1.5.1的类似,只是换了函数的名字,两个例子的结果也是一致的,所以这边就不再赘述。
1.5.4 stable_partition_copy
template__host__ __device__ thrust::pair< OutputIterator1, OutputIterator2 > thrust::stable_partition_copy( const thrust::detail::execution_policy_base< DerivedPolicy > & exec, InputIterator first, InputIterator last, OutputIterator1 out_true, OutputIterator2 out_false, Predicate pred ); template thrust::pair< OutputIterator1, OutputIterator2 > thrust::stable_partition_copy( InputIterator first, InputIterator last, OutputIterator1 out_true, OutputIterator2 out_false, Predicate pred ); template __host__ __device__ thrust::pair< OutputIterator1, OutputIterator2 > thrust::stable_partition_copy( const thrust::detail::execution_policy_base< DerivedPolicy > & exec, InputIterator1 first, InputIterator1 last, InputIterator2 stencil, OutputIterator1 out_true, OutputIterator2 out_false, Predicate pred ); template thrust::pair< OutputIterator1, OutputIterator2 > thrust::stable_partition_copy( InputIterator1 first, InputIterator1 last, InputIterator2 stencil, OutputIterator1 out_true, OutputIterator2 out_false, Predicate pred );
功能与partition_copy类似,不同的地方在于stable可以保证两个重新排序的顺序还是跟之前的顺序保持一致。
例子与1.5.2中的较为类似,只是更换了函数的名字,所以不再赘述。
1.5.5 shuffle
template__host__ __device__ void thrust::shuffle( const thrust::detail::execution_policy_base< DerivedPolicy > & exec, RandomIterator first, RandomIterator last, URBG && g ); template __host__ __device__ void thrust::shuffle( RandomIterator first, RandomIterator last, URBG && g );
根据一个随机engine,将[first, last)中的元素打乱。
例子:
int A[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
const int N = sizeof(A)/sizeof(int);
thrust::default_random_engine g;
thrust::shuffle(thrust::host, A, A + N, g);
// A {6, 5, 8, 7, 2, 1, 4, 3, 10, 9}
1.5.6 shuffle_copy
template__host__ __device__ void shuffle_copy( const thrust::detail::execution_policy_base< DerivedPolicy > & exec, RandomIterator first, RandomIterator last, OutputIterator result, URBG && g ); template __host__ __device__ void shuffle_copy( RandomIterator first, RandomIterator last, OutputIterator result, URBG && g );
相比于shuffle而言,多了一个输出结果的位置。
例子:
int A[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int result[10];
thrust::default_random_engine g;
thrust::shuffle_copy(thrust::host, A, A + 10, result, g);
// result {6, 5, 8, 7, 2, 1, 4, 3, 10, 9}
1.5.7 copy_if
template__host__ __device__ OutputIterator thrust::copy_if( const thrust::detail::execution_policy_base< DerivedPolicy > & exec, InputIterator first, InputIterator last, OutputIterator result, Predicate pred ); template OutputIterator thrust::copy_if( InputIterator first, InputIterator last, OutputIterator result, Predicate pred ); template __host__ __device__ OutputIterator thrust::copy_if( const thrust::detail::execution_policy_base< DerivedPolicy > & exec, InputIterator1 first, InputIterator1 last, InputIterator2 stencil, OutputIterator result, Predicate pred ); template OutputIterator thrust::copy_if( InputIterator1 first, InputIterator1 last, InputIterator2 stencil, OutputIterator result, Predicate pred );
按照一定的pred将[firtst, last)中的元素满足条件的拷贝到result中。同样的可以指定对应的stencil,pred将对stencil中的元素进行判断,将符合条件对应的[first, last)中的元素进行拷贝。
例子:
struct is_even {
__host__ __device__
bool operator()(int &x) {
return (x % 2) == 0;
}
}
int V[6] = {-2, 0, -1, 0, 1, 2};
int result[4];
thrust::copy_if(thrust::host, V, V + 6, result, is_even());
// thrust::copy_if(V, V + 6, result, is_even());
// result {-2, 0, 0, 2}
int data[6] = {0, 1, 2, 3, 4, 5};
int stencil[6] = {-2, 0, -1, 0, 1, 2};
int result1[4];
thrust::copy_if(thrust::host, data, data+ 6, stencil, result1, is_even());
// thrust::copy_if(data, data+ 6, stencil, result1, is_even());
// result1 {0, 1, 3, 5}
1.5.8 remove
template__host__ __device__ ForwardIterator thrust::remove( const thrust::detail::execution_policy_base< DerivedPolicy > & exec, ForwardIterator first, ForwardIterator last, const T & value ); template ForwardIterator thrust::remove( ForwardIterator first, ForwardIterator last, const T & value );
删除[first, last)中与value相等的值
例子:
int A[N] = {3, 1, 4, 1, 5, 9};
int *new_end = thrust::remove(thrust::host, A, A + N, 1);
// int *new_end = thrust::remove(A, A + N, 1);
// new_end {3, 4, 5, 9}
1.5.9 remove_copy
template__host__ __device__ OutputIterator thrust::remove_copy( const thrust::detail::execution_policy_base< DerivedPolicy > & exec, InputIterator first, InputIterator last, OutputIterator result, const T & value ); template OutputIterator thrust::remove_copy( InputIterator first, InputIterator last, OutputIterator result, const T & value );
与remove不同的是在原来的基础上会多一个结果保存的地址。
例子:
const int N = 6;
int V[N] = {-2, 0, -1, 0, 1, 2};
int result[N - 2];
thrust::remove_copy(thrust::host, V, V + N, result, 0);
// thrust::remove_copy(thrust::host, V, V + N, result, 0);
// result {-2, -1, 1, 2}
1.5.10 remove_if
template__host__ __device__ ForwardIterator thrust::remove_if( const thrust::detail::execution_policy_base< DerivedPolicy > & exec, ForwardIterator first, ForwardIterator last, Predicate pred ); template ForwardIterator thrust::remove_if( ForwardIterator first, ForwardIterator last, Predicate pred ); template __host__ __device__ ForwardIterator thrust::remove_if( const thrust::detail::execution_policy_base< DerivedPolicy > & exec, ForwardIterator first, ForwardIterator last, InputIterator stencil, Predicate pred ); template ForwardIterator thrust::remove_if( ForwardIterator first, ForwardIterator last, InputIterator stencil, Predicate pred );
对[first, end)中的元素利用pred进行判断,如果符合条件,则删除,同样的可以指定对应的stencil,对stencil中的元素进行判断爱决定[first, last)中的元素是否需要删除。
struct is_even {
__host__ __device__
bool operator()(int &x) {
return (x % 2) == 0;
}
}
const int N = 6;
int A[N] = {1, 4, 2, 8, 5, 7};
int *new_end = thrust::remove_if(thrust::host, A, A + N, is_even());
// int *new_end = thrust::remove_if(A, A + N, is_even());
// new_end {1, 5, 7}
1.5.10 remove_copy_if
template__host__ __device__ OutputIterator thrust::remove_copy_if( const thrust::detail::execution_policy_base< DerivedPolicy > & exec, InputIterator first, InputIterator last, OutputIterator result, Predicate pred ); template OutputIterator thrust::remove_copy_if( InputIterator first, InputIterator last, OutputIterator result, Predicate pred ); template __host__ __device__ OutputIterator thrust::remove_copy_if( const thrust::detail::execution_policy_base< DerivedPolicy > & exec, InputIterator1 first, InputIterator1 last, InputIterator2 stencil, OutputIterator result, Predicate pred ); template OutputIterator thrust::remove_copy_if( InputIterator1 first, InputIterator1 last, InputIterator2 stencil, OutputIterator result, Predicate pred );
与remove_if不同的是多了一个copy的操作,即将删除的元素保存到result中。
struct is_even {
__host__ __device__
bool operator()(int &x) {
return (x % 2) == 0;
}
}
const int N = 6;
int V[N] = {-2, 0, -1, 0, 1, 2};
int result[2];
thrust::remove_copy_if(thrust::host, V, V + N, result, is_even());
// thrust::remove_copy_if(V, V + N, result, is_even());
// result {-1, 1}
1.5.11 unique
template__host__ __device__ ForwardIterator thrust::unique( const thrust::detail::execution_policy_base< DerivedPolicy > & exec, ForwardIterator first, ForwardIterator last ); template ForwardIterator thrust::unique( ForwardIterator first, ForwardIterator last ); template __host__ __device__ ForwardIterator thrust::unique( const thrust::detail::execution_policy_base< DerivedPolicy > & exec, ForwardIterator first, ForwardIterator last, BinaryPredicate binary_pred ); template ForwardIterator thrust::unique( ForwardIterator first, ForwardIterator last, BinaryPredicate binary_pred );
删除连续的重复的元素,相同的元素,仅保留第一个。可以指定判断的条件。
例子:
int A[7] = {1, 3, 3, 3, 2, 2, 1};
int new_end* = thrust::unique(thrust::host, A, A + 7);
// int new_end* = thrust::unique(A, A + 7);
// A {1, 3, 2, 1}
int B[7] = {1, 3, 2, 3, 2, 1, 1};
int new_end* = thrust::unique(thrust::host, B, B + 7, thrust::euqal_to());
// int new_end* = thrust::unique{B, B + 7, thrust::euqal_to());
// B {1, 3, 2, 3, 2, 1}
1.5.12 unique_copy
template__host__ __device__ OutputIterator thrust::unique_copy( const thrust::detail::execution_policy_base< DerivedPolicy > & exec, InputIterator first, InputIterator last, OutputIterator result ); template OutputIterator thrust::unique_copy( InputIterator first, InputIterator last, OutputIterator result ); template __host__ __device__ OutputIterator thrust::unique_copy( const thrust::detail::execution_policy_base< DerivedPolicy > & exec, InputIterator first, InputIterator last, OutputIterator result, BinaryPredicate binary_pred ); template OutputIterator thrust::unique_copy( InputIterator first, InputIterator last, OutputIterator result, BinaryPredicate binary_pred );
与unique不同的是,多了一个copy的操作,删除重复之后的元素回报存在result中,可以指定判断的条件。
例子:
const int N = 7;
int A[N] = {1, 3, 3, 3, 2, 2, 1};
int B[N];
int *result_end = thrust::unique_copy(thrust::host, A, A + N, B);
// int *result_end = thrust::unique_copy(A, A + N, B);
// B {1, 3, 2, 1}
int C[N] = {1, 3, 3, 3, 2, 2, 1};
int D[N];
int *result_end1 = thrust::unique_copy(thrust::host, C, C + N, D, thrust::equal_to());
// int *result_end1 = thrust::unique_copy(C, C + N, D);
// B {1, 3, 2, 1}
1.5.13 unique_by_key
template__host__ __device__ thrust::pair< ForwardIterator1, ForwardIterator2 > thrust::unique_by_key( const thrust::detail::execution_policy_base< DerivedPolicy > & exec, ForwardIterator1 keys_first, ForwardIterator1 keys_last, ForwardIterator2 values_first ); template thrust::pair< ForwardIterator1, ForwardIterator2 > thrust::unique_by_key( ForwardIterator1 keys_first, ForwardIterator1 keys_last, ForwardIterator2 values_first ); template __host__ __device__ thrust::pair< ForwardIterator1, ForwardIterator2 > thrust::unique_by_key( const thrust::detail::execution_policy_base< DerivedPolicy > & exec, ForwardIterator1 keys_first, ForwardIterator1 keys_last, ForwardIterator2 values_first, BinaryPredicate binary_pred ); template thrust::pair< ForwardIterator1, ForwardIterator2 > thrust::unique_by_key( ForwardIterator1 keys_first, ForwardIterator1 keys_last, ForwardIterator2 values_first, BinaryPredicate binary_pred );
根据key来指定unique的操作,最终也同步保留values_first中的值。
const int N = 7;
int A[N] = {1, 3, 3, 3, 2, 2, 1}; // keys
int B[N] = {9, 8, 7, 6, 5, 4, 3}; // values
thrust::pair new_end;
new_end = thrust::unique_by_key(thrust::host, A, A + N, B);
// new_end = thrust::unique_by_key(A, A + N, B);
// A {1, 3, 2, 1}
// B {9, 8, 5, 3}
int C[N] = {1, 3, 3, 3, 2, 2, 1}; // keys
int D[N] = {9, 8, 7, 6, 5, 4, 3}; // values
thrust::pair new_end1;
thrust::equal_to binary_pred;
new_end1= thrust::unique_by_key(thrust::host, C, C + N, D, binary_pred);
// new_end1= thrust::unique_by_key(C, C + N, D, binary_pred);
// C {1, 3, 2, 1}
// D {9, 8, 5, 3}
1.5.14 unique_by_key_copy
template__host__ __device__ thrust::pair< OutputIterator1, OutputIterator2 > thrust::unique_by_key_copy( const thrust::detail::execution_policy_base< DerivedPolicy > & exec, InputIterator1 keys_first, InputIterator1 keys_last, InputIterator2 values_first, OutputIterator1 keys_result, OutputIterator2 values_result ); template thrust::pair< OutputIterator1, OutputIterator2 > thrust::unique_by_key_copy( InputIterator1 keys_first, InputIterator1 keys_last, InputIterator2 values_first, OutputIterator1 keys_result, OutputIterator2 values_result ); template __host__ __device__ thrust::pair< OutputIterator1, OutputIterator2 > thrust::unique_by_key_copy( const thrust::detail::execution_policy_base< DerivedPolicy > & exec, InputIterator1 keys_first, InputIterator1 keys_last, InputIterator2 values_first, OutputIterator1 keys_result, OutputIterator2 values_result, BinaryPredicate binary_pred ); template thrust::pair< OutputIterator1, OutputIterator2 > thrust::unique_by_key_copy( InputIterator1 keys_first, InputIterator1 keys_last, InputIterator2 values_first, OutputIterator1 keys_result, OutputIterator2 values_result, BinaryPredicate binary_pred );
与unique_by_key相比,多一个拷贝的过程,最终的key和value会被拷贝到keys_result和values_result中。
例子:
const int N = 7;
int A[N] = {1, 3, 3, 3, 2, 2, 1}; // input keys
int B[N] = {9, 8, 7, 6, 5, 4, 3}; // input values
int C[N]; // output keys
int D[N]; // output values
thrust::pair new_end;
new_end = thrust::unique_by_key_copy(thrust::host, A, A + N, B, C, D);
// new_end = thrust::unique_by_key_copy(A, A + N, B, C, D);
// C {1, 3, 2, 1}
// D {9, 8, 5,3}
int E[N] = {1, 3, 3, 3, 2, 2, 1}; // input keys
int F[N] = {9, 8, 7, 6, 5, 4, 3}; // input values
int G[N]; // output keys
int H[N]; // output values
thrust::pair new_end1;
thrust::equal_to binary_pred;
new_end1 = thrust::unique_by_key_copy(thrust::host, E, E + N, F, G, H, binary_pred);
// new_end1 = thrust::unique_by_key_copy(E, E + N, F, G, H, binary_pred);
// G {1, 3, 2, 1}
// H {9, 8, 5,3}



