#define WARP 32
#[inline(always)] int warp_sum(int v) {
for (int offset = WARP / 2; offset > 0; offset /= 2) {
v += (0xFFFFFFFFu, v, lane_id() - offset);
}
return v;
}
#[inline(always)] int warp_ballot(int predicate) {
return (0xFFFFFFFFu, predicate);
}
#[inline(always)] int warp_any(int predicate) {
return (0xFFFFFFFFu, predicate);
}
#[inline(always)] int warp_all(int predicate) {
return (0xFFFFFFFFu, predicate);
}
void warp_demo(const int* in, int* out, int n) {
int shared[WARP];
int tid = thread_idx;
int gid = block_idx * block_dim + tid;
int lane = lane_id();
int v = (gid < n) ? in[gid] : 0;
int pred = (v > 0) ? 1 : 0;
int ballot = warp_ballot(pred);
int any_pos = warp_any(pred);
int all_pos = warp_all(pred);
int active = ();
v = warp_sum(v);
;
if (lane == 0) {
shared[tid / WARP] = v;
atomicAdd(out, v);
atomicMin(out + 1, ballot);
atomicMax(out + 2, active);
}
group.sync();
if (tid == 0) {
atomicAdd(out + 3, any_pos);
atomicAdd(out + 4, all_pos);
}
}
int main(void) {
const int N = 1 << 16;
int* d_in = nullptr;
int* d_out = nullptr;
cudaMalloc((void**)&d_in, N * sizeof(int));
cudaMalloc((void**)&d_out, 5 * sizeof(int));
cudaMemset(d_out, 0, 5 * sizeof(int));
dim3 grid(N / 256);
dim3 block(256);
{ let _kernel = modules.get_function("warp_demo"); unsafe { let _ = launch!( _kernel<<<grid as grid_size, block as block_size, 0 as usize, default>>>(d_in, d_out, N) ); } };
cudaDeviceSynchronize();
cudaFree(d_in);
cudaFree(d_out);
return 0;
}