К основному содержанию
правило

cuda — правило для Cursor: как писать CUDA C++

Правило задаёт Cursor стиль работы с CUDA C++: проверка ошибок API, разделение host и device кода, оптимизация ядер. Пригодится, если пишете GPU-код и устали от молчаливых падений.

Установить в Cursor · Вручную: положить файлы Все способы и платформы ↓
.cursor/rules/cuda.mdc
Открыть на GitHub

Что делает cuda

Правило подключается файлом .cursor/rules/cuda.mdc и действует на все файлы проекта. Внутри — набор требований к CUDA C++: оборачивать вызовы API в макрос проверки ошибок, отделять host-оркестрацию от device-вычислений, давать функциям суффиксы _kernel и _device, а переменным в разделяемой памяти — префикс smem_.

Дальше идут приёмы по памяти и производительности. RAII-обёртки для device-буферов и потоков вместо ручного cudaFree, cudaMallocPitch для двумерных массивов, cudaMemcpyAsync с несколькими потоками, чтобы передача данных шла параллельно с вычислениями. Для общих операций правило советует брать готовые библиотеки CUDA-X: cuBLAS, cuFFT, cuDNN, cuML — вместо собственного GEMM.

Есть и про структуру данных: раскладка SoA вместо массива структур, квалификаторы const и __restrict__ для подсказок компилятору, борьба с расхождением варпов через предикаты и таблицы подстановки. Правило привязано к Cursor: в Claude, Codex или Copilot тот же текст лежит по другим путям, и без переноса файла оно там не заработает.

Какие задачи решает

  • поймать ошибку CUDA API сразу, а не через падение в другом месте
  • разнести host-логику и device-ядра по разным файлам
  • убрать утечки device-памяти через RAII-обёртки
  • скрыть задержку копирования данных между CPU и GPU
  • выровнять строки двумерной матрицы под coalesced-доступ

Примеры запросов агенту

  • Отрефактори этот kernel: убери расхождение варпов и добавь проверку ошибок через CUDA_CHECK
  • Перепиши аллокацию device-памяти на RAII-обёртку и раздели host и device код по файлам
  • Замени самописный матричный умножитель на вызов cuBLAS

Как установить cuda

Вручную: положить файлы

.cursor/rules/cuda.mdc

Во frontmatter: description, globs, alwaysApply

По шагам, с командами для каждой платформы: Cursor rules: файлы .mdc, четыре режима и замена .cursorrules

Вопросы о cuda

Как установить правило cuda в Cursor?

Создайте файл .cursor/rules/cuda.mdc в корне проекта и вставьте в него содержимое правила. Cursor подхватит его автоматически для файлов по маске **/*.

Что делает правило cuda?

Оно задаёт агенту соглашения по CUDA C++: проверка ошибок API, разделение host и device кода, именование ядер и device-функций, работа с памятью и потоками, оптимизация доступа к данным.

Правило подойдёт для Claude или GitHub Copilot?

Текст тот же, но пути другие: .claude/rules/cuda.md для Claude и .github/instructions/cuda.instructions.md для GitHub Copilot. Файл придётся положить отдельно для каждой платформы.

Исходный текст

cuda.mdc · CC0-1.0
---
description: Definitive guidelines for writing high-performance, maintainable, and error-resistant CUDA C++ code, focusing on modern practices, memory management, kernel optimization, and robust error handling.
globs: **/*
---
# CUDA Best Practices

This guide outlines the essential practices for developing efficient and maintainable CUDA C++ applications. Adhere to these rules to maximize GPU throughput, reduce debugging time, and ensure code quality across projects.

## 1. Code Organization and Structure

### 1.1 Robust Error Handling
**Always wrap CUDA API calls in an error-checking macro.** This prevents silent failures and provides immediate, actionable debugging information.

❌ BAD:
```cpp
cudaMalloc(&d_data, size);
// ... potentially crash later without knowing why
```

✅ GOOD:
```cpp
#define CUDA_CHECK(call)                                                          \
    do {                                                                          \
        cudaError_t err = call;                                                   \
        if (err != cudaSuccess) {                                                 \
            fprintf(stderr, "CUDA Error: %s:%d: %s\n", __FILE__, __LINE__, cudaGetErrorString(err)); \
            exit(EXIT_FAILURE);                                                   \
        }                                                                         \
    } while (0)

// Usage:
CUDA_CHECK(cudaMalloc(&d_data, size));
kernel<<<grid, block>>>(d_data);
CUDA_CHECK(cudaGetLastError()); // Check for kernel launch errors
```

