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: unified/managed memory patterns.
//
// Exercises:
//   - cudaMallocManaged (in DB -> hipMallocManaged for HIP; flagged for SYCL/Rust/OpenCL)
//   - __managed__ qualifier (in DB -> per-target rewrite)
//   - cudaHostAlloc (in DB -> renamed for HIP)
//   - cudaMallocHost (in DB -> renamed for HIP)
//   - cudaMemcpy (in DB -> renamed for HIP)
//   - cudaDeviceSynchronize (in DB -> hipDeviceSynchronize for HIP; flagged for SYCL/Rust/OpenCL)
//   - __global__ and __device__ qualifiers
//   - threadIdx.x, blockIdx.x, blockDim.x
//   - cuda_runtime.h header
#include <sycl/sycl.hpp> /* was: cuda_runtime.h */

// __managed__ memory: accessible from both host and device without explicit
// cudaMemcpy. decuda rewrites __managed__ per target and flags the
// managed-memory runtime APIs for manual review.
/* managed -> SYCL USM */ int managed_counter = 0;

// SYCL device function [[clang::always_inline]] int atomic_increment(int* addr) {
    return atomicAdd(addr, 1);
}

// TODO(decuda): rewrite as SYCL kernel lambda
 void increment_kernel(int* counter, int n) {
    int i = item.get_group(0) * item.get_local_range() + item.get_local_id();
    if (i < n) {
        atomic_increment(counter);
    }
}

// TODO(decuda): rewrite as SYCL kernel lambda
 void scale_kernel(float* data, float scale, int n) {
    int i = item.get_group(0) * item.get_local_range() + item.get_local_id();
    if (i < n) {
        data[i] *= scale;
    }
}

int main(void) {
    const int N = 1 << 16;

    // Managed memory: no explicit cudaMemcpy needed between host and device.
    // cudaMallocManaged is in the DB for HIP (-> hipMallocManaged);
    // for SYCL/Rust/OpenCL it is preserved verbatim and flagged.
    float* managed_data = nullptr;
    cudaMallocManaged((void**)&managed_data, N * sizeof(float));

    // Initialize on the host (managed memory is directly accessible).
    for (int i = 0; i < N; i++) {
        managed_data[i] = (float)i;
    }

    // Pinned host memory for comparison.
    float* pinned_data = nullptr;
    cudaMallocHost((void**)&pinned_data, N * sizeof(float));

    dim3 grid(N / 256);
    dim3 block(256);

    // Launch on managed memory — no cudaMemcpy required.
    { /* decuda SYCL launch: queue.submit([&](sycl::handler& h) { h.parallel_for(sycl::range<3>{grid}, [=](sycl::item<3> it) { /* kernel `scale_kernel` body with thread indices from it.get_*() */ }); }); smem=none stream=default args=managed_data, 2.0f, N */ };
    { /* decuda SYCL launch: queue.submit([&](sycl::handler& h) { h.parallel_for(sycl::range<3>{grid}, [=](sycl::item<3> it) { /* kernel `increment_kernel` body with thread indices from it.get_*() */ }); }); smem=none stream=default args=&managed_counter, N */ };

    // cudaDeviceSynchronize is in the DB for HIP (-> hipDeviceSynchronize);
    // for SYCL/Rust/OpenCL it is preserved verbatim and flagged.
    cudaDeviceSynchronize();

    // Read back managed memory directly on the host.
    printf("counter = %d, data[0] = %f\n", managed_counter, managed_data[0]);

    // Copy to pinned memory for explicit transfer path.
    cudaMemcpy(pinned_data, managed_data, N * sizeof(float), cudaMemcpyDeviceToHost);

    cudaFree(managed_data);
    cudaFreeHost(pinned_data);
    return 0;
}