Я попытался реализовать свой собственный Mergesort, основанный на алгоритме с нижним/итеративным объединением. Этот алгоритм разбил данные на 2 элемента и отсортировал их. Затем по 4 элементам и отсортированы и так далее, пока все данные не отсортированы. Итак, мой план назначает каждый поток на 2 элемента. Так я это сделать:Mergesort using CUDA
__global__ void mergeBU(int *d_a, int *d_aux, int sz, int N)
{
int idk = blockIdx.x*blockDim.x+threadIdx.x;
int lo = 2 * sz * idk;
int mid = lo + sz - 1;
float hi = fminf(lo + sz + sz - 1, N - 1);
merge(d_a, d_aux, lo, mid, hi);
}
__device__ void merge(int *d_a, int *d_aux, int lo, int mid, float hi)
{
int i = lo;
int j = mid + 1;
for (int k = lo; k <= hi; k++)
{
d_aux[k] = d_a[k];
}
for (int k = lo; k <= hi; k++)
{
if (i > mid) { d_a[k] = d_aux[j]; j++; }
else if (j > hi) { d_a[k] = d_aux[i]; i++; }
else if (d_aux[j] < d_aux[i]) { d_a[k] = d_aux[j]; j++; }
else { d_a[k] = d_aux[i]; i++; }
}
}
Допустим, я призываю мое ядро < < < 2,4 >>> (который 8 потоков), поэтому я могу только сортировать 16 элементов макс. Если я ввожу 32 элемента, то остальная часть индекса данных не затронута (16-31). Как заставить индекс потока продолжать обрабатывать остальную часть индекса данных? По-прежнему я имею в виду, что индекс потоков (0,1,2,3,4,5,6,7) продолжает обрабатывать остальную часть индекса данных, он должен быть похож на threadindex (dataindex, dataindex) -> 0 (16, 17); 1 (18,19); 2 (20,21); и так далее. Любые комментарии приветствуются.
Мой плохой сэр, я имел в виду, что данные массива разделяются на 2 элемента при первой итерации, поэтому в подмассиве содержится по 2 элемента, затем отсортированы по каждому подматрицу, затем по 4 элементам, затем отсортированы и так далее. Я отредактировал свой вопрос. Ваш совет кажется хорошим, но в потоке есть указатель, как назначить каждый поток для обработки массива индексов данных - это то, с чем я имею дело. Поскольку поток ограничен, мои данные также ограничены, если у меня есть фиксированное количество элементов, обрабатываемых каждым потоком. –
@PriyanggaJanmantaraAnusasana - используйте размер массива 2048 в качестве примера. В моей версии, использующей 8 потоков, каждый поток выполняет сортировку слияния по 256 элементам, принимая по 8 проходов каждый, каждый проход создает прогоны размером 2, 4, 8, 16, 32, 64, 128, 256. Затем 4 потока объединяют пары запускает размер 256 для создания 4 прогонов размером 512. Затем 2 потока объединяют пары прогонов размером 512 для создания 2 прогонов размера 1024. Затем 1 поток объединяет последние две пары прогонов для создания 1 пробега размера 2048. – rcgldr
@ PriyanggaJanmantaraAnusasana - продолжая, вы предлагаете запустить 1024 потока для создания прогонов размера 2, затем 512 потоков для создания прогонов размером 4, 256 потоков для создания прогонов размера 8, ... и так далее. Потоки будут выполняться в последовательных блоках, возможно, 8 или 16 потоков, работающих одновременно, но, как я упоминал в своем ответе, полоса пропускания памяти на обычном ПК достигается примерно в 8 потоках. – rcgldr