### 1.2 Host-Device Separation
Clearly separate host (CPU) orchestration logic from device (GPU) computation.

❌ BAD:
```cpp
// host_code.cu
void processData() {
    cudaMalloc(&d_data, size); // Mixed host/device
    kernel<<<...>>>(d_data);
}
```

✅ GOOD:
```cpp
// host_manager.cpp
void allocateAndLaunch(float* h_in, int N) {
    float *d_in;
    CUDA_CHECK(cudaMalloc((void**)&d_in, N * sizeof(float)));
    CUDA_CHECK(cudaMemcpy(d_in, h_in, N * sizeof(float), cudaMemcpyHostToDevice));
    myKernel_kernel<<<N/256 + 1, 256>>>(d_in, N);
    CUDA_CHECK(cudaGetLastError());
    CUDA_CHECK(cudaFree(d_in));
}

// device_kernels.cu
__global__ void myKernel_kernel(float* d_in, int N) {
    int idx = blockIdx.x * blockDim.x + threadIdx.x;
    if (idx < N) { d_in[idx] *= 2.0f; }
}
```

### 1.3 Consistent Naming Conventions
Use clear suffixes and prefixes to distinguish CUDA components.
*   `_kernel`: For `__global__` functions.
*   `_device`: For `__device__` functions.
*   `smem_`: For `__shared__` variables.
*   `k` prefix: For `__constant__` memory or compile-time constants.

❌ BAD:
```cpp
void compute(float* data); // Ambiguous
__shared__ int temp;
```

✅ GOOD:
```cpp
__global__ void myCompute_kernel(float* d_data);
__device__ float calculate_device(float val);
extern __shared__ float smem_scratch[];
__constant__ const int kTileSize = 32;
```

### 1.4 Modularity
Decompose large kernels into smaller, focused `__device__` functions.

❌ BAD:
```cpp
__global__ void monolithicKernel(float* d_data, int N) { /* Do everything here */ }
```

✅ GOOD:
```cpp
__device__ float processElement_device(float val) { return val * val + 1.0f; }

__global__ void modularKernel(float* d_in, int N) {
    int global_idx = blockIdx.x * blockDim.x + threadIdx.x;
    if (global_idx < N) {
        d_in[global_idx] = processElement_device(d_in[global_idx]);
    }
}
```

## 2. Common Patterns and Anti-patterns

### 2.1 Modern Memory Management (RAII)
Use RAII wrappers for device memory and streams to prevent leaks.

❌ BAD:
```cpp
float* d_data; cudaMalloc(&d_data, size); // ... cudaFree(d_data); // Easy to forget
```

✅ GOOD:
```cpp
// Use a robust library or std::unique_ptr with custom deleter in production.
template<typename T> struct CudaDeviceBuffer {
    T* ptr = nullptr; size_t count = 0;
    CudaDeviceBuffer(size_t n) : count(n) { CUDA_CHECK(cudaMalloc(&ptr, n * sizeof(T))); }
    ~CudaDeviceBuffer() { if (ptr) CUDA_CHECK(cudaFree(ptr)); }
    T* get() { return ptr; }
};
// Usage: CudaDeviceBuffer<float> d_data(N); // Auto-freed on scope exit
```

### 2.2 Aligned Memory Allocation
For 2D arrays, use `cudaMallocPitch` for proper alignment and coalescing.

❌ BAD:
```cpp
cudaMalloc(&d_matrix, width * height * sizeof(float)); // Misaligned rows possible
```

✅ GOOD:
```cpp
float* d_matrix; size_t pitch; // Stored in bytes
CUDA_CHECK(cudaMallocPitch((void**)&d_matrix, &pitch, width * sizeof(float), height));
// Access in kernel: d_matrix[row * (pitch / sizeof(float)) + col];
```

### 2.3 Overlap Data Transfer and Computation
Utilize `cudaMemcpyAsync` with multiple streams to hide data transfer latency.

