#include <hip/hip_runtime.h>
#define WARP 32
__device__ __forceinline__ int warp_sum(int v) {
for (int offset = WARP / 2; offset > 0; offset /= 2) {
v += __shfl_sync(0xFFFFFFFFu, v, __laneid()() - offset);
}
return v;
}
__device__ __forceinline__ int warp_ballot(int predicate) {
return __ballot_sync(0xFFFFFFFFu, predicate);
}
__device__ __forceinline__ int warp_any(int predicate) {
return __any_sync(0xFFFFFFFFu, predicate);
}
__device__ __forceinline__ int warp_all(int predicate) {
return __all_sync(0xFFFFFFFFu, predicate);
}
__global__ void warp_demo(const int* in, int* out, int n) {
__shared__ int shared[WARP];
int tid = threadIdx.x;
int gid = blockIdx.x * blockDim.x + tid;
int lane = __laneid()();
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 = __activemask();
v = warp_sum(v);
__syncwarp(0xFFFFFFFFu);
if (lane == 0) {
shared[tid / WARP] = v;
atomicAdd(out, v);
atomicMin(out + 1, ballot);
atomicMax(out + 2, active);
}
__syncthreads();
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;
hipMalloc((void**)&d_in, N * sizeof(int));
hipMalloc((void**)&d_out, 5 * sizeof(int));
hipMemset(d_out, 0, 5 * sizeof(int));
dim3 grid(N / 256);
dim3 block(256);
hipLaunchKernelGGL(warp_demo, dim3(grid), dim3(block), 0, 0, d_in, d_out, N);
hipDeviceSynchronize();
hipFree(d_in);
hipFree(d_out);
return 0;
}