custom-allocators
Custom allocator skill for memory allocation strategies. Use when implementing…
CUDA C/C++ skill for NVIDIA GPU kernel programming. Use when writing CUDA kernels, managing thread/block/grid hierarchy, optimizing memory access patterns, using streams and async copies, configuring nvcc flags, or integrating Thrust. Activates on queries about CUDA kernels,
$ npx -y skills add mohitmishra786/low-level-dev-skills --skill cuda --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/cudaContext preview
The summary Claude sees to decide when to auto-load this skill.
CUDA C/C++ skill for NVIDIA GPU kernel programming. Use when writing CUDA kernels, managing thread/block/grid hierarchy, optimizing memory access patterns, using streams and async copies, configuring nvcc flags, or integrating Thrust. Activates on queries about CUDA kernels,
name: cuda description: CUDA C/C++ skill for NVIDIA GPU kernel programming. Use when writing CUDA kernels, managing thread/block/grid hierarchy, optimizing memory access patterns, using streams and async copies, configuring nvcc flags, or integrating Thrust. Activates on queries about CUDA kernels, nvcc, shared memory, warp divergence, occupancy, or Thrust.
Guide agents through NVIDIA CUDA C/C++ development: kernel launch configuration, the memory hierarchy from registers through global memory, asynchronous execution with streams, nvcc compilation flags, Thrust library usage, and diagnosing common performance pitfalls like warp divergence and uncoalesced memory access.
CUDA organizes work as threads grouped into blocks, blocks grouped into a grid.
Thread hierarchy ├── grid (1D/2D/3D) │ └── block (1D/2D/3D, max 1024 threads) │ └── thread (threadIdx, blockIdx, blockDim, gridDim)
// vector_add.cu
#include <cuda_runtime.h>
#include <stdio.h>
__global__ void vector_add(const float *a, const float *b, float *c, int n) {
int i = blockIdx.x * blockDim.x + threadIdx.x;
if (i < n)
c[i] = a[i] + b[i];
}
int main(void) {
const int n = 1 << 20;
size_t bytes = n * sizeof(float);
float *h_a, *h_b, *h_c, *d_a, *d_b, *d_c;
cudaMalloc(&d_a, bytes);
cudaMalloc(&d_b, bytes);
cudaMalloc(&d_c, bytes);
// ... host init and cudaMemcpy H2D ...
int threads = 256;
int blocks = (n + threads - 1) / threads;
vector_add<<<blocks, threads>>>(d_a, d_b, d_c, n);
cudaDeviceSynchronize();
cudaMemcpy(h_c, d_c, bytes, cudaMemcpyDeviceToHost);
cudaFree(d_a); cudaFree(d_b); cudaFree(d_c);
return 0;
}| Memory | Scope | Latency | Typical use | |--------|-------|---------|-------------| | Registers | Per-thread | ~1 cycle | Local scalars, loop indices | | Shared (`__shared__`) | Per-block | ~5 cycles | Tile data, halo exchange | | Global | All threads | ~400+ cycles | Large arrays, coalesced access | | Constant (`__constant__`) | Read-only, cached | Fast broadcast | Kernel parameters, lookup tables | | Texture | Cached 2D access | Cached | Image sampling, irregular reads |
Shared memory example (matrix tile):
#define TILE 16
__global__ void matmul_tiled(const float *A, const float *B, float *C, int N) {
__shared__ float As[TILE][TILE];
__shared__ float Bs[TILE][TILE];
int row = blockIdx.y * TILE + threadIdx.y;
int col = blockIdx.x * TILE + threadIdx.x;
float sum = 0.0f;
for (int t = 0; t < (N + TILE - 1) / TILE; t++) {
As[threadIdx.y][threadIdx.x] = (row < N && t * TILE + threadIdx.x < N)
? A[row * N + t * TILE + threadIdx.x] : 0.0f;
Bs[threadIdx.y][threadIdx.x] = (col < N && t * TILE + threadIdx.y < N)
? B[(t * TILE + threadIdx.y) * N + col] : 0.0f;
__syncthreads();
for (int k = 0; k < TILE; k++)
sum += As[threadIdx.y][k] * Bs[k][threadIdx.x];
__syncthreads();
}
if (row < N && col < N)
C[row * N + col] = sum;
}cudaStream_t stream1, stream2; cudaStreamCreate(&stream1); cudaStreamCreate(&stream2); cudaMemcpyAsync(d_a, h_a, bytes, cudaMemcpyHostToDevice, stream1); cudaMemcpyAsync(d_b, h_b, bytes, cudaMemcpyHostToDevice, stream2); vector_add<<<blocks, threads, 0, stream1>>>(d_a, d_b, d_c, n); cudaMemcpyAsync(h_c, d_c, bytes, cudaMemcpyDeviceToHost, stream1); cudaStreamSynchronize(stream1);
Pinned host memory (`cudaMallocHost`) enables true async DMA overlap with kernel execution.
# Single architecture (local GPU) nvcc -O3 -arch=sm_80 -o prog vector_add.cu # Fat binary for multiple GPUs nvcc -O3 \ -gencode arch=compute_80,code=sm_80 \ -gencode arch=compute_90,code=sm_90 \ -o prog vector_add.cu # Debug symbols for cuda-gdb nvcc -G -g -O0 -arch=sm_80 -o prog_debug vector_add.cu # Show PTX/SASS nvcc -arch=sm_80 -ptx vector_add.cu nvcc -arch=sm_80 -cubin vector_add.cu cuobjdump -sass prog
Common flags:
| Flag | Effect | |------|--------| | `-O3` | Aggressive optimization | | `-G` | Disable optimizations for debugging | | `-lineinfo` | Source-line correlation in profiles | | `-Xcompiler -fopenmp` | Host-side OpenMP with CUDA | | `--use_fast_math` | Faster, less precise math intrinsics | | `-maxrregcount=N` | Cap registers to raise occupancy |
# CUDA Occupancy Calculator (spreadsheet) or programmatic: ./occupancy_tool --kernel vector_add --block-size 256 --regs 16 --smem 0
Decision tree:
Kernel slow? ├── Low occupancy (< 25%) → reduce registers, shared mem, or block size ├── Memory-bound → check coalescing, use shared memory tiling └── Compute-bound → increase arithmetic intensity, use tensor cores
Use `cudaOccupancyMaxActiveBlocksPerMultiprocessor` API or Nsight Compute `sm__warps_active.avg.pct_of_peak_sustained_active` metric.
#include <thrust/device_vector.h> #include <thrust/sort.h> #include <thrust/reduce.h> thrust::device_vector<int> d_vec(1000000); thrust::sort(d_vec.begin(), d_vec.end()); int sum = thrust::reduce(d_vec.begin(), d_vec.end());
Thrust handles temporary storage and kernel launches internally. Prefer Thrust for sort/scan/reduce; write custom kernels for domain-specific fused operations.
**Warp divergence**: Threads in a warp (32) execute in SIMT l
A curated suite of AI agent skills for systems and low-level programming — C/C++, Rust, Zig, GPU, bare-metal firmware, Linux kernel/driver development, computer architecture, compiler internals, HPC, and more.
Repo: mohitmishra786/low-level-dev-skills
Custom allocator skill for memory allocation strategies. Use when implementing…
NUMA programming skill for multi-socket memory locality. Use when detecting NUMA topology,…
AF_XDP skill for high-performance XDP sockets. Use when creating AF_XDP sockets, configuring…
DPDK skill for userspace packet I/O. Use when initializing EAL, configuring PMD drivers,…
io_uring skill for Linux async I/O. Use when building high-performance servers with liburing,…
Bare-metal ADC and DAC skill. Use when configuring analog sampling, DMA-driven ADC,…