正如@tera 所指出的,您可以将一个数字与前一个数字进行比较,以确定它是否是唯一数字序列中的第一个出现。您可以编写一个内核来为此标准生成掩码,以便掩码数组包含第一次出现的数字的索引和负数(如 -1,因为它不能是索引)。之后,使用推力通过谓词计算非 -1 值。然后使用与上述相同的谓词从掩码中复制这些值。最后,将结果复制回主机。
这是上述方法的示例实现。
#include <iostream>
#include <cuda_runtime.h>
#include <thrust/device_vector.h>
#include <thrust/count.h>
#include <thrust/copy.h>
using namespace std;
//Copy index
__global__ void is_first_occurence(int* input, int* is, int count)
{
const int tid = blockIdx.x * blockDim.x + threadIdx.x;
if(tid<count)
{
if(tid == 0)
{
is[0] = 0;
}
else if(input[tid] != input[tid-1])
{
is[tid] = tid;
}
else
{
is[tid] = -1;
}
}
}
struct isFirst
{
__host__ __device__ bool operator()(const int x)
{
return (x != -1);
}
};
int main(int argc, char** argv)
{
const int count = 13;
std::vector<int> arr = { 0, 0, 0, 1, 1, 2, 2, 2, 3, 3, 4, 4 ,4 };
thrust::device_vector<int> arr_d = arr;
thrust::device_vector<int> mask_d(arr_d.size());
int* pArr = thrust::raw_pointer_cast(arr_d.data() );
int* pMask = thrust::raw_pointer_cast(mask_d.data() );
dim3 block(16);
dim3 grid((count + block.x -1)/block.x);
is_first_occurence<<<grid,block>>>(pArr, pMask, count);
cudaDeviceSynchronize();
int num_unique = thrust::count_if(mask_d.begin(), mask_d.end(), isFirst());
thrust::copy_if(mask_d.begin(), mask_d.end(), arr_d.begin(), isFirst());
std::vector<int> unique_indices(num_unique);
thrust::copy(arr_d.begin(), arr_d.begin() + num_unique, unique_indices.begin());
for(auto i:unique_indices)
{
cout<<i<<endl;
}
return 0;
}
使用以下命令编译和测试:
nvcc -o get_unique get_unique.cu -std=c++11 -arch=sm_61