Сжатие потока в ядре cuda для поддержки очереди с приоритетами

Я ищу стратегию оптимизации для моей программы cuda. На каждой итерации внутри цикла for моего ядра каждый поток производит оценку. Я поддерживаю общую приоритетную очередь результатов, чтобы поддерживать топ-k из них на блок. Пожалуйста, смотрите псевдокод ниже:

__global__ gpuCompute(... arguments)
{
    __shared__ myPriorityQueue[k];  //To maintain top k scores ( k < #threads in this block)
    __shared__ scoresToInsertInQueue[#threadsInBlock];
    __shared__ counter;
    for(...)       //About 1-100 million iterations
    {
        int score = calculate_score(...);
        if(score > Minimum element of P. Queue && ...)
        {
            ATOMIC Operation : localCounter = counter++;
            scoresToInsertInQueue[localCounter] = score;
        }
        __syncthreads();
        //Merge scores from scoresToInsertInQueue to myPriorityQueue
        while(counter>0)
        {
            //Parallel insertion of scoresToInsertInQueue[counter] to myPriorityQueue using the participation of k threads in this block
            counter--;  
            __syncthreads(); 
        }
        __syncthreads();
    }
}

Надеюсь, что приведенный выше код имеет смысл для вас, ребята. Теперь я ищу способ удалить накладные расходы атомарной операции, когда каждый поток сохраняет "1" или "0" в зависимости от того, должно ли значение идти в приоритетную очередь или нет. Мне интересно, есть ли какая-либо реализация потокового сжатия в ядре, чтобы я мог уменьшить буфер "1000000000100000000" до "11000000000000000000" (или знать индекс "1") и, наконец, вставить оценки, соответствующие "1", в очередь.
Обратите внимание, что "1" будет очень редким в этом случае.

1 ответ

Если они очень редки, atomic метод может быть самым быстрым. Однако описанный здесь метод будет иметь более предсказуемую и ограниченную производительность в худшем случае.

Для хорошего сочетания единиц и нулей в вашем массиве решений может быть быстрее использовать параллельное сканирование или префиксную сумму для построения массива индекса точки вставки из массива решений:

Предположим, у меня есть решение о пороговом значении, которое выбирает баллы> 30 для перехода в очередь. Мои данные могут выглядеть так:

scores:     30  32  28  77  55  12  19
score > 30:  0   1   0   1   1   0   0
insert_pt:   0   0   1   1   2   3   3    (an "exclusive prefix sum")

Затем каждый поток делает выбор хранилища следующим образом:

if (score[threadIdx.x] > 30) temp[threadIdx.x] = 1;
else temp[threadIdx.x] = 0;
__syncthreads();
// perform exclusive scan on temp array into insert_pt array
__syncthreads();
if (temp[threadIdx.x] == 1)
  myPriorityQueue[insert_pt[threadIdx.x]] = score[threadIdx.x];

CUB имеет быстрое параллельное сканирование префиксов.

Другие вопросы по тегам