❌ BAD:
```cpp
cudaMemcpy(d_data, h_data, size, cudaMemcpyHostToDevice); // Synchronous
kernel<<<...>>>(d_data);
```

✅ GOOD:
```cpp
cudaStream_t stream1, stream2;
CUDA_CHECK(cudaStreamCreate(&stream1));
// Segment 1: Transfer H->D, Compute, Transfer D->H
CUDA_CHECK(cudaMemcpyAsync(d_data_seg1, h_data_seg1, size_seg1, cudaMemcpyHostToDevice, stream1));
kernel_seg1<<<...>>>(d_data_seg1, stream1);
CUDA_CHECK(cudaMemcpyAsync(h_result_seg1, d_result_seg1, size_seg1, cudaMemcpyDeviceToHost, stream1));
// ... (similar for stream2) ...
CUDA_CHECK(cudaStreamSynchronize(stream1));
CUDA_CHECK(cudaStreamDestroy(stream1));
```

### 2.4 Minimize Warp Divergence
Refactor conditional logic to reduce divergent branches within a warp. Use lookup tables or predicate execution.

❌ BAD:
```cpp
if (idx % 2 == 0) { d_data[idx] *= 2; } else { d_data[idx] += 1; }
```

✅ GOOD:
```cpp
int multiplier = (idx % 2 == 0) ? 2 : 1;
int adder = (idx % 2 == 0) ? 0 : 1;
d_data[idx] = d_data[idx] * multiplier + adder;
```

### 2.5 Use `__restrict__` and `const` Qualifiers
Enable compiler optimizations by explicitly declaring non-aliased pointers and read-only data.

❌ BAD:
```cpp
__global__ void add(float* a, float* b, float* c, int N) { /* ... */ }
```

✅ GOOD:
```cpp
__global__ void add(const float* __restrict__ a, const float* __restrict__ b, float* __restrict__ c, int N) {
    int idx = blockIdx.x * blockDim.x + threadIdx.x;
    if (idx < N) { c[idx] = a[idx] + b[idx]; }
}
```

### 2.6 Data Layout: Structures-of-Arrays (SoA)
Organize data as SoA for better memory coalescing, especially for frequently accessed fields.

❌ BAD:
```cpp
struct Particle { float x, y, z; }; Particle* particles = new Particle[N];
```

✅ GOOD:
```cpp
struct ParticlesSoA { float *x, *y, *z; }; // Allocate each array separately
```

### 2.7 Leverage CUDA-X Libraries
For common operations (BLAS, FFT, DNN), use highly optimized CUDA-X libraries (cuBLAS, cuFFT, cuDNN, cuML).

❌ BAD:
```cpp
__global__ void myMatrixMul_kernel(...) { /* complex GEMM logic */ }
```

✅ GOOD:
```cpp
cublasHandle_t handle; CUDA_CHECK(cublasCreate(&handle));
// ... setup matrices ...
CUDA_CHECK(cublasSgemm(handle, CUBLAS_OP_N, CUBLAS_OP_N, M, N, K, &alpha, d_A, M, d_B, K, &beta, d_C, M));
CUDA_CHECK(cublasDestroy(handle));
```

### 2.8 Embrace CUDA Tile (Toolkit 13.1+)
For tile-based tensor operations, use the new CUDA Tile programming model and cuTile Python API. This simplifies complex tiling logic and targets specialized hardware.

✅ GOOD:
```cpp
// Refer to NVIDIA documentation for specific CUDA Tile API usage.
// This abstracts away explicit shared memory management and synchronization for tiling.
// E.g., using cuTile Python API to express high-level tensor operations.
```

## 3. Performance Considerations

### 3.1 Memory Coalescing
Ensure global memory accesses by threads within a warp are contiguous and aligned.

❌ BAD:
```cpp
d_matrix[threadIdx.x * N + blockIdx.x]; // Strided access
```

✅ GOOD:
```cpp
d_matrix[blockIdx.x * blockDim.x + threadIdx.x]; // Coalesced access
```

### 3.2 Shared Memory Optimization
Use shared memory to cache frequently accessed global memory data. Be mindful of bank conflicts.

❌ BAD:
```cpp
__shared__ float smem_data[256]; float val = smem_data[threadIdx.x * 2]; // Bank conflicts
```

