// Generated by decuda.
// OpenCL device code is the bulk of this file. The host-side calls
// (`cudaXxx`) have been rewritten to OpenCL equivalents inline// surrounding host program still needs a cl_context + cl_queue, not
// included here. Look for TODO(decuda) markers for items requiring
// manual attention.
// Complex fixture: __device__ helper functions, __forceinline__ / __noinline__,
// __constant__ memory, warp intrinsics, and a __launch_bounds__ hint.
//
// Exercises:
// - __device__ helper functions (one __forceinline__, one __noinline__)
// - __constant__ memory arrays
// - __launch_bounds__ (flagged in the report, not auto-translated)
// - __laneid, __syncwarp, __syncthreads
// - threadIdx / blockIdx / blockDim
// - cudaMalloc / cudaFree / cudaMemcpy
// - device_functions.h and cuda_runtime.h headers
#include <CL/cl.h> /* was: cuda_runtime.h */
#include <device_functions.h>
#define WARP 32
__constant float c_scale[4]
__device float fast_scale(float v, int idx) {
return v * c_scale[idx & 3]}
__device float slow_path(float v) {
if (v < 0.0f) return 0.0f return __sinf(v)}
__launch_bounds__(256, 2)
__kernel void apply(const float* in, float* out, int n) {
int i = get_group_id(0) * get_local_size(0) + get_local_id(0) if (i < n) {
float v = fast_scale(in[i], i) out[i] = slow_path(v) }
}
__kernel void warp_sum(const float* in, float* out, int n) {
int lane = get_sub_group_id() * get_sub_group_size() + get_sub_group_local_id()() float v = (get_local_id(0) < n) ? in[get_local_id(0)] : 0.0f barrier(CLK_LOCAL_MEM_FENCE) /* approx */ // In-warp sum via shared memory.
__local float partial[WARP] partial[lane] = v barrier(CLK_LOCAL_MEM_FENCE) if (lane == 0) {
float s = 0.0f for (int i = 0 out[get_group_id(0)] = 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) clEnqueueNDRangeKernel(queue, apply_kernel, 1, NULL, (size_t[1]){grid}, (size_t[1]){block}, 0, NULL, NULL) /* args: d_in, d_out, N */ clEnqueueNDRangeKernel(queue, warp_sum_kernel, 1, NULL, (size_t[1]){N / WARP}, (size_t[1]){WARP}, 0, NULL, NULL) /* args: d_in, d_warp, N */
cudaDeviceSynchronize() cudaFree(d_in) cudaFree(d_out) cudaFree(d_warp) return 0}