#!/bin/bash # CUDA Kernel Guard — detects CPU/host leaks in .cu kernel files. # # Production H100 system. CUDA kernels must be pure device code. # This guard catches patterns that force CPU synchronization, # host memory access, or debug output in production kernels. # # Usage: # scripts/cuda-kernel-guard.sh # # Exit codes: # 0 = clean # 1 = violation detected # # Suppress reviewed lines with: // cuda-ok: set -euo pipefail FILE="${1:-}" if [ -z "$FILE" ] || [ ! -f "$FILE" ]; then exit 0 fi # Only check .cu and .cuh files case "$FILE" in *.cu|*.cuh) ;; *) exit 0 ;; esac LEAK_PATTERNS=( # ─── printf in device code (forces implicit sync, kills perf) ─── # One printf in a kernel with 1024 threads = 1024 serial host writes. 'printf\s*\(' # ─── Host API calls from device code (illegal or sync-forcing) ─── 'cudaMalloc' 'cudaFree' 'cudaMemcpy\s*\(' 'cudaMemset\s*\(' 'cudaDeviceSynchronize' 'cudaStreamSynchronize' 'cudaEventSynchronize' # ─── Host memory access patterns ─── # malloc/free/new/delete in device code = UB or host fallback '\bmalloc\s*\(' '\bfree\s*\(' '\bnew\s+\w+[\[\(]' '\bdelete\s+\w+' # ─── Host function markers in kernel files ─── # __host__ functions shouldn't be in kernel .cu files (they belong in .rs host code) '__host__\s+[^_]' # ─── CPU-side file I/O (absolutely forbidden in kernels) ─── '\bfopen\s*\(' '\bfwrite\s*\(' '\bfprintf\s*\(' '\bstdout\b' '\bstderr\b' # ─── assert() in device code (triggers host trap, kills kernel) ─── # Use __trap() or return early instead '\bassert\s*\(' # ─── Double-precision math in f32 kernels (use f suffix) ─── # exp/log/sin/cos are DOUBLE precision (4x slower on H100 tensor cores). # expf/logf/sinf/cosf are single-precision (correct for f32 kernels). # __expf/__logf are fast-math (~2 ULP) — optional, not required. # Only flag the double-precision versions (no f suffix, not prefixed with __) '[^_a-z]\bexp\s*\([^f]' '[^_a-z]\blog\s*\([^f]' '[^_a-z]\bsin\s*\([^f]' '[^_a-z]\bcos\s*\([^f]' '[^_a-z]\bsqrt\s*\([^f]' ) # Patterns that are OK (suppress false positives) SAFE_PATTERNS=( '// cuda-ok:' '// debug-only:' '#if 0' '#ifdef CUDA_DEBUG' ) found=0 for pattern in "${LEAK_PATTERNS[@]}"; do hits=$(grep -nE "$pattern" "$FILE" 2>/dev/null || true) # Filter out safe patterns for safe in "${SAFE_PATTERNS[@]}"; do if [ -n "$hits" ]; then hits=$(echo "$hits" | grep -v "$safe" || true) fi done # Filter out comments: full-line (//, /*, *) and trailing /* */ comments if [ -n "$hits" ]; then hits=$(echo "$hits" | grep -v '[0-9]*:\s*//' \ | grep -v '[0-9]*:\s*\*' \ | grep -v '[0-9]*:\s*/\*' \ || true) # For trailing comments: if the match is ONLY inside /* ... */, skip it if [ -n "$hits" ]; then hits=$(echo "$hits" | while IFS= read -r line; do # Strip trailing /* comment */ from the line, then re-check pattern stripped=$(echo "$line" | sed 's|/\*[^*]*\*/||g') if echo "$stripped" | grep -qE "$pattern" 2>/dev/null; then echo "$line" fi done || true) fi fi if [ -n "$hits" ]; then if [ "$found" -eq 0 ]; then echo "CUDA KERNEL LEAK: $FILE" found=1 fi echo "$hits" | while IFS= read -r line; do echo " $line" done fi done if [ "$found" -eq 1 ]; then echo "" echo "⛔ CPU/host operations detected in CUDA kernel." echo " printf → remove or guard with #ifdef CUDA_DEBUG" echo " cudaMalloc/Free → pre-allocate in host .rs code" echo " sinf/cosf/expf/logf → use __sinf/__cosf/__expf/__logf" echo " assert → use __trap() or return" exit 1 fi exit 0