✅ GOOD:
```cpp
__shared__ float smem_data[256]; float val = smem_data[threadIdx.x]; // No bank conflicts
```

### 3.3 Constant Memory
Use `__constant__` memory for read-only data uniform across all threads. It has a fast, cached access path.

✅ GOOD:
```cpp
__constant__ float kCoefficients[10];
__global__ void process_kernel(float* d_data) {
    int idx = blockIdx.x * blockDim.x + threadIdx.x;
    if (idx < N) { d_data[idx] *= kCoefficients[0]; } // Fast access
}
```

## 4. Common Pitfalls and Gotchas

### 4.1 Unchecked API Calls
As covered in 1.1, neglecting error checks leads to hard-to-debug issues.

### 4.2 Excessive `__syncthreads()`
Overuse of `__syncthreads()` can severely limit occupancy and performance. Only synchronize when absolutely necessary.

### 4.3 Forgetting `cuda

© sanjeed5 · CC0-1.0 · sanjeed5/awesome-cursor-rules-mdc

Похожие правила IDE

Всё по теме «ИИ и ML» →
cuda-debugging mohitmishra786 Ведёт агента по отладке CUDA: cuda-gdb, Compute Sanitizer, дампы GPU и разбор ошибок 700/702. Пригодится, когда ядро падает или даёт неверный результат. CX Codex +1 301установок cuda-profiling mohitmishra786 Ведёт агента по профилированию CUDA-приложений: таймлайн в Nsight Systems, метрики ядер в Nsight Compute, разбор roofline и узких мест. CX Codex +1 316установок mojo-gpu-fundamentals modular Инструкция для ИИ-агентов по низкоуровневой разработке на Mojo под GPU NVIDIA, AMD и Apple silicon. Избавляет модель от попыток вставлять синтаксис CUDA. CX Codex +1 2 600установок tilegym-converting-cutile-to-julia TileGym Team Переносит GPU-ядра cuTile с Python на Julia cuTile.jl с учётом 1-индексации и колоночной памяти. Пригодится при портировании вычислений под архитектуру Blackwell. CX Codex +1 1 500установок tilegym-converting-cutile-to-triton TileGym Team Переводит GPU-ядра cuTile на Triton по фазам: анализ, конвертация, проверка, тесты, бенчмарк. Плюс разбор ошибок при переносе. CX Codex +1 1 500установок pod-doctor runpod Находит причины сбоев в подах Runpod: ошибки прокси 502, пропажу GPU после перезагрузки и зависания контейнеров. Работает в режиме чтения через MCP-инструменты Runpod. CX Codex +1 2 600установок

Из того же набора69

django-rest-framework Правило Cursor, которое задаёт агенту единый стиль разработки API на Django REST Framework: структура проекта, сериализаторы, ViewSets. ★ 3 579звёзд репо digitalocean Правило для Cursor задаёт, как строить и разворачивать приложения в DigitalOcean: VPC, managed-сервисы, контейнеры. ★ 3 579звёзд репо datadog Правило для Cursor задаёт стандарты Datadog: обязательные теги service, env и version, структурные логи и порядок в именах метрик. ★ 3 579звёзд репо d3 Правило для Cursor задаёт, как писать код визуализаций на D3.js v7+: модульные импорты, selection.join() вместо ручного enter/update/exit, стили через CSS. ★ 3 579звёзд репо codemirror Правило для Cursor задаёт, как писать редакторы на CodeMirror 6: модульные импорты, неизменяемое состояние, конфигурация через расширения. ★ 3 579звёзд репо clerk Правило для Cursor задаёт жёсткие требования к аутентификации Clerk: PKCE, серверные проверки, короткие токены. Пригодится, когда в проекте уже есть Clerk и нужен порядок в безопасности. ★ 3 579звёзд репо chakra-ui Правило для Cursor задаёт, как писать интерфейсы на Chakra UI v2: тема через токены, варианты компонентов через рецепты, стилевые пропсы вместо CSS. ★ 3 579звёзд репо bottle Правило для Cursor задаёт структуру Bottle-проекта: модули вместо одного app.py, конфиг через app.config, валидация Pydantic. Пригодится, если пишете бэкенд на Bottle. ★ 3 579звёзд репо

Спонсоры проекта

Компании, которые помогают держать аналитику открытой