# Cuda Omp Translator

> Reference guide for evaluating LLM-generated translations between CUDA and OpenMP, covering memory model mapping, kernel launch patterns, shared memory, atomics, and common failure modes.

- Skill: `samyakjhaveri/cuda-omp-translator` (Agent Skill)
- Install (CLI): `npx skillmds add samyakjhaveri/cuda-omp-translator`
- Raw SKILL.md: https://api.skillmd.com/api/skills/samyakjhaveri/cuda-omp-translator/raw
- Safety review: PASS (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML, Coding & Dev Tools, Model Training & Fine-tuning
- Tags: Benchmarking, Code Review, Cuda, Gpu, Openmp, Parallel Programming, Translation
- Author: SamyakJhaveri (https://skillmd.com/u/samyakjhaveri)
- Updated: 2026-08-22
- Page: https://skillmd.com/skills/samyakjhaveri/cuda-omp-translator

---


# CUDA ↔ OpenMP Translation Guide

Reference for evaluating LLM-generated translations between CUDA and OpenMP. Organized by
pattern category — each section describes the source construct, the correct target construct,
and the failure modes LLMs commonly produce.

**Trigger:** `/cuda-omp-translator` or when reviewing CUDA↔OMP eval results.

## When to use

- Reviewing why an LLM translation got BUILD_FAIL or VERIFY_FAIL
- Writing paper sections about translation difficulty or pattern analysis
- Comparing translation quality across models for specific construct types
- Creating new benchmark specs for CUDA/OpenMP kernel pairs

## Core Translation Patterns

### 1. Kernel Launch → Parallel Region

**CUDA:**
```c
__global__ void kernel(float *data, int n) {
    int tid = blockIdx.x * blockDim.x + threadIdx.x;
    if (tid < n) data[tid] = data[tid] * 2.0f;
}
// Launch: kernel<<<grid, block>>>(d_data, n);
```

**OpenMP equivalent:**
```c
#pragma omp parallel for
for (int tid = 0; tid < n; tid++) {
    data[tid] = data[tid] * 2.0f;
}
```

**Common LLM failures:**
- Preserving `blockIdx`/`threadIdx` arithmetic instead of using loop index
- Missing `parallel for` — writing just `#pragma omp parallel` without work distribution
- Adding unnecessary `num_threads()` clause that limits parallelism

### 2. Device Memory → Stack/Heap Allocation

**CUDA:** `cudaMalloc`, `cudaMemcpy` (host↔device transfers)
**OpenMP:** Direct pointer use (shared memory space)

**Common LLM failures:**
- Leaving `cudaMalloc`/`cudaFree` calls that don't compile without CUDA runtime
- Translating `cudaMemcpy` to `memcpy` when data is already accessible (unnecessary copy)
- Not removing `__device__` / `__host__` qualifiers

### 3. Shared Memory → Thread-Local or Reduction

**CUDA:** `__shared__ float smem[BLOCK_SIZE];`
**OpenMP:** Depends on usage pattern:
- Read-only tile → no equivalent needed (cache handles it)
- Reduction accumulator → `#pragma omp parallel for reduction(+:sum)`
- Thread-local scratch → stack variable inside parallel region

**Common LLM failures:**
- Declaring a global array as shared-memory substitute (data race)
- Missing reduction clause — writing `sum += x` without `reduction(+:sum)`
- Translating shared memory as `threadprivate` when it should be a reduction

### 4. Atomic Operations

**CUDA:** `atomicAdd(&result, val);`
**OpenMP:** `#pragma omp atomic` or `#pragma omp critical`

**Common LLM failures:**
- Using `critical` where `atomic` suffices (performance kill, not correctness)
- Omitting atomic entirely — data race on shared accumulator
- Wrapping entire loop body in `critical` instead of just the update

### 5. Synchronization

**CUDA:** `__syncthreads()` (block-level barrier)
**OpenMP:** `#pragma omp barrier` (team-level barrier)

**Common LLM failures:**
- Placing barrier inside conditional (undefined behavior in OpenMP)
- Translating every `__syncthreads()` literally when the barrier is unnecessary in the flat parallel model
- Missing barrier when translating multi-phase algorithms (e.g., prefix scan)

### 6. Grid-Stride Loops

**CUDA:**
```c
for (int i = tid; i < n; i += gridDim.x * blockDim.x) { ... }
```

**OpenMP:** The `parallel for` schedule handles distribution — the grid-stride pattern disappears entirely.

**Common LLM failure:** Preserving the stride arithmetic inside the OMP parallel for, producing correct but unnecessarily complex code.

## Reverse Direction: OpenMP → CUDA

The reverse translation (OpenMP → CUDA) has distinct failure modes:

- **Missing bounds check:** OpenMP `parallel for` handles bounds implicitly; CUDA kernels need explicit `if (tid < n)` guards
- **Missing device memory management:** Forgetting `cudaMalloc`/`cudaMemcpy` for data that was just a pointer in OpenMP
- **Incorrect grid/block sizing:** LLMs often hardcode `<<<1, 256>>>` regardless of problem size
- **Missing `__global__` qualifier:** Defining the kernel as a regular function

## Diagnosis Checklist for Failed Translations

When an eval result shows BUILD_FAIL or VERIFY_FAIL for a CUDA↔OMP pair:

1. **BUILD_FAIL** — check for:
   - Leftover CUDA-specific types (`dim3`, `cudaError_t`, `__shared__`)
   - Missing OpenMP pragma on parallel loops
   - CUDA header includes (`cuda_runtime.h`) still present
   - Missing `-fopenmp` in build command (spec issue, not translation issue)

2. **VERIFY_FAIL** — check for:
   - Data races (missing `atomic`/`reduction`/`critical`)
   - Off-by-one in loop bounds vs CUDA thread index calculation
   - Floating-point reduction order differences (inherent — not a bug, see known-issues.md)
   - Uninitialized variables that CUDA zero-initializes but OpenMP doesn't

## Project-Specific Notes

- FP reduction-order divergence is common in parallel code — faithful translations may produce different bit-exact results due to floating-point associativity
- Always check `known-issues.md` KNOWN_FAIL list before investigating a failed translation
- Some synthesis asymmetries exist where macros or preprocessor directives differ between source and target paradigms

