decuda 0.1.1

CUDA to HIP, SYCL, OpenCL, and Rust GPU migration tool — automatic source-code translator for porting CUDA C++ kernels to AMD ROCm HIP, Intel oneAPI SYCL, Khronos OpenCL, and Rust GPU (cust / rust-gpu)
Documentation
// Generated by decuda.
// SYCL kernels replace CUDA kernels with parallel_for lambdas; this
// output is a *starting point* and almost always requires manual
// follow-up. Look for the `TODO(decuda)` markers in this file.

#include <sycl/sycl.hpp>

// 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 <sycl/sycl.hpp> /* was: cuda_runtime.h */
#include <sycl/sycl.hpp> /* was: device_functions.h */

#define WARP 32

/* constant -> SYCL constant_accessor */ float c_scale[4];

// SYCL device function [[clang::always_inline]] float fast_scale(float v, int idx) {
    return v * c_scale[idx & 3];
}

// SYCL device function [[gnu::noinline]] float slow_path(float v) {
    if (v < 0.0f) return 0.0f;
    return __sinf(v);
}

__launch_bounds__(256, 2)
// TODO(decuda): rewrite as SYCL kernel lambda
 void apply(const float* in, float* out, int n) {
    int i = item.get_group(0) * item.get_local_range() + item.get_local_id();
    if (i < n) {
        float v = fast_scale(in[i], i);
        out[i] = slow_path(v);
    }
}

// TODO(decuda): rewrite as SYCL kernel lambda
 void warp_sum(const float* in, float* out, int n) {
    int lane = item.get_sub_group().get_local_id()();
    float v = (item.get_local_id() < n) ? in[item.get_local_id()] : 0.0f;
    /* no native syncwarp on SYCL */ item.barrier() /* fallback */;
    // In-warp sum via shared memory.
    __shared__ float partial[WARP];
    partial[lane] = v;
    item.barrier(sycl::access::fence_space::global_space);
    if (lane == 0) {
        float s = 0.0f;
        for (int i = 0; i < WARP; ++i) s += partial[i];
        out[item.get_group(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);
    { /* decuda SYCL launch: queue.submit([&](sycl::handler& h) { h.parallel_for(sycl::range<3>{grid}, [=](sycl::item<3> it) { /* kernel `apply` body with thread indices from it.get_*() */ }); }); smem=none stream=default args=d_in, d_out, N */ };
    { /* decuda SYCL launch: queue.submit([&](sycl::handler& h) { h.parallel_for(sycl::range<3>{N / WARP}, [=](sycl::item<3> it) { /* kernel `warp_sum` body with thread indices from it.get_*() */ }); }); smem=none stream=default args=d_in, d_warp, N */ };

    cudaDeviceSynchronize();
    cudaFree(d_in);
    cudaFree(d_out);
    cudaFree(d_warp);
    return 0;
}