// Generated by decuda.
// OpenCL device code is the bulk of this file. The host-side calls
// (`cudaXxx`) have been rewritten to OpenCL equivalents inline// 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: unified/managed memory patterns.
//
// Exercises:
// - cudaMallocManaged (in DB -> hipMallocManaged for HIP// - __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// - __global__ and __device__ qualifiers
// - threadIdx.x, blockIdx.x, blockDim.x
// - cuda_runtime.h header
#include <CL/cl.h> /* 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.
/* use SVM: clSVMAlloc */ int managed_counter = 0
__device int atomic_increment(int* addr) {
return atomicAdd(addr, 1)}
__kernel void increment_kernel(int* counter, int n) {
int i = get_group_id(0) * get_local_size(0) + get_local_id(0) if (i < n) {
atomic_increment(counter) }
}
__kernel void scale_kernel(float* data, float scale, int n) {
int i = get_group_id(0) * get_local_size(0) + get_local_id(0) 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 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.
clEnqueueNDRangeKernel(queue, scale_kernel_kernel, 1, NULL, (size_t[1]){grid}, (size_t[1]){block}, 0, NULL, NULL) /* args: managed_data, 2.0f, N */ clEnqueueNDRangeKernel(queue, increment_kernel_kernel, 1, NULL, (size_t[1]){grid}, (size_t[1]){block}, 0, NULL, NULL) /* 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}