#define WARP 32
#define BLOCK 256
#[inline(always)] int warp_reduce(int v) {
for (int offset = WARP / 2; offset > 0; offset /= 2) {
v += (0xFFFFFFFFu, v, lane_id() - offset);
}
return v;
}
void reduce_block(const int* in, int* partial, int n) {
int shared[BLOCK / WARP];
int tid = thread_idx;
int gid = block_idx * block_dim + tid;
int v = 0;
for (int i = gid; i < n; i += grid_dim * block_dim) {
v += in[i];
}
v = warp_reduce(v);
group.sync();
int lane = tid % WARP;
int warp = tid / WARP;
if (lane == 0) {
shared[warp] = v;
}
group.sync();
if (warp == 0) {
v = (tid < BLOCK / WARP) ? shared[lane] : 0;
v = warp_reduce(v);
if (lane == 0) {
atomicAdd(partial, v);
}
}
}
void reduce_final(int* partial) {
if (thread_idx == 0 && block_idx == 0) {
int result = *partial;
(void)result;
}
}
int main(void) {
const int N = 1 << 22;
int* d_in = nullptr;
int* d_partial = nullptr;
cudaMalloc((void**)&d_in, N * sizeof(int));
cudaMalloc((void**)&d_partial, sizeof(int));
cudaMemset(d_partial, 0, sizeof(int));
dim3 grid(N / BLOCK);
dim3 block(BLOCK);
{ let _kernel = modules.get_function("reduce_block"); unsafe { let _ = launch!( _kernel<<<grid as grid_size, block as block_size, 0 as usize, default>>>(d_in, d_partial, N) ); } };
{ let _kernel = modules.get_function("reduce_final"); unsafe { let _ = launch!( _kernel<<<1 as grid_size, 1 as block_size, 0 as usize, default>>>(d_partial) ); } };
int result = 0;
cudaMemcpy(&result, d_partial, sizeof(int), cudaMemcpyDeviceToHost);
cudaFree(d_in);
cudaFree(d_partial);
return 0;
}