Wie @tera darauf hingewiesen hat, können Sie eine Zahl mit der vorherigen Zahl vergleichen, um festzustellen, ob es sich um das erste Vorkommen in einer Folge eindeutiger Zahlen handelt. Sie können einen Kernel schreiben, um eine Maske für dieses Kriterium zu erzeugen, so dass das Masken-Array den Index für eine Zahl enthält, die ein erstes Vorkommen und eine negative Zahl ist (wie -1, da es kein Index sein kann). Verwenden Sie danach Schub, um die Nicht-1-Werte zu zählen, indem Sie ein Prädikat verwenden. Kopieren Sie dann diese Werte aus der Maske mit dem gleichen Prädikat wie oben. Abschließend kopieren Sie die Ergebnisse zurück zum Host.
Hier ist eine Beispielimplementierung des oben genannten Ansatzes.
#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;
}
kompiliert und getestet mit dem folgenden Befehl:
nvcc -o get_unique get_unique.cu -std = C++ 11 -arch = sm_61
Vergleichen Sie jeden Wert mit dem vorherigen, um festzustellen, ob es das erste Vorkommen ist. – tera
Wie erscheint Ihr Array als Eingabe? Wenn es von einer externen Quelle (z. B. einer Datei) gelesen wird, benötigen Sie dafür einen separaten Kernel. Aber wenn es sich um eine Ausgabe eines anderen Kernels handelt, sagen wir - einen Sortieralgorithmus -, dann ist es vielleicht besser, die gewünschte Ausgabe zu dieser Zeit als in dem separaten Schritt zu erhalten. – CygnusX1
Es ist die Ausgabe von mehreren Schubaufrufen, so dass ein separater Schritt wünschenswert ist – Patrik