#include <device_functions.h>
#define WARP 32
float c_scale[4];
#[inline(always)] float fast_scale(float v, int idx) {
return v * c_scale[idx & 3];
}
#[inline(never)] float slow_path(float v) {
if (v < 0.0f) return 0.0f;
return __sinf(v);
}
__launch_bounds__(256, 2)
void apply(const float* in, float* out, int n) {
int i = block_idx * block_dim + thread_idx;
if (i < n) {
float v = fast_scale(in[i], i);
out[i] = slow_path(v);
}
}
void warp_sum(const float* in, float* out, int n) {
int lane = lane_id;
float v = (thread_idx < n) ? in[thread_idx] : 0.0f;
;
float partial[WARP];
partial[lane] = v;
group.sync();
if (lane == 0) {
float s = 0.0f;
for (int i = 0; i < WARP; ++i) s += partial[i];
out[block_idx] = s;
}
}
int main(void) {
const int N = 1 << 18;
float* d_in = nullptr;
float* d_out = nullptr;
float* d_warp = nullptr;
cudaMalloc((void**)&d_in, N * sizeof(float));
cudaMalloc((void**)&d_out, N * sizeof(float));
cudaMalloc((void**)&d_warp, (N / WARP) * sizeof(float));
float scale_init[4] = {1.0f, 2.0f, 3.0f, 4.0f};
cudaMemcpyToSymbol(c_scale, scale_init, sizeof(scale_init));
dim3 grid(N / 256);
dim3 block(256);
{ let _kernel = modules.get_function("apply"); unsafe { let _ = launch!( _kernel<<<grid as grid_size, block as block_size, 0 as usize, default>>>(d_in, d_out, N) ); } };
{ let _kernel = modules.get_function("warp_sum"); unsafe { let _ = launch!( _kernel<<<N / WARP as grid_size, WARP as block_size, 0 as usize, default>>>(d_in, d_warp, N) ); } };
cudaDeviceSynchronize();
cudaFree(d_in);
cudaFree(d_out);
cudaFree(d_warp);
return 0;
}