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: 3D 7-point stencil with shared-memory halo exchange.
//
// Exercises:
//   - 3D grid and block (dim3 with three components)
//   - threadIdx.{x,y,z}, blockIdx.{x,y,z}, blockDim.{x,y,z}, gridDim.{x,y,z}
//   - __shared__ 3D tile with halo
//   - __syncthreads barriers
//   - __global__ kernel with multi-dimensional indexing
//   - cudaMalloc, cudaFree, cudaMemcpy
//   - cuda_runtime.h header
#include <sycl/sycl.hpp> /* was: cuda_runtime.h */

#define BX 8
#define BY 8
#define BZ 8
#define HALO 1

// TODO(decuda): rewrite as SYCL kernel lambda
 void stencil_3d(const float* in, float* out, int nx, int ny, int nz) {
    // Shared memory tile: interior + 1-cell halo on each side.
    __shared__ float tile[BZ + 2 * HALO][BY + 2 * HALO][BX + 2 * HALO];

    int tx = item.get_local_id();
    int ty = item.get_local_id();
    int tz = item.get_local_id();

    int gx = item.get_group(0) * item.get_local_range() + tx;
    int gy = item.get_group(0) * item.get_local_range() + ty;
    int gz = item.get_group(0) * item.get_local_range() + tz;

    int idx = gx + gy * nx + gz * nx * ny;

    // Load interior.
    if (gx < nx && gy < ny && gz < nz) {
        tile[tz + HALO][ty + HALO][tx + HALO] = in[idx];
    }

    // Load halos — each thread loads one halo cell from each face.
    // X-minus halo.
    if (tx < HALO && gx >= HALO && gy < ny && gz < nz) {
        tile[tz + HALO][ty + HALO][tx] = in[idx - HALO];
    }
    // X-plus halo.
    if (tx >= item.get_local_range() - HALO && gx + HALO < nx && gy < ny && gz < nz) {
        tile[tz + HALO][ty + HALO][tx + 2 * HALO] = in[idx + HALO];
    }
    // Y-minus halo.
    if (ty < HALO && gy >= HALO && gx < nx && gz < nz) {
        tile[tz + HALO][ty][tx + HALO] = in[idx - HALO * nx];
    }
    // Y-plus halo.
    if (ty >= item.get_local_range() - HALO && gy + HALO < ny && gx < nx && gz < nz) {
        tile[tz + HALO][ty + 2 * HALO][tx + HALO] = in[idx + HALO * nx];
    }
    // Z-minus halo.
    if (tz < HALO && gz >= HALO && gx < nx && gy < ny) {
        tile[tz][ty + HALO][tx + HALO] = in[idx - HALO * nx * ny];
    }
    // Z-plus halo.
    if (tz >= item.get_local_range() - HALO && gz + HALO < nz && gx < nx && gy < ny) {
        tile[tz + 2 * HALO][ty + HALO][tx + HALO] = in[idx + HALO * nx * ny];
    }

    item.barrier(sycl::access::fence_space::global_space);

    // 7-point stencil computation.
    if (gx < nx && gy < ny && gz < nz) {
        float c = tile[tz + HALO][ty + HALO][tx + HALO];
        float xp = tile[tz + HALO][ty + HALO][tx + HALO + 1];
        float xm = tile[tz + HALO][ty + HALO][tx + HALO - 1];
        float yp = tile[tz + HALO][ty + HALO + 1][tx + HALO];
        float ym = tile[tz + HALO][ty + HALO - 1][tx + HALO];
        float zp = tile[tz + HALO + 1][ty + HALO][tx + HALO];
        float zm = tile[tz + HALO - 1][ty + HALO][tx + HALO];
        out[idx] = 0.125f * (xp + xm + yp + ym + zp + zm) + c;
    }
}

int main(void) {
    const int NX = 64;
    const int NY = 64;
    const int NZ = 64;
    float* d_in = nullptr;
    float* d_out = nullptr;

    cudaMalloc((void**)&d_in, NX * NY * NZ * sizeof(float));
    cudaMalloc((void**)&d_out, NX * NY * NZ * sizeof(float));
    cudaMemcpy(d_in, d_in, NX * NY * NZ * sizeof(float), cudaMemcpyDeviceToDevice);

    dim3 grid(NX / BX, NY / BY, NZ / BZ);
    dim3 block(BX, BY, BZ);
    { /* decuda SYCL launch: queue.submit([&](sycl::handler& h) { h.parallel_for(sycl::range<3>{grid}, [=](sycl::item<3> it) { /* kernel `stencil_3d` body with thread indices from it.get_*() */ }); }); smem=none stream=default args=d_in, d_out, NX, NY, NZ */ };

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