Thrust 在 Github 上的文档不是最新的。正如@JaredHoberock 所说,thrust::partition
这是要走的路,因为它现在支持 stencils。您可能需要从Github 存储库获取副本:
git clone git://github.com/thrust/thrust.git
然后scons doc
在 Thrust 文件夹中运行以获取更新的文档,并在编译代码时使用这些更新的 Thrust 源 ( nvcc -I/path/to/thrust ...
)。使用新的模板分区,您可以:
#include <thrust/partition.h>
#include <thrust/execution_policy.h>
#include <thrust/iterator/zip_iterator.h>
#include <thrust/tuple.h>
struct is_positive
{
__host__ __device__
bool operator()(const int &x)
{
return x >= 0;
}
};
thrust::partition(thrust::host, // if you want to test on the host
thrust::make_zip_iterator(thrust::make_tuple(keyVec.begin(), valVec.begin())),
thrust::make_zip_iterator(thrust::make_tuple(keyVec.end(), valVec.end())),
keyVec.begin(),
is_positive());
这将返回:
Before:
keyVec = 0 -1 2 -3 4 -5 6 -7 8 -9
valVec = 0 1 2 3 4 5 6 7 8 9
After:
keyVec = 0 2 4 6 8 -5 -3 -7 -1 -9
valVec = 0 2 4 6 8 5 3 7 1 9
请注意,这 2 个分区不一定是排序的。此外,原始向量和分区之间的顺序可能不同。如果这对您很重要,您可以使用thrust::stable_partition
:
stable_partition 与 partition 的不同之处在于 stable_partition 保证保持相对顺序。也就是说,如果 x 和 y 是 [first, last) 中的元素,使得 pred(x) == pred(y),并且如果 x 在 y 之前,那么在 stable_partition 之后 x 在 y 之前仍然为真。
如果你想要一个完整的例子,这里是:
#include <thrust/host_vector.h>
#include <thrust/device_vector.h>
#include <thrust/partition.h>
#include <thrust/iterator/zip_iterator.h>
#include <thrust/tuple.h>
struct is_positive
{
__host__ __device__
bool operator()(const int &x)
{
return x >= 0;
}
};
void print_vec(const thrust::host_vector<int>& v)
{
for(size_t i = 0; i < v.size(); i++)
std::cout << " " << v[i];
std::cout << "\n";
}
int main ()
{
const int N = 10;
thrust::host_vector<int> keyVec(N);
thrust::host_vector<int> valVec(N);
int sign = 1;
for(int i = 0; i < N; ++i)
{
keyVec[i] = sign * i;
valVec[i] = i;
sign *= -1;
}
// Copy host to device
thrust::device_vector<int> d_keyVec = keyVec;
thrust::device_vector<int> d_valVec = valVec;
std::cout << "Before:\n keyVec = ";
print_vec(keyVec);
std::cout << " valVec = ";
print_vec(valVec);
// Partition key-val on device
thrust::partition(thrust::make_zip_iterator(thrust::make_tuple(d_keyVec.begin(), d_valVec.begin())),
thrust::make_zip_iterator(thrust::make_tuple(d_keyVec.end(), d_valVec.end())),
d_keyVec.begin(),
is_positive());
// Copy result back to host
keyVec = d_keyVec;
valVec = d_valVec;
std::cout << "After:\n keyVec = ";
print_vec(keyVec);
std::cout << " valVec = ";
print_vec(valVec);
}
更新
thrust::sort_by_key
我与版本进行了快速比较,thrust::partition
实现似乎确实更快(这是我们自然可以期待的)。这是我在 NVIDIA Visual Profiler 上获得的内容,左侧N = 1024 * 1024
是排序版本,右侧是分区版本。您可能希望自己进行相同类型的测试。