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>

// Advanced fixture: warp-level primitives and cooperative patterns.
//
// Exercises:
//   - __shfl_sync (NOT a known builtin -> preserved, flagged)
//   - __ballot_sync (NOT a known builtin -> preserved, flagged)
//   - __any_sync (NOT a known builtin -> preserved, flagged)
//   - __all_sync (NOT a known builtin -> preserved, flagged)
//   - __activemask (NOT a known builtin -> preserved, flagged)
//   - __laneid (known builtin -> rewritten per target)
//   - __syncwarp (known builtin -> rewritten per target)
//   - warpSize (known builtin -> rewritten per target)
//   - __syncthreads (known builtin -> rewritten per target)
//   - atomicAdd, atomicMin, atomicMax (known atomics -> preserved/rewritten)
//   - __global__, __device__, __shared__ qualifiers
//   - threadIdx.x, blockIdx.x, blockDim.x, gridDim.x
//   - cuda_runtime.h header
#include <sycl/sycl.hpp> /* was: cuda_runtime.h */

#define WARP 32

// SYCL device function [[clang::always_inline]] int warp_sum(int v) {
    // __shfl_sync is NOT in decuda's builtin table — preserved verbatim.
    for (int offset = WARP / 2; offset > 0; offset /= 2) {
        v += sycl::sub_group::shuffle(0xFFFFFFFFu, v, item.get_sub_group().get_local_id()() - offset);
    }
    return v;
}

// SYCL device function [[clang::always_inline]] int warp_ballot(int predicate) {
    // __ballot_sync is NOT in decuda's builtin table — preserved verbatim.
    return sycl::sub_group::ballot(0xFFFFFFFFu, predicate);
}

// SYCL device function [[clang::always_inline]] int warp_any(int predicate) {
    // __any_sync is NOT in decuda's builtin table — preserved verbatim.
    return sycl::sub_group::any(0xFFFFFFFFu, predicate);
}

// SYCL device function [[clang::always_inline]] int warp_all(int predicate) {
    // __all_sync is NOT in decuda's builtin table — preserved verbatim.
    return sycl::sub_group::all(0xFFFFFFFFu, predicate);
}

// TODO(decuda): rewrite as SYCL kernel lambda
 void warp_demo(const int* in, int* out, int n) {
    __shared__ int shared[WARP];
    int tid = item.get_local_id();
    int gid = item.get_group(0) * item.get_local_range() + tid;
    int lane = item.get_sub_group().get_local_id()();

    // Load value and compute predicate.
    int v = (gid < n) ? in[gid] : 0;
    int pred = (v > 0) ? 1 : 0;

    // Warp-level vote: how many lanes have pred == 1?
    int ballot = warp_ballot(pred);
    int any_pos = warp_any(pred);
    int all_pos = warp_all(pred);
    int active = sycl::sub_group::get_local_range();

    // Warp-level sum via shuffle.
    v = warp_sum(v);
    /* no native syncwarp on SYCL */ item.barrier() /* fallback */;

    if (lane == 0) {
        shared[tid / WARP] = v;
        atomicAdd(out, v);
        atomicMin(out + 1, ballot);
        atomicMax(out + 2, active);
    }
    item.barrier(sycl::access::fence_space::global_space);

    // Record vote results from lane 0 of the first warp.
    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);
    { /* decuda SYCL launch: queue.submit([&](sycl::handler& h) { h.parallel_for(sycl::range<3>{grid}, [=](sycl::item<3> it) { /* kernel `warp_demo` body with thread indices from it.get_*() */ }); }); smem=none stream=default args=d_in, d_out, N */ };

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