J'essaie d'accélérer la recherche binaire du CPU. Malheureusement, la version GPU est toujours beaucoup plus lente que la version CPU. Peut-être que le problème ne convient pas au GPU ou que je fais quelque chose de mal?Implémentation de la recherche binaire CUDA
version CPU (environ de 0,6 ms.): utilisant le tableau trié de longueur 2000 et faire la recherche binaire pour valeur spécifique
...
Lookup (search[j], search_array, array_length, m);
...
int Lookup (int search, int* arr, int length, int& m)
{
int l(0), r(length-1);
while (l <= r)
{
m = (l+r)/2;
if (search < arr[m])
r = m-1;
else if (search > arr[m])
l = m+1;
else
{
return index[m];
}
}
if (arr[m] >= search)
return m;
return (m+1);
}
version GPU (environ 20ms.): en utilisant le tableau trié de longueur 2000 et faire une recherche binaire pour valeur spécifique
....
p_ary_search<<<16, 64>>>(search[j], array_length, dev_arr, dev_ret_val);
....
__global__ void p_ary_search(int search, int array_length, int *arr, int *ret_val)
{
const int num_threads = blockDim.x * gridDim.x;
const int thread = blockIdx.x * blockDim.x + threadIdx.x;
int set_size = array_length;
ret_val[0] = -1; // return value
ret_val[1] = 0; // offset
while(set_size != 0)
{
// Get the offset of the array, initially set to 0
int offset = ret_val[1];
// I think this is necessary in case a thread gets ahead, and resets offset before it's read
// This isn't necessary for the unit tests to pass, but I still like it here
__syncthreads();
// Get the next index to check
int index_to_check = get_index_to_check(thread, num_threads, set_size, offset);
// If the index is outside the bounds of the array then lets not check it
if (index_to_check < array_length)
{
// If the next index is outside the bounds of the array, then set it to maximum array size
int next_index_to_check = get_index_to_check(thread + 1, num_threads, set_size, offset);
if (next_index_to_check >= array_length)
{
next_index_to_check = array_length - 1;
}
// If we're at the mid section of the array reset the offset to this index
if (search > arr[index_to_check] && (search < arr[next_index_to_check]))
{
ret_val[1] = index_to_check;
}
else if (search == arr[index_to_check])
{
// Set the return var if we hit it
ret_val[0] = index_to_check;
}
}
// Since this is a p-ary search divide by our total threads to get the next set size
set_size = set_size/num_threads;
// Sync up so no threads jump ahead and get a bad offset
__syncthreads();
}
}
Même si j'essaie de plus grands tableaux, le rapport de temps n'est pas mieux.
Une simple recherche binaire n'est pas exactement acceptable pour les opérations GPU. C'est une opération en série qui ne peut pas être parallélisée. Cependant, vous pouvez diviser le tableau en petits morceaux et faire des recherches binaires sur chacun d'eux. Créez des blocs X, déterminez qui peut contenir votre variable dans X threads parallèles. Jetez tout sauf un candidat, subdiviser plus loin, etc ... –
Vous pourriez vouloir vérifier la recherche binaire Thrust à http://wiki.thrust.googlecode.com/hg/html/group__binary__search.html – jmsu