Я работаю над ядром Cuda, которое выполняет векторный точечный продукт (A x B). Я предположил, что длина каждого вектора кратно 32 (32,64, ...) и определяет размер блока равным длине массива. Каждый поток в блоке умножает один элемент A на соответствующий элемент B (поток i ==> psum = A [i] xB [i]). После умножения я использовал следующие функции, которые использовали метод перетаскивания основы для выполнения сокращения и вычисления суммы всех умножений.warp shuffling для уменьшения массивов с любой длиной
__inline__ __device__
float warpReduceSum(float val) {
int warpSize =32;
for (int offset = warpSize/2; offset > 0; offset /= 2)
val += __shfl_down(val, offset);
return val;
}
__inline__ __device__
float blockReduceSum(float val) {
static __shared__ int shared[32]; // Shared mem for 32 partial sums
int lane = threadIdx.x % warpSize;
int wid = threadIdx.x/warpSize;
val = warpReduceSum(val); // Each warp performs partial reduction
if (lane==0)
shared[wid]=val; // Write reduced value to shared memory
__syncthreads(); // Wait for all partial reductions
//read from shared memory only if that warp existed
val = (threadIdx.x < blockDim.x/warpSize) ? shared[lane] : 0;
if (wid==0)
val = warpReduceSum(val); // Final reduce within first warp
return val;
}
Я просто называю blockReduceSum (Psum), который Psum является умножение двух элементов на волоске.
Этот подход не работает, когда длина массива не кратная 32, поэтому мой вопрос заключается в том, можем ли мы изменить этот код, чтобы он также работал на любую длину? или это невозможно, потому что, если длина массива не кратная 32, некоторые перекосы имеют элементы, принадлежащие более чем одному массиву?