Ответ на ваши вопросы содержится в том самом документе, на который вы ссылаетесь, и пример сокращения SDK показывает конкретные реализации концепции сокращения.
Для полноты приведем конкретный пример ядра сокращения:
template <typename T, int BLOCKSIZE>
__global__ reduction(T *inputvals, T *outputvals, int N)
{
__shared__ volatile T data[BLOCKSIZE];
T maxval = inputvals[threadIdx.x];
for(int i=blockDim.x + threadIdx.x; i<N; i+=blockDim.x)
{
maxfunc(maxval, inputvals[i]);
}
data[threadIdx.x] = maxval;
__syncthreads();
// Here maxfunc(a,b) sets a to the minimum of a and b
if (threadIdx.x < 32) {
for(int i=32+threadIdx.x; i < BLOCKSIZE; i+= 32) {
maxfunc(data[threadIdx.x], data[i]);
}
if (threadIdx.x < 16) maxfunc(data[threadIdx.x], data[threadIdx.x+16]);
if (threadIdx.x < 8) maxfunc(data[threadIdx.x], data[threadIdx.x+8]);
if (threadIdx.x < 4) maxfunc(data[threadIdx.x], data[threadIdx.x+4]);
if (threadIdx.x < 2) maxfunc(data[threadIdx.x], data[threadIdx.x+2]);
if (threadIdx.x == 0) {
maxfunc(data[0], data[1]);
outputvals[blockIdx.x] = data[0];
}
}
}
Ключевым моментом является использование неявной синхронизации внутри деформации для выполнения сокращения общей памяти.Результатом является максимальное значение для каждого блока.Второй проход сокращения необходим, чтобы уменьшить набор максимумов блоков до глобального максимума (часто это происходит быстрее на хосте).В этом примере maxvals
- это функция «сравнить и установить», которая может быть простой:
template<T>
__device__ void maxfunc(T & a, T & b)
{
a = (b > a) ? b : a;
}