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.
// OpenCL device code is the bulk of this file. The host-side calls
// (`cudaXxx`) have been rewritten to OpenCL equivalents inline; the
// surrounding host program still needs a cl_context + cl_queue, not
// included here. Look for TODO(decuda) markers for items requiring
// manual attention.

// Advanced fixture: multi-GPU device management with error handling and
// pinned host memory.
//
// Exercises:
//   - cudaGetDeviceCount, cudaSetDevice, cudaGetDevice (in DB -> renamed for HIP)
//   - cudaGetLastError, cudaGetErrorString (in DB -> renamed for HIP)
//   - cudaDeviceSynchronize (in DB -> hipDeviceSynchronize for HIP; flagged for SYCL/Rust/OpenCL)
//   - cudaHostAlloc (in DB -> renamed for HIP)
//   - Error-checking macro pattern (preserved verbatim)
//   - __global__ kernel
//   - threadIdx.x, blockIdx.x, blockDim.x
//   - cuda_runtime.h header
#include <CL/cl.h> /* was: cuda_runtime.h */
#include <stdio.h>

#define CUDA_CHECK(call) do { \
    cl_int() err = (call); \
    if (err != cudaSuccess) { \
        printf("CUDA error: %s at %s:%d\n", cudaGetErrorString(err), __FILE__, __LINE__); \
        cudaGetLastError(); \
    } \
} while (0)

__kernel void fill_kernel(float* data, float value, int n) {
    int i = get_group_id(0) * get_local_size(0) + get_local_id(0);
    if (i < n) {
        data[i] = value;
    }
}

int main(void) {
    int device_count = 0;
    CUDA_CHECK(cudaGetDeviceCount(&device_count));
    if (device_count == 0) {
        printf("No CUDA devices found.\n");
        return 1;
    }

    // Run on each device.
    for (int dev = 0; dev < device_count; dev++) {
        CUDA_CHECK(cudaSetDevice(dev));

        int current = 0;
        CUDA_CHECK(cudaGetDevice(&current));
        printf("Using device %d\n", current);

        const int N = 1024;
        float* d_data = nullptr;
        CUDA_CHECK(cudaMalloc((void**)&d_data, N * sizeof(float)));

        // Pinned host memory for faster transfers.
        float* h_data = nullptr;
        CUDA_CHECK(cudaHostAlloc((void**)&h_data, N * sizeof(float), 0));

        dim3 grid(N / 256);
        dim3 block(256);
        clEnqueueNDRangeKernel(queue, fill_kernel_kernel, 1, NULL, (size_t[1]){grid}, (size_t[1]){block}, 0, NULL, NULL) /* args: d_data, 3.14f, N */;

        // cudaDeviceSynchronize is NOT in the DB — it is preserved verbatim
        // and flagged in the migration report for non-HIP targets.
        cudaDeviceSynchronize();

        CUDA_CHECK(cudaMemcpy(h_data, d_data, N * sizeof(float), cudaMemcpyDeviceToHost));
        printf("device %d: h_data[0] = %f\n", dev, h_data[0]);

        CUDA_CHECK(cudaFree(d_data));
        cudaFreeHost(h_data);
    }

    return 0;
}